2011年2月25日金曜日

Android 別々のアプリで SharedPreferences を共有

SharedPreferences を作成するときには、ファイル作成のモードとして以下の4つが選択できます。

MODE_PRIVATE (0x00)
 ファイル作成モード
 デフォルトのモード
 getSharedPreferences を呼んだ(= ファイルを作成した) アプリケーションからのみアクセスできる(ただし、同じ user ID を共有しているアプリケーションもアクセスできる)

MODE_WORLD_READABLE (0x01)
 ファイル作成モード
 他の全てのアプリケーションが読み込みアクセス権限をもつ

MODE_WORLD_WRITEABLE (0x02)
 ファイル作成モード
 他の全てのアプリケーションが書き込みアクセス権限をもつ

MODE_MULTI_PROCESS (0x04)
 SharedPreference の読み込みフラグ
 たとえプロセス内ですでに shared preferences インスタンスがロードされていても、編集のためにディスク上のファイルをチェックする。複数のプロセスをもつアプリケーションで、それらが同じ SharedPreferences ファイルに書き込みをする場合に必要となる。

# MODE_MULTI_PROCESS は API Level 11 (= Android 3.0 で追加されたAPI) です。

getSharedPreferences の第2引数に上記のモードを設定します。

SharedPreferences mSharedPreferences = getSharedPreferences("yanzm_name", MODE_WORLD_READABLE);
Editor prefsPrivateEditor = mSharedPreferences.edit();
prefsPrivateEditor.putString("name", "yanzm");
prefsPrivateEditor.commit();


この yanzm_name という SharedPreference ファイルを別のアプリケーション (= 別のパッケージ) から読むには、yanzm_name を作成したパッケージの Context を生成する必要があります。


try {
Context mContext = createPackageContext("yanzm.example.hoge", CONTEXT_RESTRICTED);

SharedPreferences mSharedPreferences = mContext.getSharedPreferences(
"yanzm_name",
Context.MODE_PRIVATE);

String name = mSharedPreferences.getString("name", "");
} catch (NameNotFoundException e) {
Log.e("SharedPref", e.getLocalizedMessage());
}


createPackageContext() で SharedPreference を作ったパッケージの Context オブジェクトを作成します。


createPackageContext (String packageName, int flags)

 起動時と同じ Context を返す
 同じリソース、クラスローダーを含む
 このメソッドの呼び出しごとに新しい Context オブジェクトのインスタンスを返す
 Context オブジェクト自体は share されないが、common state (Resources, ClassLoader など) は share するので、Content instance 自身はとても軽量

第1引数にはアプリケーションのパッケージ名を指定します。
パッケージ名に相当するアプリない場合 PackageManager.NameNotFoundException
が発行されます。

第2引数に設定するフラグには次の3つがあります。

CONTEXT_INCLUDE_CODE (0x01)
 アプリケーションコードを含む Context
 つまり、呼んだプロセス内にコードがロードされるので、アプリケーションのクラスをインスタンスするのに getClassLoader() を使うことができる。このフラグをセットすることでどのアプリケーション Context にアクセスできるかのセキュリティ制限を設定する。リクエストしたアプリケーションがプロセスにとって安全ではない場合 java.lang.SecurityException が発行される。このフラグがセットされていない場合、ロード可能なパッケージ上に制限はないが、 getClassLoader() は常にデフォルトシステムの class loader を返す。

CONTEXT_IGNORE_SECURITY (0x02)
 要求されている Context 上のすべてのセキュリテイ制限を無視し、常にロードを許可する。CONTEXT_INCLUDE_CODE と一緒に使うと、たとえそれが安全でなくても、プロセス内にコードがロードされるので、使うときは十分注意すること!
 
CONTEXT_RESTRICTED (0x04)
 特定の機能が無効になった制限された Context
 例えば、制限された Context に関連する View は特定の XML 属性を無視する

このフラグの設定とアプリケーションの SharedUserId によっては java.lang.SecurityException が投げられます。


ShareUserId が違う場合で試してみました。

その1 CONTEXT_INCLUDE_CODE だけ --- SecurityException

Caused by: java.lang.SecurityException: Requesting code from yanzm.example.hoge (with uid 10117) to be run in process yanzm.example.hogehoge (with uid 10064)

その2 CONTEXT_INCLUDE_CODE | CONTEXT_RESTRICTED --- SecurityException

Caused by: java.lang.SecurityException: Requesting code from yanzm.example.hoge (with uid 10117) to be run in process yanzm.example.hogehoge (with uid 10064)

その3 CONTEXT_RESTRICTED だけ --- OK

その4 CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY --- OK

その5 CONTEXT_IGNORE_SECURITY だけ --- OK



 

0 件のコメント:

コメントを投稿