2014/10/31

Android: SQLite3 LockとTransaction Immediate/Exclusive

Intro

AndroidのSQLite3のLockとTransaction Immediate/Exclusiveについてまとめた.
基礎となる知識としては こちら を参照.

Locking And Concurrency In SQLite3

Oracle等のDBMSでは”行ロック”など細かくロック粒度を制御できるが, SQLiteではこれができない.
SQLiteのロック粒度は”データベース単位”のみである. このためRead/Writeロック取得~解放までの間, 他のトランザクションはデータベースにアクセスできない. (このことは”データベースを分割する/しない”の判断基準の1つにはなりそう)

AndroidではSQLiteのトランザクションモードとしてImmediateとExclusiveをAPIで指定できる. 特に指定しない場合はExclusiveモードとなる.

Transaction Immediate

ロック取得中は他トランザクションの書き込みを制限し, 読み込みを許可するmode.
Exclusive modeより緩い分離レベルであるためトランザクションの並列化を促進でき, パフォーマンス面で期待できる. ただし, Phantom Readが発生する可能性を考慮する必要がある.

IMMEDIATE.
トランザクション開始時にRESERVEDロックを取得する. BEGIN IMMEDIATEによりRESERVEDロックが取得されると, 他のデータベースコネクションはデータベースに書き込んだり, BEGIN IMMEDIATE or BEGIN EXCLUSIVEを実行することができなくなるが, データベースからの読み込みを継続することはできる.
ANSI/ISO SQL標準では REPEATABLE_READ に相当する.

アプリケーションがデータベースへアクセスするのに書き込み専用トランザクション と 読み込み専用トランザクションのようにRead/Writeを分離できるのであればImmediate modeは有効に作用する.

Immediate modeではPhantom Readが発生するため, 次のようなシーケンスでは一貫性が損なわれる.

Created with Raphaël 2.1.0Transaction ATransaction AShared ResourceShared ResourceTransaction BTransaction BBEGIN TRANSACTIONBEGIN TRANSACTIONREAD ALL (x)DELETE (x)INSERT (y)COMMIT TRANSACTIONREAD ALL (y)Expected xBut was y-Phantom Read-

Transaction Exclusive

ロック取得中は他トランザクションの読み込み/書き込みを制限するmode.
Immediateより厳しい分離レベルであるためトランザクションの直列化が促進され, データの一貫性が向上する. ただしパフォーマンスはImmediateに劣る可能性が高い.

EXCLUSIVE
トランザクション開始時にEXCLUSIVEロックを取得する. BEGIN EXCLUSIVEによりEXCLUSIVEロックが取得されると, READ_UNCOMMITTEDの接続を除いた全てのデータベースコネクションからデータを読み込むことができなくなる. データベースへの書き込みについては例外なくトランザクションの完了まで許可されない.
ANSI/ISO SQL標準では SERIALIZABLE に相当する.

データベースに対して完全なデータの一貫性が求められる場合はExclusive modeを指定する.

Implements

クライアントからTransaction modeを指定するにはSQLiteDataBaseクラスを使用する.

  • SQLiteDataBase.beginTransaction()
  • SQLiteDataBase.beginTransactionWithListener(SQLiteTransactionListener)
  • SQLiteDataBase.beginTransactionNonExclusive()
  • SQLiteDataBase.beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)

beginTransactionNonExclusive/beginTransactionWithListenerNonExclusiveはAPI Level11で追加されたAPI.

beginTransaction/beginTransactionWithListenerで開始されたトランザクションはExclusive modeで,
beginTransactionNonExclusive/beginTransactionWithListenerNonExclusiveで開始されたトランザクションはImmediate modeで動作する.

// Transaction Exclusive mode
db.beginTransaction();
try {
    // do something.
    db.setTransactionSuccessful();
} finally {
    db.endTransaction();
}

// Transaction Immediate mode
db.beginTransactionNonExclusive();
try {
    // do something.
    db.setTransactionSuccessful();
} finally {
    db.endTransaction();
}

SQLiteDatabaseLockedException

ロックされているデータベースに対し, SQLiteDatabase経由でクエリを実行した場合の挙動は下記.

SQLiteDatabase.query

ロックが取得できるまでトランザクションは待機される. API Level16以降はCancellationSignalを使ってクエリをキャンセルすることができる.

SQLiteDatabase.insert

SQLiteDatabaseがSQLiteDatabaseLockedExceptionをキャッチし, 呼出し元に-1を返す.

public long insert(String table, String nullColumnHack, ContentValues values) {
    try {
        return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
    } catch (SQLException e) {
        Log.e(TAG, "Error inserting " + values, e);
        return -1;
    }
}

SQLiteDatabase.insertOrThrow

SQLiteDatabaseLockedExceptionがスローされる.

public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
        throws SQLException {
    return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
}

SQLiteDatabase.update

SQLiteDatabaseLockedExceptionがスローされる.

SQLiteDatabase.delete

SQLiteDatabaseLockedExceptionがスローされる.

SQLiteDatabase.beginTransaction

SQLiteDatabaseLockedExceptionがスローされる.

Reference

