データ永続化
第二回Android勉強会
Ishin FUKUOKA
Data Persistance
データを保存する方法
● プリファレンス	

!
● データベース	

!
● ファイル	

!
今日は上の二つを詳しく扱います
今日扱うのは	

「アプリ内でのデータの扱い」	

です。	

他アプリからのデータアクセス等は	

「コンテントプロバイダ」	

を使用します。
プリファレンス
キー:値でのデータの保存
プリファレンス
● プリファレンスの利用	

!
● 第一引数 String	

 ファイル名。任意。	

!
● 第二引数 Context(定数)	

 処理モード	

■ MODE_PRIVATE 他アプリからのアクセス不可	

■ MODE_WORLD_READABLE 他アプリからの読み込み可 	

■ MODE_WORLD_WRITABLE  他アプリからの書き込み可
SharedPreferences preferences = getSharedPreferences(FILE_NAME,MODE_PRIVATE);
使わない!!
● データの取得	

!
!
● 第一引数 String	

取得する型に応じてメソッドは異なる(getInt(),getBoolean() etc…)	

!
● 第二引数	

キーに指定したデータがなかったときに返す値
プリファレンス
String value = preferences.getString(“KEY”,"Not Found");
● データの保存	

!
!
!
● SharedPreferences.Editorインターフェースのインスタンス
を取得	

● putString(),putInt()	

● 第一引数 String	

保存するデータのキー	

!
● 第二引数	

  保存する値
プリファレンス
SharedPreferences.Editor editor = preference.edit();	

editor.putString(“STR_KEY”,”テスト”);	

editor.putInt(“INT_KEY”,100);	

edirot.commit();
● データ消去	

● 全て消去	

!
!
● 指定したキーを消去
プリファレンス
editor.clear();	

Editor.commit();
editor.remove(“KEY”);	

Editor.commit();
プリファレンス まとめ
● SharedPreferencesクラス	

!
● データをキー:値の組で保存	

!
● アプリの設定など簡易的な値の保存に使われる
practice
演習
演習用テンプレート
https://www.dropbox.com/sh/6xyssumb57vn5r2/0_L3sWKY5q
PreferenceActivity.javaの穴埋めを行ってください
データベース
SQLiteを利用したデータ保存
データベース
● SQLiteを使用	

!
● データ型 INTEGER,REAL,TEXT,BLOB,NULL	

!
● DB定義に必要な文字列を定数として宣言しておく
と便利
データベース
public static abstract class DataBaseEntry implements BaseColumns {	

public static final StringTABLE_NAME="entry";	

public static final String COLUMN_NAME_ENTRY_ID = "entryid";	

public static final String COLUMN_NAME_ITEM = "item";	

public static final String COLUMN_NAME_VALUE = "value";	

}	

}
データベース定義
● SQLiteOpenHelperクラスを継承	

!
!
!
!
!
!
スーパークラスのコンストラクタ	

第一引数:アクティビティクラスのインスタンス	

第二引数:データベース名	

第三引数:null(標準のカーソルを拡張するときに使う?)	

第四引数:バージョン番号
public class CreateProductHelper extends SQLiteOpenHelper {	

!
public static final int DATABASE_VERSION = 1;	

public static final String DATABASE_NAME = "DBSample.db";	

//コンストラクタ	

public CreateProductHelper(Context con){	

super(con,DATABASE_NAME,null,DATABASE_VERSION);	

}	

……	

}
● SQLiteOpenHelperを継承したクラスが実装するメ
ソッド
データベース定義
 //onCreate 必須	

@Override	

public void onCreate(SQLiteDatabase db){	

//SQL文を作成してexecSQLメソッド	

db.execSQL(SQL_CREATE_ENTRIES);	

}	

//onUpgrade 必須	

@Override	

public void onUpgrade(SQLiteDatabase db,int oldversion,int newversion){	

}	

//onDowngrade 任意	

@Override	

public void onDowngrade(SQLiteDatabase db,int oldversion,int newversion){	

}
予め定義したString型の定数
● Create文の例
データベース定義
private static final StringTEXT_TYPE = "TEXT";	

