ContentProviderでデータを共有する その2

前回に引き続き、ContentProviderの使い方について説明します。

前回のContentProviderを使った記事では、作成したアプリケーションのDBに対して、不特定多数のアプリからアクセス出来る事を確認しました。

しかし、不特定多数のアプリからではなく、特定のアプリケーションにのみアクセスを許可したい場合もあると思います。


今回はContentProviderとPermissionを使って、署名が同じアプリケーションのみDBアクセスが可能なアプリケーションを作成してみようと思います。


前回作成したプロジェクトをそのまま流用しますので、プロジェクトの作成はこちらを参照してください。
又、プロジェクトを作成するのが面倒な方は、こちらよりプロジェクト一式をダウンロードできます。 → http://www.geocities.jp/finnissy/Blog/android_A_B.zip


これより先は、既に上記プロジェクトが用意されているものとして説明します。

プロジェクト「A」の変更点

  • Permissionを作成する
  • 作成したPermissionをContentProviderに適用する

プロジェクト「B」の変更点

  • プロジェクトAの作成したPermissionに対するアクセスを宣言する
  • SecurityExceptionが発生した際の処理を追記


同じ証明書で署名したアプリは、次のようにアクセス可能ですが、・・・



アクセスするアプリの証明書が違った場合は、例外が発生します。


プロジェクトAの変更

マニフェストファイルにPermissionを追加します。具体的には次のようにします。

<uses-permission
        android:name="hoge.hoge.hatena.A.permission.DB"/>
<permission android:protectionLevel="signature" 
        android:name="hoge.hoge.hatena.A.permission.DB">
</permission>

protectionLevelをsignatureにする事で、同じ証明書からアクセスできるようになります。


ContentProviderに対して、作成したPermissionを適用します。

<provider
    android:name=".HelloProvider"
    android:authorities="hoge.hoge.hatena.A.HELLO_DATABASE"
    android:permission="hoge.hoge.hatena.A.permission.DB">
</provider>




プロジェクトBの変更

マニフェストファイルに、プロジェクトAのPermissionを使用することを宣言します。

<uses-permission
         android:name="hoge.hoge.hatena.A.permission.DB" />



例外発生時の処理をHelloクラスに追記。

try {
    getIntent().setData(Uri.parse(CONTENT));
    c = managedQuery(getIntent().getData(), null, null,null,null);
    if (c != null) {
        
        HelloTable q = new HelloTable();
        HelloTable []bean = q.makeData(c);
        
        if (bean != null) {
            
            list.setAdapter(new HelloListAdapter(this, 0, bean));
        }
    } else {
        
        //データが存在しない場合
        Log.d(TAG, "result 0items");
        ArrayAdapter<String> ad = new ArrayAdapter<String>(
                this, android.R.layout.simple_list_item_1);
        ad.add("No Data");
        list.setAdapter(ad);
    }
} catch (SecurityException e) {
    
    //データが存在しない場合
    Log.d(TAG, e.toString());
    ArrayAdapter<String> ad = new ArrayAdapter<String>(
            this, android.R.layout.simple_list_item_1);
    ad.add("SecurityException!!");
    list.setAdapter(ad);
}


異なる証明書でアクセス出来ないことを確認

普段、Eclipseからアプリのインストールをする際は、デフォルトの証明書を使っていると思います。
違う証明書での確認をするためには、証明書が二つ必要ですので、予め証明書を作成しておいてください。
証明書の作成については、他サイトを参考にしてもらえれば良いと思います。


次に、Emulaterか実機を用意します。
そして、先ほど作成した証明書で署名したアプリAを、コマンドラインからインストール。
(インストール方法については、こちらで詳しく説明されてます)
その次に、デフォルトの証明書で署名したアプリBを、インストールします。
アプリBからはアクセスできなくて、次のようになる筈です。




同じ証明書でアクセスできることを確認

今度はアプリBにも、先ほど作成した証明書で署名。
そして、コマンドラインからインストールします。(インストールする前に、アプリBは削除しておきます)
同じ証明書で署名したアプリなので、Permissionのプロテクトにも引っかからず、SecurityExceptionが出ることも無いと思います。



今回の記事については、こちらを参考にしました。 → http://d.hatena.ne.jp/haruser/20090823/1251042430