File Locking And Concurrency In SQLite Version 3

以上.

Android: 同時実行制御とSQLite3

Intro

同時実行制御とは, 共有リソースにアクセスする複数のトランザクションを, いかに並列処理しつつ競合によるデータ破壊を回避するかを扱う分野である.
昨今のアプリケーションではクライアントが複数いることは珍しくない. 同時アクセスを許容せず, クライアントからの要求を直列的に処理できれば同時実行制御の課題は解決されるが, アプリケーションのレスポンスは極端に低下し使い物にならない.
パフォーマンスの低下を抑えるためにトランザクションを並列化し, かつリソースの整合性を保証しなければならないため, 同時実行制御を考える必要が出てくる.

Conflict

並列処理されるトランザクションの競合を制御しなかった場合の問題は主に4種類ある.
基本的にデータの一貫性は保証されない.

Dirty Read (w-r)

コミットされていないデータを別のトランザクションから参照できてしまう問題. トランザクションがロールバックされた場合に, 別のトランザクションから参照されていたデータはDirtyになる.
Created with Raphaël 2.1.0Transaction ATransaction AShared ResourceShared ResourceTransaction BTransaction BBEGIN TRANSACTIONBEGIN TRANSACTIONREAD (x=0)WRITE (x=1)READ (x=1)ROLLBACK TRANSACTIONExpected x=0But was 1-Dirty Read-

Lost Update / Overwrite (w-w)

別のトランザクションによる書き込みで, 更新したデータが上書きされてしまう問題.
Created with Raphaël 2.1.0Transaction ATransaction AShared ResourceShared ResourceTransaction BTransaction BBEGIN TRANSACTIONBEGIN TRANSACTIONWRITE (x=1)WRITE (x=0)COMMIT TRANSACTIONCOMMIT TRANSACTIONExpected x=1But was 0-Lost Update-

Non-Repeatable Read / Fuzzy Read (r-w)

トランザクション内で別のトランザクションによるデータ更新が反映されてしまい, 同じレコードでも参照するたびに結果が変わる.
Created with Raphaël 2.1.0Transaction ATransaction AShared ResourceShared ResourceTransaction BTransaction BBEGIN TRANSACTIONBEGIN TRANSACTIONREAD (x=0)WRITE (x=1)COMMIT TRANSACTIONREAD (x=1)Expected x=0But was 1-Fuzzy Read-

Phantom Read / Inconsistent Read (r-w)

同じトランザクション内でも, データの参照結果が増減する. 別のトランザクションによるデータ更新 or 削除が参照できることが原因で発生する.
Created with Raphaël 2.1.0Transaction ATransaction AShared ResourceShared ResourceTransaction BTransaction BBEGIN TRANSACTIONBEGIN TRANSACTIONREAD ALL (x)DELETE (x)INSERT (y)COMMIT TRANSACTIONREAD ALL (y)Expected xBut was y-Phantom Read-

Isolation

Isolationは分離性や隔離性, 独立性と訳される(本項では分離性とする). 分離性とはトランザクションを並列処理する中で, どこまでトランザクション同士の干渉を回避して読み取り一貫性を保証するかの度合いである.

Consistency and Isolation

分離レベルとはトランザクションの並列性/直列性の度合いを定義したものである. ACID特性の中でも分離性は柔軟解釈されている.
データベースソフトウェアでは分離レベルを選択できるものが多い. これは分離レベルの度合いにより拡張性や性能に大きな影響を与えるためである.
分離レベルは緩いほどパフォーマンスが向上する. 反対に厳しくするほどパフォーマンスは犠牲になる. ただし, 分離レベルを厳しくするほどデータの一貫性は保証されていく. 分離レベルには次のものがある.
  1. Read Uncommitted
  2. Read Committed
  3. Monotonic View
  4. Repeatable Read
  5. Serializability
Serializabilityは特定のリソースに対するアクセスを同時に1つのトランザクションしか実行させない形式, つまり各トランザクションが完全に直列実行されるため, トランザクションは交差することなく完全に分離される. Serializabilityは最も厳しい分離レベルである. このレベルは同時実行制御に関係する多くの問題が解決されるため一貫性の面においては理想的なレベルであるが, トランザクションが直列化することによりパフォーマンスを大きく損なうため多くの場合採用するに至らない.
少なくない数のクライアントを抱えているアプリケーションやリアルタイム性を求められるアプリケーションの場合, Serializability分離レベルを選択するのは現実的ではない1.
“では, パフォーマンスを向上しよう”という話になり, トランザクションを並列化させる方向に進んでいく. つまり同時実行制御を考える必要が出てくる.
  • トランザクションの並列化を促進する程, パフォーマンスは向上する.
  • トランザクションの直列化を促進する程, パフォーマンスは低下する.
ただし,
  • トランザクションの並列化を促進する程, 同時実行制御は複雑になる.
  • トランザクションの直列化を促進する程, 同時実行制御は単純になる.

Isolation Levels

トランザクションの代表的な分離レベル(ANSI/ISO表記)を次に記載する.
データ一貫性を保証するために全ての分離レベルではDirty Writeを回避する必要がある. 分離レベルが緩い(より並列化させる)ほど同時実行制御は複雑化しデータ破壊のリスクが高まる.