private static final String INTEGER_TYPE = " INTEGER";	

private static final String PRIMARY_KEY = " PRIMARY KEY";	

private static final String AUTO_INCREMENT = " AUTOINCREMENT";	

private static final String COMMA_SEP = ",";	

!
private static final String SQL_CREATE_ENTRIES =	

"CREATETABLE " + DataBaseEntry.TABLE_NAME + " ("+	

DataBaseEntry.COLUMN_NAME_ENTRY_ID+ INTEGER_TYPE + 	

	

 PRIMARY_KEY + AUTO_INCREMENT+COMMA_SEP+	

DataBaseEntry.COLUMN_NAME_ITEM +TEXT_TYPE + COMMA_SEP +	

DataBaseEntry.COLUMN_NAME_VALUE + INTEGER_TYPE +	

")";
● データベースクラスのインスタンス取得	

!
!
!
!
!
!
書き込み時 helper.getWritableDatabase();	

読み込み時 helper.getReadableDatabase();
データベース定義
CreateProductHelper helper = null;	

SQLiteDatabase db = null;	

!
protected void onCreate(…){	

	

 //DB作成	

	

 helper = new CreateProductHelper(DatabaseActivity.this);	

	

 //DBインスタンス取得	

	

 db = helper.getWritableDatabase();	

…..	

}
データベース データの挿入
● ContentValuesクラス	

● db.insert()	

!
!
!
!
!
ContentValues.put(列名,登録する値);	

db.insert(テーブル名,NULLを登録したい列名,データ)
ContentValues values = new ContentValues();	

values.put(DataBaseEntry.COLUMN_NAME_ITEM, item_name);	

values.put(DataBaseEntry.COLUMN_NAME_VALUE, item_value);	

!
db.insert(DataBaseEntry.TABLE_NAME, null, values);
データベース データの削除
● db.delete()	

!
!
!
condition nullの場合はデータすべて消去	

db.delete(テーブル名,条件,条件に?が含まれる場合そこに入る値の文
字配列);
//削除条件	

String condition = null;	

//データ削除	

db.delete(DataBaseEntry.TABLE_NAME, condition, null);
//例	

db.delete(	

	

 DataBaseEntry.TABLE_NAME,	

	

 “item=?”, 	

	

 new String[]{“りんご”}	

);
データベース データの更新
● ContentValuesクラス	

● db.update()	

!
!
!
!
!
condition nullの場合はデータすべて更新	

db.update(テーブル名,データ,条件,条件に?が含まれる場合ry);
//更新条件	

String condition = null;	

ContentValues values = new ContentValues();	

values.put(DataBaseEntry.COLUMN_NAME_ITEM, item_name);	

values.put(DataBaseEntry.COLUMN_NAME_VALUE, item_value);	

//データ更新	

db.update(DataBaseEntry.TABLE_NAME,values,condition,null);
データベース データの取得
● helper.getReadableDatabase()	

● db.query(),またはdb.rawQuery()でCursorクラスにク
エリ結果を渡す
db = helper.getReadableDatabase();
Cursor cursor = db.query(DataBaseEntry.TABLE_NAME,columns,null,null,null,null,
DataBaseEntry.COLUMN_NAME_ENTRY_ID);
Cursor cursor =db.rawQuery(	

	

 “select item,value from entry where value < ? ;”,	

	

 String[]{“500”}	

);
データベース データの取得
● db.query()
db = helper.getReadableDatabase();	

!
//取得する列名	

String columns[] = {	

	

 DataBaseEntry.COLUMN_NAME_ENTRY_ID,	

	

 DataBaseEntry.COLUMN_NAME_ITEM,	

	

 DataBaseEntry.COLUMN_NAME_VALUE	

};	

!
//データ取得	

Cursor cursor = db.query(DataBaseEntry.TABLE_NAME,columns,null,null,null,null,
DataBaseEntry.COLUMN_NAME_ENTRY_ID);
データベース データの取得
db.query(	

	

 テーブル名,	

	

 取得する列名,	

	

 選択条件(where),	

	

 選択条件に?が含まれry,	

	

 集計条件(group by),	

	

 選択条件(having),	

	

 ソート条件(order by)	

);
//データ取得	

