Android Programming and Database IS04 組み込み 1
Android とデータベースの連結 1 データベースオープンヘルパー SQLite は データベースを1つのファイルで扱うので 指定のデータベースがないときは作成し あるときは 既存のファイルを開く という処理が必要です そういう一連の処理をしてくれるのが SQLiteOpenHelper クラスです これを継承して テーブル作成 初期うデータ挿入まで定義しておきます package jp.ac.neec.kmt.is04.takata; import android.content.context; import android.database.sqlite.sqlitedatabase; import android.database.sqlite.sqlitedatabase.cursorfactory; import android.database.sqlite.sqliteopenhelper; public class DBHelper extends SQLiteOpenHelper { public DBHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); // TODO Auto-generated constructor stub @Override public void oncreate(sqlitedatabase db) { // TODO Auto-generated method stub String sql = "create table planet_table (" + "id integer primary key autoincrement," + "name text," + "image text" + ")"; // テーブル作成 sql="insert into planet_table (name,image) values(' 水星 ','mercury.jpg')"; sql="insert into planet_table (name,image) values(' 金星 ','venus.jpg')"; sql="insert into planet_table (name,image) values(' 地球 ','earth.jpg')"; sql="insert into planet_table (name,image) values(' 火星 ','mars.jpg')"; sql="insert into planet_table (name,image) values(' 木星 ','jupiter.jpg')"; 2
sql="insert into planet_table (name,image) values(' 土星 ','saturn.jpg')"; @Override public void onupgrade(sqlitedatabase db, int oldversion, int newversion) { // TODO Auto-generated method stub 2 主プログラムからオープンヘルパーを呼び出してデータベースを使えるようにする Activity.java SQLiteDatabase db; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); DBHelper dbhelper = new DBHelper(this, "planet_db", null, 1); db = dbhelper.getwritabledatabase(); new DBHelper(this, "planet_db", null, 1); このクラス, データベース名, 特別なカーソルを使うか?, DB 番号 SQLiteOpenHelper 戻り値 SQLiteDatabase SQLiteDatabase メソッド getreadabledatabase() 読み込み専用でデータベースを開く getwritabledatabase() 書き込みもできるデータベースを開く 3 SQL を発行する Select 文のようにデータを読み出す SQL と delete 文や insert 文のようにデータベースに影響を与える SQL とで扱いが違います データの挿入や削除の場合 sql="insert into photo_table (name,title) values('mercury.jpg',' 水星 ')"; 3
データの読み出しの場合 Cursor cursor = null; sql = "select * from photo_table"; cursor = db.rawquery(sql, null); 4 データの読み出しデータを読み出した瞬間は 先頭のデータの前を指しています カーソル データ1 データ2 まず 先頭のデータを指すようにカーソルを移動します cursor.movetofirst(); カーソル データ 1 データ 2 カーソル移動のメソッド (Cursor クラス ) 戻り値メソッド boolean move(into offset) 現在のカーソル位置から相対値で移動する boolean movetofirst() 先頭位置に移動する boolean movetolast() 最後の位置に移動する boolean movetonext() 次の行に移動する boolean movetoposition(int position) 絶対値に移動する boolean movetoprevious() 前の行に移動するいずれも移動できなかったとき false となる 4
カーソル位置のデータを読み込む データの種類によってメソッドが異なります 引数に カラム位置を指定する ( 最初のカラムは 0) String name=cursor.getstring(1); 戻り値 メソッド double getdouble(int columnindex) int getint(int columnindex) long getlong(int columnindex) String getstring(int columnindex) その他のメソッド戻り値 int int int String int int boolean boolean boolean boolean boolean メソッド getcolumncount() カラム数を得る getcolumnindex(string columnname) カラム名からカラム番号を得る 指定の名前がないときは-1 が返る getcolumnindexorthrow(string columnname) カラム名からカラム番号を得る 指定の名前がないときは例外を投げる getcolumnname(int columnindex) カラム番号からカラム名を得る getcount() 総行数を返す getposition() 現在カーソルがある位置を求める isafterlast() 最後の行より後にカーソルがあるか? isbeforfirst() 最初の行より前にカーソルがあるか? isfirst() 先頭行にカーソルがあるか? islast() 最終行にカーソルがあるか? isnull(int columnindex) 指定のカラムが NULL か? 5
プログラム例データベースの最初のレコードを表示する Activity package jp.ac.neec.kmt.is04.takata; import java.io.file; import android.app.activity; import android.database.cursor; import android.database.sqlite.sqlitedatabase; import android.graphics.bitmap; import android.graphics.bitmapfactory; import android.os.bundle; import android.os.environment; import android.widget.imageview; import android.widget.textview; public class HelloDBActivity extends Activity { SQLiteDatabase db; Cursor cursor = null; 6
/** Called when the activity is first created. */ @Override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); DBHelper dbhelper = new DBHelper(this, "planet_db", null, 1); db = dbhelper.getwritabledatabase(); String sql = "select * from planet_table"; cursor = db.rawquery(sql, null); cursor.movetofirst(); String name=cursor.getstring(1); String image=cursor.getstring(2); System.out.println("name="+name); File dir = Environment.getExternalStorageDirectory(); dir = new File(dir, "Pictures"); String path = dir.getabsolutepath(); Bitmap bitmap = BitmapFactory.decodeFile(path+"/"+image); TextView textview = (TextView) this.findviewbyid(r.id.planet_name); ImageView imageview = (ImageView) this.findviewbyid(r.id.planet_image); textview.settext(name); imageview.setimagebitmap(bitmap); データベースの場所 :data/data/( パッケージ名 )/database/ この中のファイルを削除すると データベースは削除されます 7
データベースからリストを表示する SDカード上の画像ファイルをすべて表示するのではなく データベースの情報をもとに SDカード上の画像を選んで表示するプロジェクトです 1 レイアウトの作成プログラミング編 p43 を参考に メインのレイアウトと 1 行分のレイアウトを設計してください ( 画像を載せる場合には 画像のサイズが大きくなりすぎないように 最初からサイズを指定しておくとよい ) android:layout_width="85dp" android:layout_height="85dp" 2 データベースヘルパークラスの作成データベースを作成し 初期データをインサートしておく そのとき コマンドで SQL が正しいことを確認しておく 3 Activity からでデータベースヘルパーのインスタンス作成し データベースとの連携に問題がないことを実験しておく ( データベースプログラミング編 p3) これはあとでアダプタに移動します Activity.java SQLiteDatabase db; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); DBHelper dbhelper = new DBHelper(this, "planet_db", null, 1); db = dbhelper.getwritabledatabase(); 4 1 行分のデータを格納するクラスの作成プログラミング編 p44 を参考に ただし 画像がある場合でも データベースに格納されているのはファイル名なので String にしておくのがおすすめ ビットマップ化は 表示のときに行う 5 アダプタの作成プログラミング編 p45 を参考に ただし 読み込むのはSDカードではなく データベースになります Adapter // コンストラクタ public DataListAdapter(Context c) { // レイアウトとデータを統合させるおまじない 8
layoutinflater = (LayoutInflater) c.getsystemservice(context.layout_inflater_service); // 袋をインスタンス化 list = new ArrayList<LineData>(); // ここからデータベースから情報を取得する DBHelper dbhelper = new DBHelper(c, "planet_db", null, 1); db = dbhelper.getwritabledatabase(); String sql = "select * from planet_table"; cursor = db.rawquery(sql, null); cursor.movetofirst(); while(cursor.movetonext()){ //DBから全部読む int id = cursor.getint(0); String name=cursor.getstring(1); String image=cursor.getstring(2); System.out.println(id + " " + name + " " + image); LineData one = new LineData(id, name, image); list.add(one); getview で画像のファイル名からビットマップに変換します そのために コンストラクタで Path を取得しておくとよいでしょう getcount でデータの個数を返してください プログラミング編 p46 参照 6 Activity で表示しますプログラミング編 p47 参照 9
リストをタップして 次の画面に進む リストをタップして 詳細情報を表示するようにします 1 リストにイベントをつけますプログラム編 p49 2 第 2 画面を設計します プログラム編 p51~ 3 第 2 画面をマニフェストに登録しますプログラム編 p55~ 4 Intent を使って第 2 画面を呼び出しますプログラム編 p55 5 第 2 画面から戻るボタンでメイン画面に戻りますプログラム編 p58 6 リスト中の選ばれたデータを第 2 画面に送りますここでは データベース 1 行分のデータをまるごと第 2 画面に送ります そのためには オブジェクトがシリアライズ化できなければなりません 文字や数値だけからなるデータはシリアライズ化できます public class LineData implements Serializable { private static final long serialversionuid = 1L; private int id; //ID private String name; // 名前 private String image; // 画像ファイル名 10
Activity public void onitemclick(adapterview<?> parent, View view, int position, long id) { // TODO Auto-generated method stub LineData data = adapter.getitem(position); Intent intent = new Intent(this, SecondActivity.class); intent.putextra("data", adapter.getitem(position)); startactivityforresult(intent, 1); 7 第 2 画面でデータをうけとり 表示します第 2Activity protected void oncreate(bundle savedinstancestate) { // TODO Auto-generated method stub super.oncreate(savedinstancestate); setcontentview(r.layout.second); subtext = (TextView) this.findviewbyid(r.id.textsub); subimage = (ImageView) this.findviewbyid(r.id.imagesub); Intent intent = this.getintent(); LineData data = (LineData) intent.getserializableextra("data"); subtext.settext(subtext.gettext() + data.getname()); File dir = Environment.getExternalStorageDirectory(); dir = new File(dir, "Pictures"); String path = dir.getabsolutepath(); Bitmap bitmap = BitmapFactory.decodeFile(path+"/"+ data.getimage()); subimage.setimagebitmap(bitmap); 第 2 画面で新たにデータベースを参照することもできます 11
main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <ListView android:id="@+id/listmain" android:layout_height="match_parent" android:layout_width="match_parent" > </ListView> </LinearLayout> list_item.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/idarea" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/imagearea" android:layout_width="85dp" 12
android:layout_height="85dp" android:layout_gravity="center_vertical" /> <TextView android:id="@+id/namearea" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10dp" android:text="test" android:textsize="16sp" /> </LinearLayout> DBHelper package jp.ac.neec.kmt.is04.takata; import android.content.context; import android.database.sqlite.sqlitedatabase; import android.database.sqlite.sqlitedatabase.cursorfactory; import android.database.sqlite.sqliteopenhelper; public class DBHelper extends SQLiteOpenHelper { public DBHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); // TODO Auto-generated constructor stub @Override public void oncreate(sqlitedatabase db) { // TODO Auto-generated method stub String sql = "create table planet_table (" + "id integer primary key autoincrement," + "name text," + "image text" 13
+ ")"; // テーブル作成 sql="insert into planet_table (name,image) values(' 水星 ','mercury.jpg')"; sql="insert into planet_table (name,image) values(' 金星 ','venus.jpg')"; sql="insert into planet_table (name,image) values(' 地球 ','earth.jpg')"; sql="insert into planet_table (name,image) values(' 火星 ','mars.jpg')"; sql="insert into planet_table (name,image) values(' 木星 ','jupiter.jpg')"; sql="insert into planet_table (name,image) values(' 土星 ','saturn.jpg')"; @Override public void onupgrade(sqlitedatabase db, int oldversion, int newversion) { // TODO Auto-generated method stub LineData package jp.ac.neec.kmt.is04.takata; public class LineData implements Serializable { private static final long serialversionuid = 1L; private int id; //ID private String name; // 名前 private String image; // 画像ファイル名 // コンストラクタ public LineData(int id, String name, String image) { 14
this.id = id; this.name = name; this.image = image; // セッタ ゲッタ public int getid() { return id; public void setid(int id) { this.id = id; public String getname() { return name; public void setname(string name) { this.name = name; public String getimage() { return image; public void setimage(string image) { this.image = image; 15
DataListAdapter package jp.ac.neec.kmt.is04.takata; import java.io.file; import java.util.arraylist; import android.content.context; import android.database.cursor; import android.database.sqlite.sqlitedatabase; import android.graphics.bitmap; import android.graphics.bitmapfactory; import android.os.environment; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.widget.baseadapter; import android.widget.imageview; import android.widget.textview; public class DataListAdapter extends BaseAdapter { private ArrayList<LineData> list; private LayoutInflater layoutinflater = null; private SQLiteDatabase db; private Cursor cursor = null; private String path; // コンストラクタ public DataListAdapter(Context c) { // レイアウトとデータを統合させるおまじない layoutinflater = (LayoutInflater) c.getsystemservice(context.layout_inflater_service); // 袋をインスタンス化 list = new ArrayList<LineData>(); // ここからデータベースから情報を取得する 16
DBHelper dbhelper = new DBHelper(c, "planet_db", null, 1); db = dbhelper.getwritabledatabase(); String sql = "select * from planet_table"; cursor = db.rawquery(sql, null); cursor.movetofirst(); while(cursor.movetonext()){ int id = cursor.getint(0); String name=cursor.getstring(1); String image=cursor.getstring(2); System.out.println(id + " " + name + " " + image); LineData one = new LineData(id, name, image); list.add(one); File dir = Environment.getExternalStorageDirectory(); dir = new File(dir, "Pictures"); path = dir.getabsolutepath(); System.out.println("path="+path); // データの個数 @Override public int getcount() { // TODO Auto-generated method stub return list.size(); @Override public Object getitem(int arg0) { // TODO Auto-generated method stub return null; 17
@Override public long getitemid(int arg0) { // TODO Auto-generated method stub return 0; @Override public View getview(int position, View convertview, ViewGroup parent) { // TODO Auto-generated method stub convertview = layoutinflater.inflate(r.layout.list_item, null); TextView idview = (TextView) convertview.findviewbyid(r.id.idarea); ImageView imageview = (ImageView) convertview.findviewbyid(r.id.imagearea); TextView nameview = (TextView)convertView.findViewById(R.id.nameArea); idview.settext("" + list.get(position).getid()); Bitmap bitmap = BitmapFactory.decodeFile(path+"/"+list.get(position).getImage()); imageview.setimagebitmap(bitmap); imageview.setscaletype(imageview.scaletype.center_crop); nameview.settext(list.get(position).getname()); System.out.println("name="+list.get(position).getName()); return convertview; public ArrayList<LineData> getlist(){ return list; 18
Activity package jp.ac.neec.kmt.is04.takata; import android.app.activity; import android.database.sqlite.sqlitedatabase; import android.os.bundle; import android.widget.listview; public class HelloDBListActivity extends Activity { /** Called when the activity is first created. */ @Override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); DataListAdapter adapter = new DataListAdapter(this); ListView listview = (ListView) this.findviewbyid(r.id.listmain); listview.setadapter(adapter); listview.settextfilterenabled(true); @Override public void onitemclick(adapterview<?> parent, View view, int position, long id) { // TODO Auto-generated method stub LineData data = adapter.getitem(position); testtext.settext(data.getname()); Intent intent = new Intent(this, SecondActivity.class); intent.putextra("position", position); intent.putextra("data", adapter.getitem(position)); //intent.setaction(intent.action_view); startactivityforresult(intent, 1); 19
データベースの検索データベースは 必要なデータを必要なときに必要なだけ取り出せなければなりません そのための機能が検索です 検索して得られるのは 1 件だけとは限りません いろいろなケースを想定してアプリを設計しましょう 1 オープンヘルパーの作成テーブルを作成 初期データをインサートあらかじめコマンドを実行してSQL 文が正しいことを検証しておく public void oncreate(sqlitedatabase db) { // TODO Auto-generated method stub String sql = "create table town_table(" + "id integer primary key autoincrement," + "ken char(20) not null," + "town char(20)" +")"; // テーブル作成 sql = "insert into town_table (ken, town) values(' 東京 ', ' 蒲田 ')"; sql = "insert into town_table (ken, town) values(' 東京 ', ' 渋谷 ')"; sql = "insert into town_table (ken, town) values(' 東京 ', ' 新宿 ')"; 20
sql = "insert into town_table (ken, town) values(' 東京 ', ' 四谷 ')"; sql = "insert into town_table (ken, town) values(' 神奈川 ', ' 横浜 ')"; sql = "insert into town_table (ken, town) values(' 神奈川 ', ' 川崎 ')"; sql = "insert into town_table (ken, town) values(' 神奈川 ', ' 相模原 ')"; sql = "insert into town_table (ken, town) values(' 埼玉 ', ' 越谷 ')"; sql = "insert into town_table (ken, town) values(' 埼玉 ', ' 熊谷 ')"; sql = "insert into town_table (ken, town) values(' 千葉 ', ' 浦安 ')"; 2 ヘルパーの呼び出し Activity からヘルパーを呼び出して データベースを作成 DDMS でデータベースができていることを確認する data/data/< パッケージ名 >/< データベース名 > Activity public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); DBHelper dbhelper = new DBHelper(this, "town_db", null,1); db = dbhelper.getwritabledatabase(); // テスト TextView test1 = (TextView) this.findviewbyid(r.id.test_id); String sql = "select * from town_table"; Cursor cursor = db.rawquery(sql, null); test1.settext("" + cursor.getcount()); 21
3 データベース読み出しテストデータベースが入力されていることを確認するため 件数を調べて表示してみましょう TextView に ID をつけておきます public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); DBHelper dbhelper = new DBHelper(c, "town_db", null,1); db = dbhelper.getwritabledatabase(); String sql = "select * from town_table"; Cursor cursor = db.rawquery(sql, null); TextView textview = (TextView) this.findviewbyid(r.id.test_id); textview.settext("" + cursor.getcount()); 4 画面レイアウト検索を行うためのテキストエディタとボタン それに結果を表示するリストを作成しておきます main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id = "@+id/test_id" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <EditText 22
android:id="@+id/key_ed" android:layout_height="wrap_content" android:layout_width="0dp" android:layout_weight="3" android:text="@string/key_label" /> <Button android:id="@+id/go_bt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/go_label" android:onclick="onclickgo" /> </LinearLayout> <ListView android:layout_height="match_parent" android:layout_width="match_parent" android:id="@+id/result_id" > </ListView> </LinearLayout> リストの 1 行分の定義 list_item.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/text_ken" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <TextView android:id="@+id/text_town" android:layout_width="0dp" 23
android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> 5 データを受け取るクラスデータベースの 1 件分を受け取るクラスを作成 LineData.java 6 アダプタデータベースから読み込んでリストを作成 public DataListAdapter(Context c) { layoutflater = (LayoutInflater) c.getsystemservice(context.layout_inflater_service); list = new ArrayList<LineData>(); DBHelper dbhelper = new DBHelper(c, "town_db", null,1); db = dbhelper.getwritabledatabase(); String sql = "select * from town_table"; Cursor cursor = db.rawquery(sql, null); while(cursor.movetonext()){ int id = cursor.getint(0); String ken = cursor.getstring(1); String town = cursor.getstring(2); System.out.println(id + " " + ken + " " + town); LineData one = new LineData(id,ken, town); list.add(one); 24
7 ためしに全データ表示 Activity public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); DataListAdapter adapter = new DataListAdapter(this); ListView listview = (ListView) this.findviewbyid(r.id.result_id); listview.setadapter(adapter); 25
8 ボタンのイベントハンドラを記述 EditText からテキストを読み込んでおく これがキーワードになる Activity public void onclickgo(view view){ EditText ev = (EditText) this.findviewbyid(r.id.key_ed); String key = ev.gettext().tostring(); 9 アダプタにもう一つのコンストラクタ public DataListAdapter(Context c, String key) { layoutflater = (LayoutInflater) c.getsystemservice(context.layout_inflater_service); list = new ArrayList<LineData>(); DBHelper dbhelper = new DBHelper(c, "town_db", null,1); db = dbhelper.getwritabledatabase(); String sql = "select * from town_table where ken='" + key + "'"; Cursor cursor = db.rawquery(sql, null); while(cursor.movetonext()){ int id = cursor.getint(0); String ken = cursor.getstring(1); String town = cursor.getstring(2); System.out.println(id + " " + ken + " " + town); LineData one = new LineData(id,ken, town); list.add(one); 10 アダプタの呼び出し Activity public void onclickgo(view view){ EditText ev = (EditText) this.findviewbyid(r.id.key_ed); String key = ev.gettext().tostring(); DataListAdapter adapter = new DataListAdapter(this, key); ListView listview = (ListView) this.findviewbyid(r.id.result_id); listview.setadapter(adapter); 26
データベースの登録 データベースにデータを新規に登録します 1 まず 入力画面を作ります main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/test_tx" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <EditText android:id="@+id/ken_ed" 27
android:layout_height="wrap_content" android:layout_width="0dp" android:layout_weight="1" /> <EditText android:id="@+id/town_ed" android:layout_height="wrap_content" android:layout_width="0dp" android:layout_weight="1" /> <Button android:id="@+id/go_bt" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/go_label" android:onclick="onclickreg" /> </LinearLayout> </LinearLayout> 2 データベースヘルパーを作りますすでにできているデータベースを使うときは どうせ oncreate は動かないので 何も書かなくてOK 3 データベースと連結します Activity @Override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); DBHelper dbhelper = new DBHelper(this, "town_db", null, 1); db = dbhelper.getwritabledatabase(); 28
4 ボタンのイベント Activity public void OnClickReg(View view){ EditText kenarea = (EditText) this.findviewbyid(r.id.ken_ed); EditText townarea = (EditText) this.findviewbyid(r.id.town_ed); String ken = kenarea.gettext().tostring(); String town = townarea.gettext().tostring(); String sql = "insert into town_table (ken, town) values('" + ken + "','" + town + "')"; System.out.println(sql); // SQL を発行するまえに 正しいかどうか チェックしてください sql 文が log に表示されるので これを選んでファイルに保存するファイルを開いて コマンドプロンプトで実行してみる sqlite> insert into town_table (ken, town) values(' 東京 ',' 銀座 '); sqlite> select * from town_table; 1 東京 蒲田 2 東京 渋谷 3 東京 新宿 4 東京 四谷 5 神奈川 横浜 6 神奈川 川崎 7 神奈川 相模原 8 埼玉 越谷 9 埼玉 熊谷 10 千葉 浦安 11 東京 銀座 sqlite> 挿入されることを確認してから コメント文をはずして実行する 検索用アプリで確認する 29
銀座が追加されており 成功した 30
リストから個別へ リスト表示から 1 つ選んで個別詳細データを表示します セカンドアクティビティ側で あらためてデータベースを読み直します ID を指定して読み込みができるようにアダプタのコンストラクタを追加 // コンストラクタ public DataListAdapter(Context c) { String sql = "select * from planet_table"; dataset(c, sql); public DataListAdapter(Context c,int id) { String sql = "select * from planet_table where id="+id; dataset(c, sql); public void dataset(context c, String sql){ // レイアウトとデータを統合させるおまじない layoutinflater = (LayoutInflater) c.getsystemservice(context.layout_inflater_service); // 袋をインスタンス化 list = new ArrayList<LineData>(); // ここからデータベースから情報を取得する DBHelper dbhelper = new DBHelper(c, "planet_db", null, 1); 31
db = dbhelper.getwritabledatabase(); cursor = db.rawquery(sql, null); //cursor.movetofirst(); while(cursor.movetonext()){ int id = cursor.getint(0); String name=cursor.getstring(1); String image=cursor.getstring(2); System.out.println(id + " " + name + " " + image); LineData one = new LineData(id, name, image); list.add(one); File dir = Environment.getExternalStorageDirectory(); dir = new File(dir, "Pictures"); path = dir.getabsolutepath(); System.out.println("path="+path); セカンドアクティビティでアダプタを作り直して表示 protected void oncreate(bundle savedinstancestate) { // TODO Auto-generated method stub super.oncreate(savedinstancestate); setcontentview(r.layout.second); subtext = (TextView) this.findviewbyid(r.id.textsub); subimage = (ImageView) this.findviewbyid(r.id.imagesub); Intent intent = this.getintent(); int id = intent.getintextra("id", 0); subtext.settext("" + id); adapter = new DataListAdapter(this, id); int size = adapter.getcount(); LineData data = adapter.getitem(0); 32
subtext.settext(subtext.gettext() + data.getname()); dir = new File(dir, "Pictures"); String path = dir.getabsolutepath(); Bitmap bitmap = BitmapFactory.decodeFile(path+"/"+ data.getimage()); subimage.setimagebitmap(bitmap); 詳しい説明をファイルから読んでみよう ( とりあえずファイル固定 ) セカンドアクティビティ File dir = Environment.getExternalStorageDirectory(); String description = readfromfile("earth.txt"); TextView desarea = (TextView) this.findviewbyid(r.id.desriptionsub); desarea.settext(description); private String readfromfile(string filename){ String readstring = ""; String SDFile = android.os.environment.getexternalstoragedirectory().getpath() + "/Text/earth.txt"; File file = new File(SDFile); try{ FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis,"UTF-8"); BufferedReader br= new BufferedReader(isr); String s; while ((s = br.readline() )!= null){ readstring = readstring+s+" r n"; br.close(); isr.close(); fis.close(); catch(filenotfoundexception e){ e.printstacktrace(); 33
catch(unsupportedencodingexception e){ e.printstacktrace(); catch (IOException e) { e.printstacktrace(); return readstring; 34
CSV からデータベースに読み込み Excel で作成したデータを CSV で書き出して それを使ってデータベースに読み込みを行うと データベースのデータ作成が楽にできます Helper を作成します データベースがまだない場合には public void oncreate(sqlitedatabase db) { // TODO Auto-generated method stub ここでデータベースをCreateする Activity public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); // データベースに接続する DBHelper dbhelper = new DBHelper(this, "town_db", null,1); db = dbhelper.getwritabledatabase(); // ファイルに接続する String readstring=""; String SDFile = Environment.getExternalStorageDirectory().getPath() + "/Text/city.csv"; File file = new File(SDFile); try { // ストリームを確立する FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis,"UTF-8"); BufferedReader br= new BufferedReader(isr); String s; while ((s = br.readline() )!= null){ //1 行分の処理 String[] part = s.split(","); //, で分割する 35
//insert 文を組み立てる String sql = "insert into town_table (ken, town) values('"+part[0]+"', '"+part[1]+"')"; System.out.println(sql); readstring += sql + " r n"; //sql = "select * from town_table"; //db.rawquery(sql, null); br.close(); isr.close(); fis.close(); catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printstacktrace(); catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printstacktrace(); catch (IOException e) { // TODO Auto-generated catch block e.printstacktrace(); // 確認用にSQLを表示 TextView tv = (TextView) this.findviewbyid(r.id.text_id); tv.settext(readstring); 36
ファイル名を入力するエディットテキストを用意し データ取り込みボタンでデータベースに追加するアプリなども考えられます 37
正規表現 入力データに制限をかけ 不正なデータがデータベースに登録されないようにしましょうそういうときには 文字列のマッチングを調べる正規表現が便利です あいう 通常の文字リテラル. 任意の 1 文字 [ あいう ] ここに含まれる任意の 1 文字 [^あいう] ここに含まれる任意の 1 文字以外 ^あ 先頭の文字を指定 あ $ 最後の文字を指定 あ? 0 回または 1 回 あ + 1 回以上の繰り返し あ * 0 回以上の繰り返し あ {n, m n 回以上 m 回以下の繰り返し あ {n, n 回以上の繰り返し あ {n n 回の繰り返し ( あ い ) 選択どちらでもよい { グループ ( 繰り返しの単位指定 ) プログラム例 AlertDialog.Builder dlg; dlg = new AlertDialog.Builder(this); dlg.settitle("test"); dlg.setpositivebutton(" 閉じる ", null); EditText et = (EditText) this.findviewbyid(r.id.input_et); Pattern pattern = Pattern.compile("^あ.*$"); Matcher matcher = pattern.matcher(et.gettext()); if(matcher.matches()){ dlg.setmessage("ok"); System.out.println("OK"); else{ dlg.setmessage("ng"); System.out.println("NG"); dlg.show(); 38
アプリケーション作品制作について 設計項目 1. 画面遷移図 2. データベース仕様書 フィールド名 内容 型 備考 ( 内容説明と属性 primary key など ) id 主キー Integer primary Key autoincrement 3. 画像やテキストファイルがある場合には 保存場所 ( フォルダ階層 ) 4. データベースと画面との関係 39