Read Uncommitted

他のトランザクションによるコミット前データの読み込みを許容する分離レベル. トランザクションは極めて並列に実行されるためパフォーマンスは高い. ただし, この分離レベルではDirty Writeは回避されるもののDirty Read, Fuzzy Read, Phantom Read, Lost Updateなど様々な問題が発生するため, 競合が発生する状況下ではデータ破壊の可能性も高くなる.

Read Committed

コミット済みデータが読み込まれることを保証する分離レベル. ただし, トランザクションの途中でも他のトランザクションがコミットしたデータが読み込まれる.
この分離レベルではDirty Readを回避できるが Fuzzy Read, Phantom Read, Lost Updateは回避できない.

Repeatable Read

トランザクションで読み込んだデータはコミットするまで変更されないことを保証する分離レベル.
保証するのは読み込んだデータに対してのみであり, それ以外のレコード追加などは保証されないので範囲指定問合せによるPhantom Readは防げない.

Serializability

完全な一貫性を保証する分離レベル. 全てのトランザクションが直列に実行されているように見える特徴がある.
競合問題と分離レベルの関係をまとめる.
- Dirty Read Lost Update Fuzzy Read Phantom Read
READ UNCOMMITTED 発生する 発生する 発生する 発生する
READ COMMITTED 発生しない 発生する 発生する 発生する
REPEATABLE READ 発生しない 発生しない 発生しない 発生する
SERIALIZABLE 発生しない 発生しない 発生しない 発生しない

Exclusive control

Shared lock, Exclusive lock

トランザクションの競合が発生すると前述の競合問題が発生する. 競合を回避してデータの一貫性を保証するためには共有リソースへのアクセスを制限するロックメカニズムを導入して排他制御を促進する.
排他制御とは, 他のトランザクションから共有リソースへのアクセスを制限(ロック)するものである. ロックはトランザクションの完了まで保持されたあと解除され, 他のトランザクションはそれまで共有リソースへアクセスすることができない.
ロックは他のトランザクションのアクセスを制限するという特性から, パフォーマンスに大きく影響する. そのためロックにはいくつか形態があり, 用途によって使い分けられる. ロックの形態は大きく2つ存在する.

Shared lock - 共有ロック

トランザクションがデータを読み込む場合のロック方式. データが共有ロックされている間は他のトランザクションでもデータを読み込むことができるが, データを書き込むことはできない.

Exclusive lock - 排他ロック

トランザクションがデータを書き込む場合のロック方式. データが排他ロックされている間は, 他のトランザクションからデータを読み込むことも書き込むこともできない.
また, ロックするデータの範囲をロック粒度(またはロックレベル)という. ロックするデータの範囲にはテーブル全体, 行全体, 特定の列がある. ロック粒度の程度には一長一短がある.
  • ロック粒度を小さくするとトランザクションの並列性が高くなる
  • ロック粒度を小さくするとトランザクションの競合頻度は高くなる
また,
  • ロック粒度を大きくするとトランザクションの並列性が低くなる
  • ロック粒度を大きくするとトランザクションの競合頻度は低くなる

Pessimistic mechanism, Optimistic mechanism

ロックを取得する期間も重要である. トランザクションは競合を検知するとデータの一貫性を保証するためにロールバックを実行し, トランザクション処理をキャンセルする. ロックの期間を短くするのは大切だが, 短くし過ぎてロールバックが頻発するのは問題である.
  • ロック取得の期間を長くすれば競合の排除を促進できる
  • ロック取得の期間を短くすれば競合の排除は抑制される
また,
  • ロック取得の期間を長くすると空振り(ロールバック)に終わる頻度は下がる
  • ロック取得の期間を短くすると空振り(ロールバック)に終わる頻度が上がる
ただし,
  • ロック取得の期間を長くすると別のトランザクションの待ち時間が延びる
  • ロック取得の期間を短くすると別のトランザクションの待ち時間が縮まる
さらに,
  • ロック取得の期間を長くするとデッドロックの発生確率が上がる
  • ロック取得の期間を短くするとデッドロックの発生確率は下がる
ロックにはパフォーマンスの話題がつきもので, 最適なロックの粒度と期間を選択しないとパフォーマンスの低下を招く.
ロックを取得するタイミングには2通りに大別される. 悲観的ロック と 楽観的ロック である.
悲観的ロックはロックの期間を長くとる. 反対に, 楽観的ロックではロックの期間を短くとる. システムの特性にあわせてどちらの方式を採用するかを決める.

Pessimistic mechanism - 悲観的方式

排他制御において, “トランザクションは高頻度で競合する前提”で考えられた悲観的な方式. 主にロックで排他制御を実現する.
悲観的方式では, トランザクションがデータにアクセスし始めた時点からコミットまでロックを保持する. この間, 別のトランザクションがリソースにアクセスすることを制限する.
悲観的方式はトランザクションを直列処理するため, 排他制御の扱いは容易に映るが, デッドロックやパフォーマンスの面で注意が必要である.

Optimistic mechanism - 楽観的方式

