ppt - 建國科技大學

Download Report

Transcript ppt - 建國科技大學

經濟部工業局
Android智慧型手機程式設計實務應用班
Android資料庫處理
建國科技大學 資管系
饒瑞佶
2012/4
Android資料庫-SQLite
• 資料庫
– SQLite
– 檔案式資料庫
– 適合嵌入式系統,不需要額外安裝系統
– OPEN SOURCE資料庫
– SQL指令與一般DBMS大同小異,但有些微差
異
SQLite
Android
結構1
資料
class DatabaseHelper extends
SQLiteOpenHelper
結構2
SQL指令
資料
adb shell + sqlite3+SQL指令
SQLite管理
adb shell + sqlite3
SQLite操作-adb shell
• 沒有AVD或是手機
沒有連線的device
SQLite操作-adb shell
• 先用android list avd 看可以用的AVD
可用的AVD
SQLite操作-adb shell
• 再使用emulator –avd <AVD名稱> 啟動一個AVD
• 例如:emulator –avd my_avd
啟動中的my_avd
SQLite操作-adb shell
• my_avd模擬器
SQLite操作-adb shell
• 再次執行adb shell,就可以看到#提示符號
#提示符號
SQLite操作-adb shell
• 建議進入sdcard內建立目錄存放資料庫
進入sdcard
在sdcard內建立mydb目錄
進入mydb目錄
SQLite操作-adb shell
• 請在#提示符號後輸入sqlite3 <資料庫名稱>
• 例如sqlite3 db1
• 如果資料庫不存在會自動建立,可以看到
sqlite>提示符號
sqlite>提示符號
SQLite操作-adb shell
• 離開是.quit (注意有一個.)
• 現在可以開始操作db1資料庫
• 使用SQL指令進行操作,包括:
建立欄位與資料表(結構部分)
建立資料(資料部分)
維護資料(資料部分)
SQLite結構相關SQL指令
不分大小寫
SQL指令-結構操作
• create table:建立資料表
• 藍色是要填資料的部分,其它是固定語法
• 所有SQL指令都要以;結束
create table資料表名稱 (
欄位1 資料型態,
欄位2 資料型態,
….
);
create table member(
id char(20) not null,
name char(20) not null,
pwd char(20) not null,
age int,
PRIMARY KEY(id)
);
SQL指令-結構操作
• .tables:可以查看目前資料庫內存在的資料表
• .help:可以看sqlite3所有指令
沒有任何資料表
SQL指令-結構操作
• create table:建立資料表
member資料表已經被建立
SQL指令-結構操作
• .schema:查看資料表結構
member資料表結構
SQL指令-結構操作
• alter table:更改資料表結構
增加欄位
alter table資料表名稱 add 欄位1 資料型態;
更改資料表名稱
alter table資料表名稱 rename to 新資料表名稱;
• drop table:刪除資料表
drop table資料表名稱;
SQLite資料相關SQL指令
SQL指令-資料操作
• insert:新增資料
所有資料都要加上單引號
insert into 資料表名稱 (欄位1,欄位2…) values (‘資料1’,’資料2’…);
已在member資料表中新增一筆資料
SQL指令-資料操作
• Select:篩選資料
select 欄位s from資料表名稱 where 條件;
加入where條件
SQL指令-資料操作
• update:更新資料
update 資料表名稱 set 欄位=‘新值’… where 條件;
姓名改成大寶
SQL指令-資料操作
• delete:刪除資料
Delete from 資料表名稱 where 條件;
先新增一筆資料
刪除剛新增的資料
SQL指令-結構操作
• SQLite沒有刪除欄位的指令,例如
ALTER TABLE DROP COLUMN
• 那怎麼辦?
SQL指令-結構操作
新增一個備份資料庫member_backup
將資料從member搬到member_backup
刪除member
再新增一個member,此時不要含要刪
掉的欄位
再把資料從member_backup搬到member
刪除member_backup
完成
更多SQLite SQL指令
• http://www.newobjects.com/pages/ndl/SQLit
e3/sql.htm#ALTER TABLE
SQLite+Android
By SQLiteOpenHelper
SQLite+Android
• 建立新專案
-HelloDB
Android+SQLite使用方式
• 引用class SQLiteOpenHelper
• 建立SQLiteOpenHelper 物件
• 透過SQLiteOpenHelper 物件建立
database物件
• 透過database物件存取資料
記得要開android.permission.WRITE_EXTERNAL_STORAGE
SQLiteOpenHelper運作架構
class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
只有在資料庫不存在時
super(context, "/sdcard/db2.db", null, 1);
才執行
}
@Override
只有在DatabaseHelper
public void onCreate(SQLiteDatabase db) {
此建構子有執行時才執
db.execSQL(DATABASE_CREATE_TABLE); //新增資料表
行
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldV, int newV)
{
資料庫版本有更新時才
}
執行
}
SQLite+Android
• 首先,在主程式中加入SQLiteOpenHelper結構
必要的class
建立db2.db資料庫
資料庫第一次建立時會執行onCreate
資料庫異動版本時會執行onUpgrade
SQLite+Android
• SQLiteOpenHelper結構
// SQLite資料庫使用必要class -----------------------String DATABASE_TABLE = "member";
String DATABASE_CREATE_TABLE = "create table " + DATABASE_TABLE + "(_id char(20),
name, pwd, age, primary key(_id));";
class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, "/sdcard/db2.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
}
}
SQLite+Android
• 從class HelloDB呼叫DatabaseHelper建立資
料庫
建立DatabaseHelper物件
呼叫建立db2.db資料庫
SQLite+Android
• 資料庫被建立在data/data/com.android.hellodb
SQLite+Android
• 資料庫被建立在data/data/com.android.hellodb
SQLite+Android
• 有資料庫後,下一步要建立資料表與資料
新增資料
定義資料表結構
建立資料表
SQLite+Android
• 建立資料表schema
String DATABASE_TABLE = "member";
String DATABASE_CREATE_TABLE = "create table " + DATABASE_TABLE + "(_id char(20),
name, pwd, age, primary key(_id));";
class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, "/sdcard/db2.db", null, 1);
建立資料表結構
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE_TABLE); //新增資料表
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
}
}
• 建立資料
String cmd="insert into " + DATABASE_TABLE + " (_id,name,pwd,age)
values ('c123','小黑','ccc',12)";
db.execSQL(cmd);
SQLite+Android
• 為何會錯誤?
跟執行流程有關!
SQLite+Android
• 幾點注意!
1.下面這段只有在資料庫第一次被建立時才會進行,所以如
果資料庫已經存在,那就不會建立資料表,當然也就不能
寫入資料
上張投影片的錯誤就是因為我們已經先建立db2.db,因此再
次執行程式時,並不會建立資料表,導致下面程式出錯
SQLite+Android
• 正常執行結果
資料庫
資料表
資料
中文資料有亂碼
到此為止,同樣的程式再執行一
次會出現錯誤,WHY?
SQLite+Android
• 最後,可以進行資料查詢
再新增一筆資料(小黑)
SQL查詢指令
資料移動到第一筆
顯示資料
String cmd_select="select * from " + DATABASE_TABLE;
Cursor c=db.rawQuery(cmd_select, null);
c.moveToNext();
String data="";
For(int i=1;i<=c.getCount();i++){
for(int j=1;j<=c.getColumnCount();j++){
data +=c.getString(j-1);
}
data +="\n";
c.moveToNext();
}
new AlertDialog.Builder(HelloDB.this)
.setTitle("data")
.setMessage(data)
.setPositiveButton("確認",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
})
.show();
SQLite+Android
• 實際顯示沒有亂碼
小練習
• 使用上述課程member資料表
• 設計一個登入畫面,可以讓使用者輸入帳
號與密碼
• 輸入完成後按下「確認」按鈕後,連回資
料庫內的member 資料表進行確認(id與pwd
欄位)
• 輸入正確者跳至下一個頁面(自訂),錯誤者
請跳出訊息提示框
透過ListView顯示資料庫資料
透過ListView顯示資料
整個版面都用ListActivity
改成ListActivity
刪除
透過ListView顯示資料
ArrayAdapter
陣列資料
透過ListView顯示資料
陣列資料
private static final String[] mStrings = new String[] {
"大餅包小餅", "蚵仔煎", "東山鴨頭", "臭豆腐", "潤餅",
"豆花", "青蛙下蛋","豬血糕", "大腸包小腸", "鹹水雞",
"烤香腸","車輪餅","珍珠奶茶","鹹酥雞","大熱狗",
"炸雞排","山豬肉","花生冰","剉冰","水果冰",
"包心粉圓","排骨酥","沙茶魷魚","章魚燒","度小月",
"aaa","abc","bbb","bcd","123"
};
透過ListView顯示資料
選了怎麼不會勾選?
透過ListView顯示資料
加入:
ListView lv = this.getListView();
lv.setChoiceMode( ListView.CHOICE_MODE_SINGLE );
修改:android.R.layout.simple_list_item_checked
ListView勾選效果
透過ListView顯示資料
偵測選擇資料
Object o=this.getListAdapter().getItem(position);
String keyword=o.toString();
Toast.makeText(HelloDB.this, "choose:" + keyword,
Toast.LENGTH_SHORT).show();
透過ListView顯示資資料
透過ListView顯示資料
• 假設是在Activity中除了ListView之
外,還要放入其他的組件時,這時
候就需要在Activity中加入一個
ListView物件,利用這個組件的
setAdapter來連接Adapter
透過ListView顯示資料
main.xml版面
ListView物件的id
透過ListView顯示資料
不改
陣列資料
透過ListView顯示資料
偵測選擇資料
如果是顯示兩個欄位以上資料
Cursor c = (Cursor) arg0.getItemAtPosition(position);
String tableValue = c.getString(0);
透過ListView顯示資料
• ArrayAdapter中有一個android定義好的內建list樣式 “android.R.layout.simple_list_item_1”,其它樣式如下所列:
–
–
–
–
–
android.R.layout.simple_list_item_1:一行text
android.R.layout.simple_list_item_2:一行text較大,一行text較小
android.R.layout.simple_list_item_single_choice:單選
android.R.layout.simple_list_item_multiple_choice:多選按鈕
android.R.layout.simple_list_item_checked:勾選盒
• 第1個剛剛有用了,事實上第3,4,5個也是直接換上去就可以
看到了。
• 第2個android.R.layout.simple_list_item_2就比較麻煩,原因是
ArrayAdapter並不支援傳入兩個字串參數值,所以要改用
SimpleAdapter,而且傳入的數值型態要改為ArrayList才可以
透過ListView顯示資料-
SimpleAdapter
ArrayList
SimpleAdapter
透過ListView顯示資料-
SimpleAdapter
陣列資料
透過ListView顯示資料-
SimpleAdapter
private static final String[] mPlaces = new String[] {
"台北市", "新北市", "台南市", "高雄市", "苗粟縣",
"台北市", "新北市", "台南市", "高雄市", "苗粟縣",
"台北市", "新北市", "台南市", "高雄市", "苗粟縣",
"台北市", "新北市", "台南市", "高雄市", "苗粟縣",
"台北市", "新北市", "台南市", "高雄市", "苗粟縣",
"台北市", "新北市", "789", "cde", "abc"
};
private static final String[] mFoods = new String[] {
"大餅包小餅", "蚵仔煎", "東山鴨頭", "臭豆腐", "潤餅",
"豆花", "青蛙下蛋","豬血糕", "大腸包小腸", "鹹水雞",
"烤香腸","車輪餅","珍珠奶茶","鹹酥雞","大熱狗",
"炸雞排","山豬肉","花生冰","剉冰","水果冰",
"包心粉圓","排骨酥","沙茶魷魚","章魚燒","度小月",
"aaa","abc","bbb","bcd","123"
};
陣列資料
透過ListView顯示資料-
SimpleAdapter
透過ListView顯示資料-
SimpleAdapter
偵測選擇資料
偵測選擇資料
透過ListView顯示資料-自訂版面
• 如果不要用android內建的simple_list_item_2,
改用自己定義的樣式,要怎麼作呢?像上面
的範例,再加上一個評分的字串在地點的旁
邊。
• 首先先製作一個專用的layout,取名為
mylistview.xml。
透過ListView顯示資料-自訂版面
mylistview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent" android:layout_width="fill_parent"
android:orientation="vertical">
<TextView android:text="TextView" android:id="@+id/textView1"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="6dip" android:layout_marginTop="6dip"
android:textAppearance="?android:attr/textAppearanceLarge"> </TextView>
<LinearLayout android:layout_height="wrap_content"
android:layout_width="wrap_content" android:id="@+id/linearLayout1"
android:orientation="horizontal">
<TextView android:id=“@+id/textView2” android:text=“TextView”
android:layout_height=“wrap_content” android:layout_width=“wrap_content”
android:textAppearance=“?android:attr/textAppearanceSmall”> </TextView>
<TextView android:text="TextView" android:id="@+id/textView3"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_marginLeft="6dip"> </TextView>
</LinearLayout>
</LinearLayout>
透過ListView顯示資料-自訂版面
第二個LinearLayout要設定成horizontal
透過ListView顯示資料-自訂版面
三個改變的地方
透過ListView顯示資料-自訂版面
陣列資料
private static final String[] mRatings = new String[] {
"1", "2", "4", "3", "5",
"3", "2", "4", "1", "1",
"3", "3", "3", "1", "3",
"3", "5", "2", "5", "2",
"5", "3", "1", "2", "2",
"2", "3", "1", "2", "3"
};
透過ListView顯示資料-自訂版面
透過ListView顯示資料-加入圖片
• 最後加入圖 片到ListView吧
• 圖片需要先放到res/drawable-xxxx目錄中(這
裡放到res/drawable-hdpi中)
• 因為HashMap的value部份需要用到圖片,是
一個int的型態,所以HashMap的value部份需
要改為Object,才能容得下int和string的類型。
• 修改mylistview.xml,加上圖片在標題的左邊
透過ListView顯示資料-加入圖片
再加入LinearLayout與ImageView
LinearLayout要設定成horizontal
透過ListView顯示資料-加入圖片
三個修改的地方
透過ListView顯示資料-加入圖片
陣列資料
private static final int[] mPics=new int[]{
R.drawable.pic1,R.drawable.pic2,R.drawable.pic3, R.drawable.pic4,R.drawable.pic5,
R.drawable.pic1,R.drawable.pic2,R.drawable.pic3, R.drawable.pic4,R.drawable.pic5,
R.drawable.pic1,R.drawable.pic2,R.drawable.pic3, R.drawable.pic4,R.drawable.pic5,
R.drawable.pic1,R.drawable.pic2,R.drawable.pic3, R.drawable.pic4,R.drawable.pic5,
R.drawable.pic1,R.drawable.pic2,R.drawable.pic3, R.drawable.pic4,R.drawable.pic5,
R.drawable.pic1,R.drawable.pic2,R.drawable.pic3, R.drawable.pic4,R.drawable.pic5
};
透過ListView顯示資料-加入圖片
陣列資料
ListView + 資料庫
透過ListView顯示資料庫資料
原程式,用Toast顯示資料
用ListView取代這裡
透過ListView顯示資料庫資料
• 注意資料表內需要有個_id的主鍵欄位
• 注意使用ListView顯示資料,需要修改extends Activity變成
ListActivity
• 需刪掉setContentView(R.layout.main);
透過ListView顯示資料庫資料
String[] from = new String[]{"name","pwd","_id"}; //一定要有_id才行
int[] to = new int[]{android.R.id.text1};
Cursor c1 = db.query("member", from, null, null, null, null, "_id ASC");
startManagingCursor(c1);
//多資料欄位
ListAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_2,c1,
new String[] {"name","pwd"},
new int[] {android.R.id.text1, android.R.id.text2 });
setListAdapter(adapter);
透過ListView顯示資料庫資料
透過ListView顯示資料庫資料
• 兩列字體大小不同
改這個屬性
透過ListView顯示資料庫資料
透過ListView顯示資料庫資料
直接顯示資料
偵測選擇資料
透過ListView顯示資料庫資料
偵測選擇資料
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
// Get the item that was clicked
//直接顯示資料
Cursor cursor = (Cursor)this.getListAdapter().getItem(position);
String keyword =cursor.getString(cursor.getColumnIndex("_id"));
Toast.makeText(this, "您選擇了: " + keyword, Toast.LENGTH_LONG)
.show();
}
透過ListView顯示資料庫資料
透過另一頁(DataDetails)顯示資料
注意要加入<activity android:name="DataDetails"></activity>
傳送資料
透過ListView顯示資料庫資料
透過另一頁(DataDetails)顯示資料
注意要加入<activity android:name="DataDetails"></activity>
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
// Get the item that was clicked
//* 跳頁顯示資料
Intent intent = new Intent(this, Page2.class);
Cursor cursor = (Cursor)this.getListAdapter().getItem(position);
intent.putExtra("EMPLOYEE_ID", cursor.getInt(cursor.getColumnIndex("_id")));
startActivity(intent);
}
透過ListView顯示資料庫資料
DataDetails.java
接收資料
修改
• 加入版面 main.xml
修改 I
修改 II
dbHelper = new DatabaseHelper(this);
db = dbHelper.getWritableDatabase();
tv1=(EditText)findViewById(R.id.editText1);
tv2=(EditText)findViewById(R.id.editText2);
tv3=(EditText)findViewById(R.id.editText3);
bt1=(Button)findViewById(R.id.button1);
修改
mID = this.getIntent().getExtras().getString("EMPLOYEE_ID");
employeeId = getIntent().getIntExtra("EMPLOYEE_ID", 0);
Toast.makeText(DataDetails.this, mID, Toast.LENGTH_LONG).show();
// 查詢資料
String cmd_select="select * from member where _id='" + mID + "';";
//Toast.makeText(DataDetails.this, cmd_select, Toast.LENGTH_LONG).show();
Cursor c = db.rawQuery(cmd_select, null); // 執行SQL指令,進行資料查詢
if(c.moveToFirst()){ //有資料才顯示
tv1.setText(c.getString(2)); //密碼
tv2.setText(c.getString(c.getColumnIndex("name"))); //姓名
tv3.setText(String.valueOf(c.getInt(c.getColumnIndex("age")))); //年齡
//c.close();
}else{
Toast.makeText(DataDetails.this, "找不到任何資料", Toast.LENGTH_LONG).show();
return;
}
/* 修改的Button */
bt1.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v)
{
String cmd="update member set name='" + tv2.getText() + "',pwd='" + tv1.getText() + "',age=" + tv3.getText() + " where _id='" + mID + "';";
db.execSQL(cmd); // 執行SQL指令,進行資料修改
Toast.makeText(DataDetails.this, "資料修改完成", Toast.LENGTH_LONG).show();
}
});
小迷思
• 應改成cursor.getString,否則將取不到值
• 接收端:
mID = this.getIntent().getExtras().getString("EMPLOYEE_ID");
刪除
/* 刪除的Button */
bt2.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v)
{
db.delete("member", "_id='" + mID + "'", null);
Toast.makeText(DataDetails.this, "資料刪除完成", Toast.LENGTH_LONG).show();
}
});
選單
• 使用手機硬體上的MENU鍵進行呼叫顯示
• 建立選單
– onCreateOptionsMenu
• 處理選項動作
– onOptionsItemSelected
選單基本結構
• 建立選單
– onCreateOptionsMenu
• 處理選項動作
– onOptionsItemSelected
加入選單選項
• 加入選項
– menu.add(0, 識別符號, 0, 顯示文字)
menu.add(0, MENU_ABOUT, 0, "關於BMI").setIcon(android.R.drawable.ic_menu_help);
menu.add(0, MENU_QUIT, 0, "結束
BMI").setIcon(android.R.drawable.ic_menu_close_clear_cancel);
選單
處理選項動作
• 處理選項動作
– onOptionsItemSelected
protected static final int MENU_ABOUT=Menu.FIRST;
protected static final int MENU_QUIT=Menu.FIRST+1;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
menu.add(0, MENU_ABOUT, 0, "關於BMI").setIcon(android.R.drawable.ic_menu_help);
menu.add(0, MENU_QUIT, 0, "結束BMI").setIcon(android.R.drawable.ic_menu_close_clear_cancel);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch(item.getItemId()){
case MENU_ABOUT:
break;
case MENU_QUIT:
break;
}
return super.onOptionsItemSelected(item);
}
新增
• 加入版面 main1.xml
新增
新增
dbHelper = new DatabaseHelper(this);
db = dbHelper.getWritableDatabase();
tv1=(EditText)findViewById(R.id.editText1);
tv2=(EditText)findViewById(R.id.editText2);
tv3=(EditText)findViewById(R.id.editText3);
tv4=(EditText)findViewById(R.id.editText4);
bt1=(Button)findViewById(R.id.button1);
/* 新增的Button */
bt1.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v)
{
String cmd="insert into member (_id, name, pwd, age) values ('" + tv1.getText() + "','" +
tv3.getText() + "','" + tv2.getText() + "'," + tv4.getText() + ");";
db.execSQL(cmd); // 執行SQL指令,進行資料新增
Toast.makeText(NewData.this, "資料新增完成", Toast.LENGTH_LONG).show();
Intent it1=new Intent();
it1.setClass(NewData.this, ListViewDB.class);
startActivity(it1);
NewData.this.finish();
}
});
小練習
• 在DataDetails上設計四個TextView物件
• 透過傳進來的EMPLOYEE_ID,再到資料庫
查詢詳細資料,將其顯示到上面四個
TextView中
透過WebService
連結外部DB