Cursor cursor = db.query(DataBaseEntry.TABLE_NAME,columns,null,null,null,null,
DataBaseEntry.COLUMN_NAME_ENTRY_ID);
データベース データの取得
db.rawQuery(SQL文,SQL文に?が含まry);
//データ取得	

Cursor cursor = db.rawQuery(	

	

 “select item,value from entry where value < ? ;”,	

	

 String[]{“500”}	

);
データベース データの取得
クエリ結果をcursor.getString(取得した値の列番号)で取得
while(cursor.moveToNext()){	

TableRow row = newTableRow(con);	

TextView id_tv = newTextView(con);	

id_tv.setText(cursor.getString(0));	

TextView item_tv = newTextView(con);	

item_tv.setText(cursor.getString(1));	

TextView value_tv = newTextView(con);	

value_tv.setText(cursor.getString(2));	

row.addView(id_tv);	

row.addView(item_tv);	

row.addView(value_tv);	

!
table.addView(row);	

!
}
データベース トランザクション
//トランザクション制御開始	

db.beginTransaction();	

try {	

	

 .......	

	

 //コミット	

	

 db.setTransactionSuccessful();	

} finally {	

	

 //トランザクション制御終了	

	

 db.endTransaction();	

}
コミットをかけて初めて変更内容がDBに反映される
● 複数人が同時にDBにアクセスしてもデータに矛盾が発生
しないための仕組み	

!
● あるトランザクションAがデータにアクセスしたとき、
DBをロック状態にする。その間他のトランザクションか
らのアクセスは待たされる。	

 デッドロックとかOSで似たようなのやったよね!	

!
● COMMITでトランザクションを終了すると、更新処理を
行いそこまでのデータは保証される。
トランザクション?
データベースまとめ
● SQLiteOpenHelpreクラスを継承したヘルパークラスを作
成	

!
● SQLiteDatabase.insert(),delte(),update()等で操作	

(今回は書きませんでしたがexecSQL()のSQL文直打ちでもできます。)	

!
● SQLiteDatabase.query(),rawQuery()で取得	

!
● データベースに変更を加える際はトランザクションで
制御
practice
演習
演習用テンプレート
https://www.dropbox.com/sh/6xyssumb57vn5r2/0_L3sWKY5q
DataBaseActivity.javaの穴埋めを行ってください
ファイル
内部/外部ストレージを利用したデータ保存
ファイル
● 内部ストレージ	

p アプリからのアクセスのみ	

p アプリをアンインストールしてもデータは残る	

● 外部ストレージ	

p 外からのアクセスが可(WORLD_READABLE)	

p アプリをアンインストールした場合の挙動はデータの生成
方法によって異なる(?)	

p Manifest.xmlに権限の記述が必要	

!
● 基本的にJavaでのファイル操作
ファイル 内部ストレージ
● 保存方法の例(内部ストレージの場合)
try{	

	

 FileOutputStream stream = openFileOutput(FILE_NAME,MODE_APPEND);	

	

 BufferedWriter out = new BufferedWriter(new OutputStreamWriter(stream));	

!
	

 out.write(“保存内容”);	

out.newLine();	

out.close();	

!
}catch(Exception e){	

!
}
ファイル 内部ストレージ
● データ読み取り
try{	

	

 FileInputStream stream = openFileInput(FILE_NAME);	

BufferedReader in = new BufferedReader(new InputStreamReader(stream));	

String line = "";	

while((line=in.readLine())!=null){	

	

 str+=line+"n";	

}	

in.close();	

!
}catch(Exception e){	

	

 	

}
ファイル 内部ストレージ
● データ消去
try{	

!
deleteFile(FILE_NAME);	

!
}catch(Exception e){	

!
}
ソースコード
40
https://github.com/IshinFUKUOKA/SavingDataSample
Thank you for Listening
References
● AndroidDevelopers - SavingData	

http://developer.android.com/training/basics/data-storage/
index.html	

!
The Android robot is reproduced or modified from work created and shared by Google and used
according to terms described in the Creative Commons 3.0 Attribution License.

【第二回Android勉強会】データ永続化