排他制御において, “トランザクションは低頻度で競合する前提”で考えられた楽観的な方式. 主に競合検出で排他制御を実現する.
楽観的方式では, トランザクション中に別のトランザクションによるデータ更新がなかったかを検査(競合検出)してからコミットする. トランザクションが更新操作中でも別のトランザクションからの操作は制限されない. コミット時に競合検出された場合は当該トランザクションはロールバックされる.
悲観的方式と楽観的方式は一長一短であり, それだけで優劣をつけるものではなく要件にあって選択すべきものである.
リソースの更新リクエストが頻発すると予想されるシステムでは, 書き込みに最適化させたい場合が多い. このケースでは悲観的方式を選択できる.
リソースの参照リクエストが中心となるシステムでは読み込みに最適化させたい場合が多い. このケースでは楽観的ロックが選択できる.
一般的にRDBMSは書き込み操作に最適化されており, 悲観的方式が採用される2.
一方, Webサーバは読み込み操作に最適化されており, レスポンス性を高めるために楽観的方式が採用されやすい.

SQLite3

SQLite3における同時実行制御関連の情報.

ロック粒度

DBMSによってはロックの粒度を行や列単位で指定できるものがある. ただし, SQLiteではデータベース全体のロック粒度しか選択できない.
SQLite.org - Appropriate Uses For SQLite … High Concurrency

ロック状態

SQLiteは共有ロック, 排他ロックの仕組みを備えており, プロセスを跨いで同時実行されても適切に処理される.
SQLiteのトランザクションには複数のモードが存在し, 各モードや実行内容によって取得されるロック種別が変わる.
UNLOCKED
非ロック状態. どのプロセスも書き込み/読み込みしていないデータベースの初期状態.
SHARED
データを書き込みを伴わずに読み込む場合に取得されるロック. 他のプロセスからの読み込みを許可するが書き込みは許可しない. SHAREDロックは複数のプロセスに保持させることができるため, 他のプロセスからの読み込みに対してオープンである.
RESERVED
将来データを書き込む予定だが現状読み込みしかされていない場合に取得されるロック. SHAREDロックとRESERVEDロックを共存させることができるが, RESERVEDロックはある時点で1つしか保持されない.
PENDING
EXCLUSIVEロックを取得してデータの書き込みを実行しようとSHAREDロックの開放を待機する場合に取得されるロック. 全てのSHAREDロックが開放されるとEXCLUSIVEロックが取得される.
EXCLUSIVE
データを書き込むために必要なロック. PENDINGロックからEXCLUSIVEロックに状態遷移するため, EXCLUSIVEロックが取得されているタイミングでは他のすべてのロックは解放されている. EXCLUSIVEと他のロックとを共存させることはできない.
See. SQLite.org - File Locking And Concurrency In SQLite Version 3

分離レベル

SQLiteにおける分離レベルはANSI/ISO SQL標準の表記とは異なっており, ロックを取得するタイミングに主眼を置いた表記となっている.
DEFERRED
トランザクション開始時にはロックを取得せず, データの読み込み/書き込みをする時点までロック取得を延期する. そのため, BEGINステートメントによるトランザクション開始のみでは何のロックも取得されない. ロックの取得がBEGIN~データの読み込み/書き込みまで延期されるため, 別トランザクションによるデータ書き込みの割り込みが発生する可能性がある. (ANSI/ISO SQL標準では READ_COMMITTED に相当. )
IMMEDIATE
トランザクション開始時にRESERVEDロックを取得する. BEGIN IMMEDIATEによりRESERVEDロックが取得されると, 他のデータベースコネクションはデータベースに書き込んだり, BEGIN IMMEDIATE or BEGIN EXCLUSIVEを実行することができなくなるが, データベースからの読み込みを継続することはできる. ( ANSI/ISO SQL標準では REPEATABLE_READ に相当. )
EXCLUSIVE
トランザクション開始時にEXCLUSIVEロックを取得する. BEGIN EXCLUSIVEによりEXCLUSIVEロックが取得されると, READ_UNCOMMITTEDの接続を除いた全てのデータベースコネクションからデータを読み込むことができなくなる. データベースへの書き込みについては例外なくトランザクションの完了まで許可されない. ( ANSI/ISO SQL標準では SERIALIZABLE に相当. )
See. SQLite.org - BEGIN TRANSACTION
See. SQLite.org - PRAGMA read_uncommitted

Reference

InfoQ - Web開発者が知っておくべき八つの分離レベル
以上.

  1. eBayやAmazonといった巨大Webアプリケーションが楽観的で緩やかな一貫性保証の方が, 古くからの悲観的メカニズムより拡張性に富んでいることを証明した例もある
  2. Oracle Databaseには楽観的ロックのイメージが強いが, 悲観的ロックも指定できる
2014/10/22

Android:Nexus5 Android5.0 preview(LPX13D)のroot化手順

0. はじめに

Root化は次のリスクをご認識の上行ってください.
本稿が原因で発生するあらゆる損害に対しても責任は負いません.
全て自己責任でお願いします.

  • メーカ保証が受けられなくなる
  • 端末が起動しなくなる
  • データが全て消える

