2012年2月21日 星期二

[TQC+ Android] 2-7 密碼鎖





設計密碼鎖 , 可自行設定密碼進行比對並更新 , 以下是程式碼。


package COM.TQC.GDD02;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class GDD02 extends Activity
{
 
 private String btnAdd = "Add";
 private String btnLogin = "Login";
 private String btnUpdate = "Update";
 private String FileName = "MY_PASSWORD";
 private FileInputStream fileInputStream = null; 
 private Button Button01;
 private EditText EditText01;
    
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        EditText01 = (EditText) findViewById(R.id.EditText01);
        Button01 = (Button) findViewById(R.id.Button01);
        
  try 
  {
   fileInputStream = openFileInput(FileName+".txt");
   //如果檔案不存在的話及會發生 FileNotFoundException 
   Button01.setText(btnLogin);
   
   fileInputStream.close();
   //已經確定檔案存在了, Closes this stream
   
  }catch (FileNotFoundException e)
  {
   // TODO Auto-generated catch block
   if(fileInputStream==null)
   {
    Button01.setText(btnAdd);
   }
   e.printStackTrace();
  } catch (IOException e)
  {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
  Button01.setOnClickListener(new View.OnClickListener()
  {
   @Override
   public void onClick(View arg0)
   {
    // TODO Auto-generated method stub
    if(Button01.getText().equals(btnAdd))
    {
     String text = ""+EditText01.getText();
     if(!text.equals(""))     
     {
      writeFile(text);      
      showToast("新增成功!請重新登入!"); 
      Button01.setText(btnLogin);
      EditText01.setText("");
     }
     else showToast("請輸入密碼!");      
    }
    else if(Button01.getText().equals(btnLogin))
    {
     String text = EditText01.getText().toString();
     
     if(text.equals(readFile()))
     {
      showToast("登入成功!");
      Button01.setText(btnUpdate);
      EditText01.setText("");
     }
     else
     {
      showToast("登入失敗!");
      EditText01.setText("");
     }     
    }
    else if(Button01.getText().equals(btnUpdate))
    {
     String text = ""+EditText01.getText();
     if(!text.equals(""))
     {
      writeFile(text);
      showToast("修改成功!請重新登入!");
      Button01.setText(btnLogin);
      EditText01.setText("");
     }
     else showToast("請輸入密碼!");     
    }
   }});
    }
    
    private void writeFile(String data)
    {   
  try
  {
   StringBuffer SBuffer = new StringBuffer(data);
   SBuffer.append('\n');
   //使用\n字元做為字串結尾
   FileOutputStream fos = openFileOutput(FileName+".txt", MODE_PRIVATE);
      fos.write(SBuffer.toString().getBytes());
      fos.close();
  }catch (FileNotFoundException e)
  {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
    }
    
    private String readFile()
    {    
     byte[] byteArray = new byte[1024];
     
  try
  {
   fileInputStream = this.openFileInput(FileName+".txt");
   fileInputStream.read(byteArray);
   fileInputStream.close();   
   
  } catch (FileNotFoundException e)
  {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } 
  String data = new String(byteArray);
  int index = data.indexOf("\n");
  return data.substring(0, index);
  /*
          由於byteArray長度為1024 , 將byteArray轉為字串後長度為1024
          因為字串補了空白字元所以長度才會到1024 , 所以當初在writeFile的時候
          才會在最後面補上\n作為結尾 , 現在取開頭到\n中間的部分做為回傳的字串 
   */
  
    }
    
    private void showToast(String message)
    {
     Toast t = Toast.makeText(this, message, Toast.LENGTH_LONG);
        t.show();
    }
}



以及簡單的 Layout檔


 
 
 












                                   
檔案儲存的地方在/data/data/PackageName/FileName.txt


P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



2012年2月18日 星期六

[TQC+ Android] 2-6 資料庫讀取 Use SQLiteDatabase, Custom BaseAdapter





可顯示資料庫內的資料於頁面 , 進行勾選後顯示於表單標題上 , 這題的重點在DataBase的存取 , 還有為了要讓嵌在List RowView內的CheckBox能引發事件 , 我們還要額外去Custom Adapter , 這個做法是去 extends Adapter , 程式碼如下。


package COM.TQC.GDD02;

import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;


public class GDD02 extends Activity
{
 SQLiteDatabase dataBase;
 Cursor cursor;
 Button exitButton , okButton;
 ListView listview;
 boolean[] CB = new boolean[3];
 
 String DATABASENAME = "MyDB";
 String TABLENAME = "MyTB";
 String FIELD01_ID = "_id";
 String FIELD02_NOTE = "note";
 String FIELD03_CREATED = "created";
 
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        dataBase =  this.openOrCreateDatabase(DATABASENAME, MODE_PRIVATE, null);
        
        try
        {
         cursor = dataBase.rawQuery("SELECT * FROM "+TABLENAME, null);
            
        }catch(SQLiteException SQLiteException)
        {
         //如果Table MyTB 不存在的話 , 新增Table , 新增資料
         String create = "create table if not exists "+TABLENAME+" ("+FIELD01_ID+" integer primary key autoincrement, "+FIELD02_NOTE+" varchar not null, "+FIELD03_CREATED+" INTEGER)";
            dataBase.execSQL(create);
                
            dataBase.execSQL("INSERT INTO "+TABLENAME+" ("+FIELD02_NOTE+","+FIELD03_CREATED+") values ('BOOK',10)");
            dataBase.execSQL("INSERT INTO "+TABLENAME+" ("+FIELD02_NOTE+","+FIELD03_CREATED+") values ('FOOD',10)");
            dataBase.execSQL("INSERT INTO "+TABLENAME+" ("+FIELD02_NOTE+","+FIELD03_CREATED+") values ('TOOL',10)");
            cursor = dataBase.rawQuery("SELECT * FROM "+TABLENAME, null);
            Log.d("Test", "SQLiteException");         
        }        
                  
        exitButton = (Button) this.findViewById(R.id.button2);
        exitButton.setOnClickListener(BOnClickListener);
        okButton = (Button) this.findViewById(R.id.button1);
        okButton.setOnClickListener(BOnClickListener);
        
        listview = (ListView) this.findViewById(R.id.listView1);
        myAdapter adapter = new myAdapter(cursor , CB);
        listview.setAdapter(adapter);       
    }
    
    public Button.OnClickListener BOnClickListener = new Button.OnClickListener()
    {
  @Override
  public void onClick(View v)
  {
   String temp="";
   int count=0;
   
      switch(v.getId())
      {
       case R.id.button1:
       for(int i=0;i<3;i++)
       {
        if(CB[i])
        {
         count++;
         cursor.moveToPosition(i);
         temp+=cursor.getString(1)+" ";
        }
       }
       if(count>0) GDD02.this.setTitle("{"+temp+"}");
       else GDD02.this.setTitle(R.string.app_name);
       break;
       
       case R.id.button2:
       finish();
       break;
      }
  }     
    };
    
    public class myAdapter extends BaseAdapter
    {        
     Cursor myAdapterCursor;       
     boolean[] myAdapterCB;     
     
     public myAdapter(Cursor c , boolean[] cb)
     {      
      myAdapterCB = cb;
      myAdapterCursor = c;
      myAdapterCursor.moveToFirst();
     }
         
        public View getView(final int position, View convertView, ViewGroup parent)
        {
            View rowview = convertView;
           
            if (rowview == null)
            {
                    LayoutInflater inflater = getLayoutInflater();
                    rowview = inflater.inflate(R.layout.list, parent, false);
                    //為了要把xml所描述的Layout轉變為View , 也就是我們要的rowview
                    //所以必須使用LayoutInflater來轉化 , 而要取得LayoutInflater的Instance方式還包括
                    //LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    //接著再使用inflate (int resource, ViewGroup root, boolean attachToRoot)
                    //傳回我們要的rowview
            }
            
            TextView notes = (TextView) rowview.findViewById(R.id.textView1);
            
            myAdapterCursor.moveToPosition(position);
            notes.setText(myAdapterCursor.getString(1));
            
            CheckBox checkBox = (CheckBox) rowview.findViewById(R.id.checkBox1);
            checkBox.setChecked(false);
            
             /*
         每個list rowview都有擺放一個CheckBox,為了當我們按下CheckBox的時候要做出
         事件反應 , 所以針對每個rowview上的CheckBox我們都將他設定 onClick(View arg0)的事件宣告
             */
            
            checkBox.setOnClickListener(new CheckBox.OnClickListener()
            {             
             @Override
    public void onClick(View arg0)
    {                           
              if(((CheckBox) arg0).isChecked()) myAdapterCB[position]= true;
     else myAdapterCB[position] = false;              
    }             
            });
            return rowview;
        }

  @Override
  public int getCount()
  {
   // TODO Auto-generated method stub   
   return myAdapterCursor.getCount();
  }

  @Override
  public Object getItem(int position) {
   // TODO Auto-generated method stub
    myAdapterCursor.moveToPosition(position);
    return myAdapterCursor.getString(1);
  }

  @Override
  public long getItemId(int position)
  {
   // TODO Auto-generated method stub
   myAdapterCursor.moveToPosition(position);
   return myAdapterCursor.getLong(0);
  }
     }

 @Override
 protected void onDestroy()
 {
  // TODO Auto-generated method stub
  
  if(dataBase.isOpen()) dataBase.close();
  
  super.onDestroy();
 }
    
}



