Androidでリソースを共有すると言えばコンテンツプロパイダがありますが、今回はsharedUserIdを使っての共有方法を整理しました。
概念
AndroidのベースとなっているのはLinuxカーネルです。
Linux文化を継承した権限構成になっており、app毎に割り振られているユーザーIDが割り振られます*1。
今回は共有IDを作り、apkの権限に加えて同じID同士で参照し合えるようにします*2。
サンプルコード構成
apk1側の(apk1と描かれた)画像とapk2側の(apk2と描かれた)画像を、apk1側のプログラムで一緒に表示させます。
apk2側のコード
リソースを読まれる側のコード
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="jp.hyoromo.apk2" android:versionCode="1" android:versionName="1.0" sharedUserId="jp.hyoromo.apk1" > <application android:icon="@drawable/icon" android:label="@string/app_name" > </application> <uses-sdk android:minSdkVersion="4" /> </manifest>
manifestタグにsharedUserIdを追加します。
UserIDは他と被らないよう"パッケージ名+α"が良いと思います、ここでは"読み込み側のパッケージ名"にしています。
res/drawable
apk2.png を配置。
apk1側のコード
リソースを読む側のコード
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="jp.hyoromo.apk1" android:versionCode="1" android:versionName="1.0" sharedUserId="jp.hyoromo.apk1" > <application android:icon="@drawable/icon" android:label="@string/app_name" > <activity android:name=".apk1" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="4" /> </manifest>
apk2と同じくmanifestタグにsharedUserIdを同じ値で設定しています。
res/drawable
apk1.png を配置。
layout/main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/img_apk1" android:layout_width="wrap_content" android:layout_height="wrap_content" ></ImageView> <ImageView android:id="@+id/img_apk2" android:layout_width="wrap_content" android:layout_height="wrap_content" ></ImageView> </LinearLayout>
src/jp.hyoromo.apk1
public class apk1 extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // apk1表示 ImageView imgApk1 = (ImageView) findViewById(R.id.img_apk1); imgApk1.setBackgroundResource(R.drawable.apk1); // apk2表示 ImageView imgApk2 = (ImageView) findViewById(R.id.img_apk2); try { // 読み込み先のパッケージ名を指定してcontext作成 Context context = this.createPackageContext("jp.hyoromo.apk2", Context.CONTEXT_RESTRICTED); Resources res = context.getResources(); // R.javaを直接読んでリソースIDを取得。apk2をeclipseでビルドパス追加してる場合は、いつもの方法でおk int id = res.getIdentifier("apk2", "drawable", "jp.hyoromo.apk2"); imgApk2.setBackgroundDrawable(res.getDrawable(id)); } catch (NameNotFoundException e) { } } }
読み込み先のパスは"jp.hyoromo.apk2"。リソースを読むときはパッケージの指定が重要になります。
参考
kazzzさんの日記が凄い参考になりました。参考にしたと言うよりコピp...ありがとうござました!
apk(パッケージ)リソースを共有する
他パッケージ(他のapk)のリソースを読む part2