Root化にあたっては Nexus5 と Android5.0preview(LPX13D) で確認しています.
Nexus7ではありません.

1. 用意するもの

Android SDK Tools(adb, fastboot)
開発で使う”いつもの”です. 詳細は省略. fastbootを使うのにAndroidSDKに環境変数PATHを通しておきます.

ブートイメージ - LPX13D
nexus5-hammerhead-lpx13d-kernel.zip

SuperSU.zip
UPDATE-SuperSU-v2.14.zip

ClockworkModリカバリ
Google Nexus 5 Download Touch Recovery 6.0.4.5

2. Root化

Step1. SuperSU.zipを端末にコピー

パスは実行する環境に合わせて読み替えてください.
push先のパスは後ほど指定する必要があるので覚えておいてください.
USBは作業が終わるまで接続し続けてください.

adb push UPDATE-SuperSU-v2.14.zip /mnt/sdcard/

Step2. ブートローダのアンロック

adb reboot bootloader

# 端末再起動されるのでブートローダ起動されたら次を実行. 
# 端末データは初期化されます. これ以降メーカ保証対象外となります. 
fastboot oem unlock

アンロックの再確認があれば”YES”でブートローダアンロックしてください.

Step3. リカバリイメージを書き換える

今回はリカバリイメージをflashしません(問題なければflash).
端末再起動後に再度CWMリカバリモードを起動するにはコマンドを再発行してください.

fastboot boot "recovery-clockwork-touch-6.0.4.5-hammerhead.img"

Step4. SuperSUを導入

Clockworkmodが起動したらadb pushしておいたSuperSU.zipをインストールします.
Clockworkmod画面でパスを辿ってインストールします.

# 下記は例. adb pushした場所まで移動しインストールします. 
install zip > choose zip from /sdcard > /0 > UPDATE-SuperSU-v2.14.zip

インストールの確認があるので”YES”を選択します.

SuperSUのインストールが完了した後は, [GO BACK]を選択してブートローダ画面まで戻ります.

Step5. ブートイメージを導入

ブートイメージ - LPX13D(nexus5-hammerhead-lpx13d-kernel.zip)に含まれるboot.imgを導入します.
こちらもflashはしていません.

fastboot boot boot.img

これで再起動がかかり, root化は一通り完了です. 再起動がかからないようであれば fastboot reboot.

Step6. flash

root化して一通り問題ないことが確認できたら各種イメージの類いをflash(ROM書き込み)しておきます.

# リカバリイメージをflash
fastboot flash boot "recovery-clockwork-touch-6.0.4.5-hammerhead.img"

# bootイメージをflash
fastboot flash boot boot.img

以上です.

2014/10/20

Android:知っておきたい標準API part.2

Intro

Android標準APIの中で知っておくと便利なものがいくつかある.
3rdParty製ライブラリを使うのもいいけれど, 標準で事足りるならそうしたい.
紹介するAPIについてはSupportLibraryを含んでおり, Javaパッケージは対象外.

Data structure

Property

android.util.Property<T, V>
Added in API level 14
URL: http://developer.android.com/reference/android/util/Property.html

A property is an abstraction that can be used to represent a mutable value that is held in a host object. The Property’s set(Object, Object) or get(Object) methods can be implemented in terms of the private fields of the host object, or via “setter” and “getter” methods or by some other mechanism, as appropriate.

ホストオブジェクトが持つ変更可能な値を表現するのに使える抽象的なプロパティ.

Usage

public abstract class FloatProperty<T> extends Property<T, Float> {
    public FloatProperty(String name) {
        super(Float.class, name);
    }

    /**
     * A type-specific override of the {@link #set(Object, Float)} that is faster 
     * when dealing with fields of type <code>float</code>.
     */
    public abstract void setValue(T object, float value);

    @Override
    final public void set(T object, Float value) {
        setValue(object, value);
    }
}

public static final Property<View, Float> X = new FloatProperty<View>("x") {
    @Override
    public void setValue(View object, float value) {
        object.setX(value);
    }

    @Override
    public Float get(View object) {
        return object.getX();
    }
};

CircularArray

android.support.v4.util.CircularArray<E>
URL: http://developer.android.com/reference/android/support/v4/util/CircularArray.html

A circular array implementation that provides O(1) random read and O(1) prepend and O(1) append

リングバッファ. O(1).

TypedValue

android.util.TypedValue
Added in API level 1
URL: http://developer.android.com/reference/android/util/TypedValue.html

Container for a dynamically typed data value. Primarily used with Resources for holding resource values.

動的型付けされたデータコンテナ. 主にリソース値を保持するために使用される.

Usage

// テーマの背景色取得
TypedValue t= new TypedValue();
getTheme().resolveAttribute(android.R.attr.colorBackground, t, true);
int id= typedValue.resourceId;
int color= getResources().getColor(id);

// dp⇒px換算
int padding = (int) TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()); 

Pair

android.util.Pair<F, S>
Added in API level 5
URL: http://developer.android.com/reference/android/util/Pair.html

Container to ease passing around a tuple of two objects. This object provides a sensible implementation of equals(), returning true if equals() is true on each of the contained objects.