再來是List RowView的 Layout檔

    
    




接著是main.xml檔



    
    
    










P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



2012年2月15日 星期三

[NBA] Linsanity 關於林書豪 About Jeremy Lin (HD Game highlights update to 3/03)





近日台灣甚至美國都捲起了一股林氏炫風 , 這是一位台裔哈佛小子林書豪 Jeremy Lin , 他在NBA打拚的故事 , 歷經未在選秀會被選上 , 然後被勇士隊簽下但是球季結束就被解約 , 輾轉到了火箭隊又被揮棄 , 在球隊的角色是替補中的替補 , 沒想到尼克隊簽下了他 , 但是尼克隊( New York Knicks )並不是馬上就重用他 , 一直到了總教練 Mike D'Antoni , 因為球隊戰績太差準備要丟了飯碗 , 在2 / 5號那天尼克對上籃網的時候 , Mike D'Antoni啟用了林書豪 , 林書豪那場以替補出賽卻打了35分鐘拿下25分7助功的成績 , 那晚他優異的表現也帶領尼克隊擊敗了籃網 , 幾次的關鍵得分更是拯救了球隊。

截至今天為止(2012/02/15) , 林書豪不僅帶領球隊取得六連勝 , 而且還創下前五場先發共得136分的紀錄為NBA歷史上得第一人打破了Shaquille O'Neal所保持的129分 , 真是不簡單 , 在這天時地利人和的情況下 , 林書豪掀起了林氏炫風 , Linsanity (林氏狂熱) , 就像童話故事灰姑娘。

