hyoromoのブログ

iOS/AndroidもしくはCocos2dxネタを書いています

リソースの共有 〜ピクチャー共有したいんです〜

Androidでリソースを共有すると言えばコンテンツプロパイダがありますが、今回はsharedUserIdを使っての共有方法を整理しました。

今回やることの図解

zu

概念

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"。リソースを読むときはパッケージの指定が重要になります。

結果

device1
apk1側のapk1画像とapk2側のapk2画像が仲良く並びました。

参考

kazzzさんの日記が凄い参考になりました。参考にしたと言うよりコピp...ありがとうござました!
apk(パッケージ)リソースを共有する
他パッケージ(他のapk)のリソースを読む part2

*1:アプリ=ユーザーの考え

*2:グループIDに近い考え