“組”を表現するクラス. 格納する型は自由. オブジェクトをペアで管理したい場合に便利. Pair.equals()は”組”となっている双方のオブジェクトと等価である場合にtrueを返す.

Usage

Pair<String, String> pair = Pair.create("android3.0", "Honeycomb");
Log.d(TAG, pair.first);  // android3.0
Log.d(TAG, pair.second);  // Honeycomb

SparseArray

android.util.SparseArray<E>
Added in API level 1
URL: http://developer.android.com/reference/android/util/SparseArray.html

SparseArrays map integers to Objects. Unlike a normal array of Objects, there can be gaps in the indices. It is intended to be more memory efficient than using a HashMap to map Integers to Objects, both because it avoids auto-boxing keys and its data structure doesn’t rely on an extra entry object for each mapping.

スパースアレイ. SparseArrayはintをキーにしたマップオブジェクト. 通常の配列とは異なりインデックスに”隙間”を許容する. SparseArrayはHashMapよりも効率が良い.

Note that this container keeps its mappings in an array data structure, using a binary search to find keys. The implementation is not intended to be appropriate for data structures that may contain large numbers of items. It is generally slower than a traditional HashMap, since lookups require a binary search and adds and removes require inserting and deleting entries in the array. For containers holding up to hundreds of items, the performance difference is not significant, less than 50%.

SparseArrayはキーのルックアップにバイナリサーチを使用するため膨大なデータに対してのパフォーマンスはHashMapに劣る. エントリ数が100程であればパフォーマンス差は50%以下に収まる.

To help with performance, the container includes an optimization when removing keys: instead of compacting its array immediately, it leaves the removed entry marked as deleted. The entry can then be re-used for the same key, or compacted later in a single garbage collection step of all removed entries. This garbage collection will need to be performed at any time the array needs to be grown or the the map size or entry values are retrieved.

コンテナはキーの削除に最適化されている. エントリが削除された場合, すぐに配列をコンパクションするのではなく, 削除マーキングのみを行う. 削除マーカーのついたエントリは再利用されるかGCのタイミングで一括削除される. このGCはArrayのサイズ拡張やサイズ取得の際に実行される.

It is possible to iterate over the items in this container using keyAt(int) and valueAt(int). Iterating over the keys using keyAt(int) with ascending values of the index will return the keys in ascending order, or the values corresponding to the keys in ascending order in the case of valueAt(int).

ketAt(int)やvalueAt(int)を使えば, 配列内をイテレートできる.

Mapインターフェイスの利用を決める前にSparseArrayの利用を検討する.
SparseArrayのキーはint型に限定されており, SparseArrayはint型のキーを持つMap<Integer, Object>と置換可能.
Mapインターフェイスと比べ, SparseArrayは汎用性を犠牲にする代わりに高いパフォーマンスを実現している.
Map

Usage

SparseArray<String> sparseArray = new SparseArray<String>();
sparseArray.put(1, "value");
String str = sparseArray.get(1);

ArrayDeque

java.util.ArrayDeque<E>
Added in API level 9
URL: http://developer.android.com/reference/java/util/ArrayDeque.html

Resizable-array implementation of the Deque interface. Array deques have no capacity restrictions; they grow as necessary to support usage. They are not thread-safe; in the absence of external synchronization, they do not support concurrent access by multiple threads. Null elements are prohibited. This class is likely to be faster than Stack when used as a stack, and faster than LinkedList when used as a queue.

容量制限のない, 非スレッドセーフな, nullを許可しない, リサイズ可能なDeque実装. よくある”使う分だけキャパシティが増える”部類のArray. StackやLinkedListよりも高速に動作する.

Most ArrayDeque operations run in amortized constant time. Exceptions include remove, removeFirstOccurrence, removeLastOccurrence, contains, iterator.remove(), and the bulk operations, all of which run in linear time.

ArrayDequeへの操作は”ならし定数時間(amortized constant time)”で処理される.
remove, removeFirstOccurrence, removeLastOccurrence, contains, iterator.remove(), やbulkオペレーションは線形時間で処理される.

The iterators returned by this class’s iterator method are fail-fast: If the deque is modified at any time after the iterator is created, in any way except through the iterator’s own remove method, the iterator will generally throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

このクラスから得られるiteratorのメソッドはfail-fastに動作する. iterator取得後にdequeが変更されたり, iteratorのremoveメソッドを呼んだりするとConcurrentModificationExceptionを投げる. 並列で同時変更されたような場合にも即座にイテレート処理が失敗する.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

ただし, 一般的に言われているものと同じく, 非同期への確実な保証は無く, fail-fastによるConcurrentModificationExceptionスローはベストエフォートで行われることに注意.

This class and its iterator implement all of the optional methods of the Collection and Iterator interfaces.

このクラスとiteratorは, CollectionおよびIteratorインタフェースのメソッドを実装している.

Pools

android.support.v4.util.Pools
URL: https://developer.android.com/reference/android/support/v4/util/Pools.html