在他剛加入NBA的時候雖然沒在選秀會上被選中 , 但是還是有和勇士隊簽下了合約 , 在對上湖人的比賽我看到他上場了 , 那時候對他的感覺是一個防守很積極很有活力的球員 , 一上場就有抄截 , 但是他那時還是替補中的替補 , 所以上場的時間很少 , 攻擊和組織球隊的部分他的參與程度很少 , 現在到了尼克隊發光發熱 , 除了他本身的實力和努力之外 , 有時候機運也是造就了一個人能不能發光發熱的因素。

剛好 Mike D'Antoni 的進攻戰術著重在後衛的發動 , 而林書豪的求烽和打球的觀念相當適合教練的進攻體系 , 如魚得水的他大量的取分 , 也透過組織和傳球讓隊友發揮得更出色 , 他也因為這優異的表現獲選為東區單週最佳球員的殊榮。


以下是一些林書豪相關的整理和花絮



    早在一週前,人們就已經通過各種渠道知道了林書豪是躺在其哥哥的一張沙
    發上睡覺的,而且也睡過其隊友蘭德里-菲爾茲(Landry Fields)的沙發。菲爾茲就在早些時候通過推特的方式,秀出這張讓很多人都想看一眼的沙發。這張「沙發」便成為了林書豪曾經困苦時期的見證,也被賦予了神奇的色彩,因為,正是睡過這張沙發,小林才一步登天,瞬間找到了靈感,同時也找到了通往成功的道路。菲爾茲在推特中也開玩笑地聲稱:「女士們和先生們,這就是林書豪所睡過的那張沙發,現在可以開始出價了。 (轉自PTT_NBA 板友 rfr (Mali)的文章)





