Androidアプリケーション技術者認定試験ベーシックの試験範囲の知識をまとめた(7)

# ストレージ

## ファイル入出力

### ファイル入出力の概要

データの保存には、ファイルで永続的に保存する方法がある。ファイルはフォルダで管理される。
パーミッションは、ファイルを作成するときにアプリケーションで指定する。

### ファイル入出力の手順

1. ファイル出力(入力)ストリームの取得
1. ファイルへのデータ出力(入力) Java共通のBufferedReaderクラスなどを使用する
1. ストリームのクローズ

### ファイル出力のコーディング

ファイル出力ストリームを取得する場合、Contextクラスの場合openFileOutputクラスを使用する。
第一引数はファイル名、第二引数は操作モード

操作モード一覧

|||
|---|---|
|MODE_APPEND|追加書き込み状態でオープン|
|MODE_PRIVATE|他のアプリケーションからアクセスできないファイルを作成する|
|MODE_WORLD_READABLE|他のアプリケーションから読み込み可能なファイルを作成する|
|MODE_WORLD_WRITEABLE|他のアプリケーションから書き込み可能なファイルを作成する|

複数の指定をしたい場合はMODE_APPEND | MODE_PRIVATEのように論理和演算子で連結して指定する。
作成される場所は/data/data/[パッケージ名]/filesに格納される

openFileOutputメソッドでFileOutputStreamが返されるのでそれに対して処理を行う。
Javaの一般的なBufferedWriterストリームが使える。最後にクローズ処理も行う。

openFileOutputメソッドはFileNotFoundExceptionをスローする
BufferdWriterのwriteメソッドではIOExceptionをスローする

#### ファイルの存在確認

DDMS(Dalvik Debug Monitor Service)やadbを使用してファイルを確認できる。

##### ファイルのパーミッションとは

いわゆるLinuxのファイルパーミッションと同じ

### ファイル入力

openFileInputメソッドでファイル入力ストリームを取得できる。Contextクラスのメソッド。
引数にはファイル名を指定する。自動的に/data/data/[パッケージ名]/files配下のファイルを読み込む
ファイルが見つからない場合はFileNotFoundExceptiion例外が発生する
後は出力と同じように一般的なJavaアプリケーションのように実装する。

### ファイルの削除

ContextクラスのメソッドdeleteFileを使って削除する。引数はファイル名で、自動的に/data/data/[パッケージ名]/files配下のファイルを処理対象とする。削除に成功したらtrue、失敗したらfalseを返す。

### ディレクトリの操作

処理の対象となる既定ディレクトリを取得するにはgetFilesDirメソッドを使う
既定ディレクトリ以外を作成するにはgetDirメソッドを使う。操作モードはファイルと同じものを指定する。
存在するディレクトリだった場合は、Fileオブジェクトが返却され、存在しなかった場合は、
/data/data/[パッケージ名]/app_[指定したディレクトリ名]というディレクトリが作成されてそのFileオブジェクトが返る。
帰ってきたFileオブジェクトを使用してjava.io.FileWriter等で、ファイルを作成できる

### SDメモリーカードへのアクセス

SDカードのファイルにアクセスするには以下が必要。

1. マニフェストファイルへSDメモリーカードへの書き込み権限を追加する
1. SDメモリカードにアクセスする前にカードの状態を確認する。
1. デバイスによって、マウントディレクトリが異なるためマウントディレクトリを確認する

#### マニフェストファイルへのパーミッション通知

AndroidManifest.xmlファイルにandroid.permission.WRITE_EXTERNAL_STORAGEを追加する

#### SDメモリカードの状態確認

Environment.getExternalStorageStateメソッドを使用する。カードの状態が返却される。

|||
|---|---|
|MEDIA_BAD_REMOVAL|アンマウントする前に外された|
|MEDIA_CHECKING|チェック中|
|MEDIA_MOUNTED|マウント済み|
|MEDIA_MOUNTED_READ_ONLY|読み込み専用としてマウント|
|MEDIA_NOFS|ファイルシステムがない状態|
|MEDIA_REMOVED|挿入されていない|
|MEDIA_SHARED|USBストレージとして共有されている状態|
|MEDIA_UNMOUNTABLE|マウントすることが出来ない状態|
|MEDIA_UNMOUTED|マウントされてない状態|

#### SDメモリカードのディレクトリ確認

Environment.getExternalStorageDirectoryメソッドを使用する。

## プリファレンス

### プリファレンスの概要

プリファレンスはXMLファイルである。boolean,float,long,string,intの各データを保存、取得できる。

### データの保存

ActivityクラスのgetPreferencesメソッドでプリファレンスオブジェクトを取得する。引数は操作モード（ファイルの時と同じ）を指定する。ファイル名はアクティビティ名と同じになる。
他に、ContextクラスのgetSharedPreferencesメソッドを使用することもできる。こちらは引数にファイル名も指定できる。
ファイルは/data/data[パッケージ名]/shared_prefsディレクトリの配下に作成される。