Pools.SimplePool
非スレッドセーフなオブジェクトプール.
Pools.SynchronizedPool
スレッドセーフなオブジェクトプール.
public class MyPooledClass {
    private static final SynchronizedPool sPool =
            new SynchronizedPool(10);

    public static MyPooledClass obtain() {
        MyPooledClass instance = sPool.acquire();
        return (instance != null) ? instance : new MyPooledClass();
    }

    public void recycle() {
         // Clear state if needed.
         sPool.release(this);
    }
    . . .
}

Processor

Linkify

android.text.util.Linkify
Added in API level 1
URL: http://developer.android.com/reference/android/text/util/Linkify.html

Linkify take a piece of text and a regular expression and turns all of the regex matches in the text into clickable links. This is particularly useful for matching things like email addresses, web urls, etc. and making them actionable. Alone with the pattern that is to be matched, a url scheme prefix is also required. Any pattern match that does not begin with the supplied scheme will have the scheme prepended to the matched text when the clickable url is created. For instance, if you are matching web urls you would supply the scheme http://. If the pattern matches example.com, which does not have a url scheme prefix, the supplied scheme will be prepended to create http://example.com when the clickable url link is created.

文字列と正規表現を受け取り, 正規表現にマッチするテキストをリンカブルテキストに置き換える. 一般的にはeメールアドレスやWebアドレスなどに対して使用される. パターンはURLスキームの接頭語にマッチする必要がある. もしスキームを持たずにマッチさせた場合, リンカブルテキストを生成する際に付与させる必要がある. 例えばWebアドレスにマッチさせたい場合はhttp://を指定する. example.comをパターンマッチさせた場合は, リンカブルテキストを作成する際にhttp://example.comとなるようにhttp://を頭に付与する.

Linkify.TransformFilter

android.text.util.Linkify.TransformFilter
Added in API level 1
URL: http://developer.android.com/reference/android/text/util/Linkify.TransformFilter.html

TransformFilter enables client code to have more control over how matched patterns are represented as URLs. For example: when converting a phone number such as (919) 555-1212 into a tel: URL the parentheses, white space, and hyphen need to be removed to produce tel:9195551212.

TransformFilterを使用すると, 特定のパターンにマッチした文字列のURL表現をコントロールできる.
例えば, (919) 555-1212にマッチした文字列に対してスペースなど余分なものを削除してtel:9195551212とすることができる. Linkifyはtechboosterに詳しくある http://techbooster.org/android/ui/13512/

Rfc822Tokenizer

android.text.util.Rfc822Tokenizer
Added in API level 1
URL: http://developer.android.com/reference/android/text/util/Rfc822Tokenizer.html

This class works as a Tokenizer for MultiAutoCompleteTextView for address list fields, and also provides a method for converting a string of addresses (such as might be typed into such a field) into a series of Rfc822Tokens.

このクラスは, アドレスリストフィールドのMultiAutoCompleteTextView用のTokenizerとして機能する. また(フィールドに入力されるような)アドレス文字列を一連のRfc822Tokenに変換するメソッドを提供する.

Rfc822Token

android.text.util.Rfc822Token
Added in API level 1
URL: http://developer.android.com/reference/android/text/util/Rfc822Token.html

This class stores an RFC 822-like name, address, and comment, and provides methods to convert them to quoted strings.

Rfc822TokenにはRFC822-likeのname, address, commentが格納され, これらをquoted stringに変換するメソッドも提供する.

Rfc822Token[] tokens 
        = Rfc822Tokenizer.tokenize("Foo Bar (something) <foo@google.com>");
assertNotNull(tokens);
assertEquals(1,tokens.length);
assertEquals("foo@google.com",tokens[0].getAddress());
assertEquals("Foo Bar",tokens[0].getName());
assertEquals("something",tokens[0].getComment());

Patterns

android.util.Patterns
Added in API level 8
URL: http://developer.android.com/reference/android/util/Patterns.html

Commonly used regular expression patterns.

よく使われるいくつかの正規表現Patternが定義されている(IANA top-level domains, Phone number(looks like.), web url etc…).

Usage

m = Patterns.EMAIL_ADDRESS.matcher(str).matches();
assertTrue("メールアドレスチェック", m);

m= Patterns.TOP_LEVEL_DOMAIN.matcher("com").matches();
assertTrue("トップレベルドメインチェック", m);

m = Patterns.WEB_URL.matcher("http://www.google.com").matches();
assertTrue("WebURLチェック", m);

m = Patterns.WEB_URL.matcher("ftp://www.example.com").matches();
assertFalse("不正なプロトコル", m);

m = Patterns.IP_ADDRESS.matcher("1234.5678.9.0").matches();
assertFalse("不正なIP", m);

m = Patterns.PHONE.matcher("(123) 456-7890").matches();
assertTrue("電番チェック", t);

Others

AndroidException

android.util.AndroidException
Added in API level 1
URL: http://developer.android.com/reference/android/util/AndroidException.html

Base class for all checked exceptions thrown by the Android frameworks.

Android Frameworkが投げたことを意味する例外. AndroidExceptionを継承したサブクラスは次の通り.