在菲爾茲公佈這張照片僅僅三個小時以後,瀏覽數就達到了26000,簡直堪稱
是本年度最熱的沙發。



林書豪的HD Games Highlight




2012/02/05 New York Knicks vs New Jersey Nets Jeremy Lin 25 points Highlights
第一場 尼克對籃網 , 他爆發掘起的一場 , 從這場以後他開始先發 , 也帶著尼克走向連勝之旅~~








2012/02/07 New York Knicks vs Utah Jazz Jeremy Lin 28 points Highlights
第二場尼克對爵士 , 這場林書豪打滿下半場有點體力不濟








2012/02/08 New York Knicks vs Washington Wizards Jeremy Lin 23 points Highlights 
第三場尼克對巫師 , 這場的焦點在和去年選秀狀元John wall的對決









2012/02/11 New York Knicks vs Los Angeles Lakers Jeremy Lin 38 points Highlights
第四場尼克對湖人 , 這場的焦點是和Kobe的對決 , 雖然兩人打的位置不同但是媒體還是相當得關注兩人的互動 , 這場林書豪帶領尼克擊敗湖人 , 賽後Kobe對林書豪不禁印象深刻還對讚賞了一番。









2012/02/11 New York Knicks vs Minnesota Timberwolves Jeremy Lin 20 points Highlights
第五場尼克對灰狼 , 這場是和西班牙金童Ricky Rubio的對決 , 下半場灰狼對林書豪採取包夾 , 造成他的命中率下降 , 所幸最後靠著罰球險勝了灰狼。









Lin plays hero for Knicks 2012 02 15 New York Knicks vs Toronto Raptors 
第六場比賽尼克對暴龍 , 堪稱林書豪最精采的一場 , 在最後讀秒階段靠著三分球逆轉了暴龍 , 這場尼克一路落後靠著第四節林書豪帶起的反攻 , 最後90-87擊敗了爆龍 , 林書豪也因為這場比賽打破了歐尼爾的記錄









林書豪真是有英雄命 , 最後致勝的三分球短片 , 關於這個play有個小插曲 , 賽後林書豪表示他轉過頭向教練要求要隊友清開空間給他單打 , 真是心臟大顆的男人 , 最後也靠著這顆三分球擊敗了暴龍啦!!!!!








第七場尼克對國王 , 這場林書豪以策應分球為主 , 也創下生涯新高的13次的助功 , 尼克在第三節結束就以大筆分領先國王 , 所以第四節林書豪沒有上場





2/19尼克對上去年總冠軍小牛 , 林書豪和Jason Kidd的對決受到矚目。







這場對上騎士, 對方控球後衛是今年的選秀狀元, Kyrie Iriving 也是今年新秀對抗賽的MVP




下面分享林書豪和他的好隊友Landry Fields的招牌打氣方式 , 有人說這是"書呆子打氣" , 因為兩人的學歷都相當的高 , 林書豪是哈佛經濟系畢業的 , Landry Fields則是史丹佛大學畢業的 , 堪稱NBA最聰明的後場組合了~












林書豪教你如何進入哈佛 , 搞笑的KUSO影片

















林書豪的狂熱也席捲NBA球員 , 老鷹隊在和魔術隊比賽完畢之後 , 老鷹隊的球員關注著林書豪的表現 , 並在更衣室官看林書豪對灰狼隊的比賽。其他球隊的主力球員,對都關心林書豪的戰況,當他投進今天對暴龍隊的絕殺時,湖人休息室大爆發,World Peace還跑出來大喊「Linsanity」!繼日前對明尼蘇達灰狼用罰球逆轉勝之後,林書豪又連續拿下6分,包括最後一記三分球,把尼克從鬼門關里拉了回來。