プリファレンスオブジェクトのeditメソッドを使用してEditorオブジェクトを取得する。
取得したEditorオブジェクトのputXxxメソッドを使用して保存するデータを設定する。第一引数はString型でキーを指定。第二引数が保存したいデータ。同じキーを指定した場合は上書きされる。
最後にEditorオブジェクトのcommitメソッドでデータをファイルに書き出す。

### データの取得

getPreferencesメソッドでプレファレンスオブジェクトを取得する。
プレファレンスオブジェクトのgetXxxメソッドでデータを取得する。第一引数はキー名で、第二引数はキーがない場合のデフォルト値。
保存する場合はEditorオブジェクトだが取得する場合はShardPreferencesオブジェクトのメソッドであることに注意。
型を間違えて指定すると、ClassCastException例外が発生する。
getAllメソッドで取得することでプリファレンスに定義したデータをすべて読み込める。その場合はMAP型として読み込むことになる。

### データの削除

getPreferencesメソッドでプレファレンスオブジェクトを取得する。
プレファレンスオブジェクトよりeditメソッドを使用してEditorオブジェクトを取得する。
Editorオブジェクトのremoveメソッドを使用してデータを削除する。引数にキー名を指定する。
clearメソッドを使うとすべてのデータがクリアされる。
最後に、commitメソッドでファイルに反映させる。

## データベース

### データベースの概要

SQLiteを使用する場合、以下の二つのクラスを利用する。

- SQLiteOpenHelper抽象クラス

利用者はこのクラスを継承した作成し、onCreate, onUpgradeを実装する。
onCreateはデータベースを最初に利用するときに呼び出され、テーブルの作成や初期データの設定などが行われる
onUpgradeはデータベースのアップデート時に呼び出され、旧テーブルから新テーブルへのデータ移行などが行われる

- SQLiteDatabaseクラス

データベースのデータを操作するときに利用する。getWritableDatabaseメソッド（あるいはgetReadableDatabaseメソッド）を呼び出すことで取得。
Insert, Update, Delete, Selectするためのメソッドが用意されている。

####　データベースの準備

SQLiteOpenHelperクラスの継承クラスを生成する。コンストラクタの第一引数はContextクラス、第二引数はデータベース名、第三引数は通常null、第四引数はバージョン番号を指定する。

onCreateメソッドで渡されたSQLiteDatabaseクラスのexecSQLメソッドを使用して、テーブル作成など
初期設定を行う。

##### テーブル作成時のCREATE構文

SQLiteで指定できる列のデータ型と列制約は以下の通り

|||
|---|---|
|NULL|NULL値|
|INTEGER|符号付整数|
|REAL|浮動小数点数|
|TEXT|テキスト|
|BLOB|バイナリデータ|

列制約

|||
|---|---|
|PRIMARY KEY|主キー制約|
|NOT NULL|NULL値が格納できない|
|AUTOINCREMENT|自動でインクリメントされる|
|UNIQUE|値の重複が許されない|
|DEFAULT|挿入時に値が指定されない場合のデフォルト値を指定|

execSQLメソッドで実行するSQL文に誤りがあるとSQLException例外が発生する。

onUpgradeメソッドはコンストラクタの第4引数のバージョン番号と既存のバージョンが異なる場合に呼び出される。
onUpgradeの第三引数と第四引数で比較できるため、それをもとに適切なバージョンアップを行う。

#### データベースのファイル

データベースファイルは/data/data/[パッケージ名]/database配下に作成される。

#### データベースの操作

Activityなどでデータベースオブジェクトを取得するにはgetWritableDatabaseメソッドかgetReadableDatabaseメソッドを呼び出す。

#### データベースのトランザクション

SQLiteDatabaseクラスのbeginTransactionメソッドでトランザクションの開始が出来る。
データのへの操作が成功し完了した場合はsetTransactionSuccessfulメソッド、
トランザクションを終える時はendTransactionメソッドを呼び出す。
つまりsetTransactionSuccessfullメソッドを呼び出さずにendTransactionメソッドを呼び出すと
ロールバックされるということ。

#### レコードの挿入

execSQLを使用して、INSERT文を発行する。

#### レコードの更新

execSQLを使用して、UPDATE文を発行する。

#### レコードの検索

rawQueryメソッドを使用して、SELECT分を発行し、Cursorオブジェクトを取得する。
Cursorオブジェクトを操作し、getColumnIndexメソッドなどを利用して検索結果を取得する。

#### レコードの削除

execSQLを使用して、DELETE文を発行する。

#### その他のメソッド

SQL文を使用せずにレコードを操作するメソッドが用意されている。
insert, update, query, deleteの各メソッド。