IntentFilter.MalformedMimeTypeException
This exception is thrown when a given MIME type does not have a valid syntax.
IntentSender.SendIntentException
Exception thrown when trying to send through a PendingIntent that has been canceled or is otherwise no longer able to execute the request.
PackageManager.NameNotFoundException
This exception is thrown when a given package, application, or component name cannot be found.
PendingIntent.CanceledException
Exception thrown when trying to send through a PendingIntent that has been canceled or is otherwise no longer able to execute the request.
RemoteException
Parent exception for all Binder remote-invocation errors
Settings.SettingNotFoundException
-
DeadObjectException
The object you are calling has died, because its hosting process no longer exists.
TransactionTooLargeException
The Binder transaction failed because it was too large.

LogPrinter

android.util.LogPrinter
Added in API level 1
URL: http://developer.android.com/reference/android/util/LogPrinter.html

Implementation of a Printer that sends its output to the system log.

System logを出力するPrinterの実装. LogCat内部で使用されている.

EventLog

android.util.EventLog
Added in API level 8
URL: http://developer.android.com/reference/android/util/EventLog.html

Access to the system diagnostic event record. System diagnostic events are used to record certain system-level events (such as garbage collection, activity manager state, system watchdogs, and other low level activity), which may be automatically collected and analyzed during system development.

システム診断イベントレコードへのアクセスクラス. システム診断イベントにはシステムレベルのイベント(GC, ActivityManagerState, watchdog, 低次レイヤーイベントなど)が含まれている. このイベントは自動収集されてシステム開発に活かされる.

This is not the main “logcat” debugging log (Log)! These diagnostic events are for system integrators, not application authors.

これはLogcatのようなアプリのためのログシステムではない.

Events use integer tag codes corresponding to /system/etc/event-log-tags. They carry a payload of one or more int, long, or String values. The event-log-tags file defines the payload contents for each type code.

イベントには整数タグコードが使用され, /system/etc/event-log-tagsに対応している. ペイロードは1つ以上のint, long, Stringの値で構成され, event-log-tagsファイルには各タイプコードに対応するペイロードの内容が定義されている.

EventLogはadb logcatのeventsバッファから収集するか, DDMSのイベントログタブから参照できる.

IntentSender

android.content.IntentSender
Added in API level 4
URL: http://developer.android.com/reference/android/content/IntentSender.html

A description of an Intent and target action to perform with it. The returned object can be handed to other applications so that they can perform the action you described on your behalf at a later time.

Intentを実行するIntentSender. IntentSenderのオブジェクトを他アプリケーションに渡すことで, あなたのアプリケーションに変わって他アプリがIntentを後から実行できるようになる.

By giving a IntentSender to another application, you are granting it the right to perform the operation you have specified as if the other application was yourself (with the same permissions and identity). As such, you should be careful about how you build the IntentSender: often, for example, the base Intent you supply will have the component name explicitly set to one of your own components, to ensure it is ultimately sent there and nowhere else.

IntentSenderを他アプリケーションに渡すことはIntent実行に必要な権限やアイデンティティまで渡すことと同義である. よくある方法としては, 自身のコンポーネントを指定した明示的IntentをセットしたIntentSenderを渡して, Intentを受け取った自コンポーネントで想定されたSenderからのリクエストかをチェックする.

A IntentSender itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that, even if its owning application’s process is killed, the IntentSender itself will remain usable from other processes that have been given it. If the creating application later re-retrieves the same kind of IntentSender (same operation, same Intent action, data, categories, and components, and same flags), it will receive a IntentSender representing the same token if that is still valid.

IntentSender自体はSystemによって記述されるTokenを単純に参照するものである. つまり, IntentSenderを生成したプロセスがkillされてもなお有効であることを意味する. もしアプリ起動後に再度同じIntentSender(同じoperation, intent action, data, category, component, flag)を取得した場合, 有効であるなら同じtokenを受け取ることになる.

Instances of this class can not be made directly, but rather must be created from an existing PendingIntent with PendingIntent.getIntentSender().

このクラスは直接生成するのではなく, PendingIntent.getIntentSender()から取得すること.

CancellationSignal

android.os.CancellationSignal
Added in API level 16
URL: http://developer.android.com/reference/android/os/CancellationSignal.html

Provides the ability to cancel an operation in progress.

処理のキャンセル要求を表現するクラス. これをサポートしたクラスにシグナル送信することでキャンセル要求を発出できる. ContentProviderや, AsyncTaskLoaderがこれをサポートしている.

参考: Android:CancellationSignalで処理を中断する

// Client
try {
    Cursor cursor = getContentResolver().query(
            Uri.parse("content://yuki.mycontentprovider"),
            new String[] { "_id" }, null, null, null, mCancelSignal);
} catch (OperationCanceledException ex) {
    // do something.
}

// ContentProvider
@Override
public Cursor query(Uri uri, String[] projection, String selection,
        String[] selectionArgs, String sortOrder,
        CancellationSignal cancellationSignal) {
    SQLiteDatabase db = mDataBaseHelper.getReadableDatabase();
    Cursor c = db.query(false, "test", projection,
            selection, selectionArgs, null, null, sortOrder, null,
            cancellationSignal);
    ... 略 ...
}

以上.