除了世界和平之外,許多頂級球星都對這球有極高評價,洛杉磯快艇隊「CP3」保羅
(Chris Paul)在推特上說,「我正在看尼克對暴龍的比賽,林書豪那球真是太巨大啦!」
從尼克隊轉至金州勇士隊的大衛李(David Lee)說,「林書豪那一射棒極了。」


2012年2月12日 星期日

[TQC+ Android] 2-5 圖檔讀取




分別讀取存在/res/drawable資料夾和手機檔案系統 /data/data/COM.TQC.GDD02/png001.PNG 的圖檔後 , 顯示在畫面上 , /res/drawable資料夾內的png002.PNG檔用 setImageResource(R.drawable.png002) 即可 , 而/png001.PNG由於存在手機系統內的資料夾所以使用setImageDrawable(Drawable.createFromPath(filePath)讀取 , 以下是如何載入檔案至/data/data/COM.TQC.GDD02/的方法和程式碼。






請注意紅色框框的部分 , 這是在DDMS視窗下操作的 , 將檔案匯入你程式packageName資料夾裡。


package COM.TQC.GDD02;


import java.io.File;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class GDD02 extends Activity
{
  
  private ImageView mImageView;
  private Button mButton;
  private TextView mTextView;
  private String fileName="/data/data/COM.TQC.GDD02/png001.PNG";
  
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    
    setContentView(R.layout.main);
    
    mImageView = (ImageView)findViewById(R.id.mImageView);    
    mImageView.setImageResource(R.drawable.png002);
    
    mTextView=(TextView)findViewById(R.id.mTextView);
    
    mButton = (Button)findViewById(R.id.mButton);
    mButton.setOnClickListener(new Button.OnClickListener()
    {
      public void onClick(View v)
      {
     
        File f = new File(fileName);   
        if(f.exists()) //檢查檔案是否存在
        { 
         /* 產生Bitmap物件,並放入mImageView中 */
            Drawable drawable = Drawable.createFromPath(fileName);
         mImageView.setImageDrawable(drawable);
         mTextView.setText(fileName);         
        } 
        else 
        {  
          mTextView.setText("檔案不存在"); 
        } 
      } 
    });
  }
}




再來是單純的Layout檔

    
    
    







P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



[TQC+ Android] 2-4 SQLite 與 MENU 作業 Use SQLiteDatabase , SQLiteOpenHelper , SimpleCursorAdapter





提示使用者按MENU鍵 , 畫面會顯示MENU供使用者新增修改和刪除所選取的List item , 並且我們繼承SQLiteOpenHelper這個類別並override 其中幾個method , 幫助我們管理database和Table的操作 , 以下為程式碼。


package COM.TQC.GDD02;

import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

public class GDD02 extends Activity
{
  private mySQLiteOpenHelper gaaSQLiteOpenHelper;
  private Cursor myCursor;
  private ListView myListView;
  private EditText myEditText;
  private int _id;
  protected final static int MENU_ADD = Menu.FIRST;
  protected final static int MENU_EDIT = Menu.FIRST + 1;
  protected final static int MENU_DELETE = Menu.FIRST + 2;

  @Override
  public boolean onOptionsItemSelected(MenuItem item)
  {
    super.onOptionsItemSelected(item);
    
    switch (item.getItemId())
    {
      case MENU_ADD:
        this.addTodo();
        break;
      case MENU_EDIT:
        this.editTodo();
        break;
      case MENU_DELETE:
        this.deleteTodo();
        break;
    }
    return true;
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu)
  {
    super.onCreateOptionsMenu(menu);
    
    menu.add(0, MENU_ADD, 1, R.string.strAddButton);
    menu.add(0, MENU_EDIT, 2, R.string.strEditButton);
    menu.add(0, MENU_DELETE, 3, R.string.strDeleteButton);
    
    return true;
  }

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    myListView = (ListView) this.findViewById(R.id.myListView);
    myEditText = (EditText) this.findViewById(R.id.myEditText);

    gaaSQLiteOpenHelper = new mySQLiteOpenHelper(this); 

    updateAdapter();
    
    myListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
    {
      public void onItemClick(AdapterView arg0, View arg1, int postion,
          long rowID)
      {        
        myCursor.moveToPosition(postion);        
        _id = myCursor.getInt(0); // 取出所選物件的rowID
        //_id = (int) rowID;  rowID is the row id of the item that was clicked.
        myEditText.setText(myCursor.getString(1));
        //Log.d("Test", "postion:"+postion+" rowID:"+rowID+" _id:"+_id);
      }
    });
  }

  private void addTodo()
  {   
   gaaSQLiteOpenHelper.insert(myEditText.getText().toString());
   updateAdapter();
   myEditText.setText("");    
  }

  private void editTodo()
  {  
   gaaSQLiteOpenHelper.update(_id, myEditText.getText().toString());
   updateAdapter();
   myEditText.setText(""); 
  }

  private void deleteTodo()
  {
   gaaSQLiteOpenHelper.delete(_id);
   updateAdapter();
   myEditText.setText(""); 
  }
  
  private void updateAdapter()
  {
   myCursor = gaaSQLiteOpenHelper.select();
   SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.list,
          myCursor, new String[]
          {mySQLiteOpenHelper.FIELD_TEXT }, new int[]
          {R.id.listTextView1});
   /*
           使用SimpleCursorAdapter將我們所要的資料顯示在ListView中
     myCursor為我們query的結果 , 他可能有許多row
           而我們只需要顯示其中 FIELD_TEXT欄位的資料
           並且每行row的資料使用 我們事先在R.layout.list中定義好的rowView來顯示
           而FIELD_TEXT這欄資料對應到listTextView1 所定義的方式呈現
    */
   myListView.setAdapter(adapter);
  }
}




接下來是我們繼承SQLiteOpenHelper的類別。

package COM.TQC.GDD02;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class mySQLiteOpenHelper extends SQLiteOpenHelper
{
  private final static String DATABASE_NAME = "todo_db";
  private final static int DATABASE_VERSION = 1;
  private final static String TABLE_NAME = "todo_table";
  public final static String FIELD_id = "_id";
  public final static String FIELD_TEXT = "todo_text";

  public mySQLiteOpenHelper(Context context)
  {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
  }

  @Override
  public void onCreate(SQLiteDatabase db)
  {    
    String sql = "CREATE TABLE " + TABLE_NAME + " (" + FIELD_id
        + " INTEGER primary key autoincrement, " + " " + FIELD_TEXT + " text)";
    db.execSQL(sql);    
  }

  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
  {
    String sql = "DROP TABLE IF EXISTS " + TABLE_NAME;
    db.execSQL(sql);
    onCreate(db);
  }

  public Cursor select()
  {
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, null);
    //query的結果顯示所有欄位的資料
    return cursor;
  }

  public long insert(String text)
  {
    SQLiteDatabase db = this.getWritableDatabase();
    db.execSQL("INSERT INTO "+TABLE_NAME+" ("+FIELD_TEXT+") values ('"+text+"')");
    Cursor cursor = db.rawQuery("SELECT "+FIELD_id+" FROM "+TABLE_NAME+" WHERE "+FIELD_TEXT+"='"+text+"';", null);
    //rawQuery(String) 為另一種query的方法 , string內容為一般的 SQL語法
    cursor.moveToLast();
    /*
                也許有很多筆結果 , 因為text可能重複 , 但是FIELD_id是不會重複的
                跳置最後一個可以保證是剛剛所Insert的物件
     */
    return  cursor.getInt(0);    
  }

  public void delete(int id)
  {
    SQLiteDatabase db = this.getWritableDatabase();
    
    String where = FIELD_id + " = ?";
    String[] whereValue = { Integer.toString(id) };
    
    db.delete(TABLE_NAME, where, whereValue);
    
    // 或者使用 db.execSQL("DELETE FROM "+TABLE_NAME+" WHERE "+FIELD_id+"="+id);    
  }

  public void update(int id, String text)
  {
    SQLiteDatabase db = this.getWritableDatabase();
    db.execSQL("UPDATE "+TABLE_NAME+" SET "+FIELD_TEXT+"='"+text+"' WHERE "+FIELD_id+"="+id);
  }
}




main.xml


  
    
  
  
  
     




再來是主程式GDD02.java中 , 在updateAdapter()時所用到的R.layout.list也就是 res/layout/list.xml


  
  






P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....

Google Analytics