スタブ コンテンツ プロバイダを作成する

同期アダプター フレームワークは、安全性の高い柔軟なコンテンツ プロバイダ フレームワークで管理されたデバイスデータを操作できるように設計されています。このため、同期アダプター フレームワークでは、そのフレームワークを使用するアプリで、そのローカルデータに対してコンテンツ プロバイダがすでに定義されているものと見なされます。 同期アダプター フレームワークが同期アダプターを実行しようとする際にアプリにコンテンツ プロバイダがないと、同期アダプターはクラッシュします。

サーバーからデバイスにデータを転送する新しいアプリを開発する場合は、コンテンツ プロバイダにローカルデータを保存することを検討してください。コンテンツ プロバイダは、同期アダプターにとって重要ですが、それ以外にもさまざまなセキュリティ上のメリットがあり、特に Android システムでデータ ストレージを処理するために設計されています。コンテンツ プロバイダの作成について詳しくは、コンテンツ プロバイダの作成をご覧ください。

ただし、ローカルデータを別の形式で保存している場合は、引き続き同期アダプターを使用してデータ転送を処理できます。コンテンツ プロバイダの同期アダプター フレームワークの要件を満たすには、スタブ コンテンツ プロバイダをアプリに追加します。スタブ プロバイダはコンテンツ プロバイダ クラスを実装しますが、その必須メソッドはすべて null または 0 を返します。スタブ プロバイダを追加すると、同期アダプターを使用して任意のストレージ メカニズムからデータを転送できます。

アプリにコンテンツ プロバイダがすでにある場合、スタブ コンテンツ プロバイダは必要ありません。 その場合はこのレッスンをスキップして、同期アダプターの作成に進んでください。コンテンツ プロバイダがまだない場合は、このレッスンをご覧ください。ここでは、スタブ コンテンツ プロバイダを追加する方法について説明します。スタブ コンテンツ プロバイダを使用すると、同期アダプターをフレームワークに接続できます。

スタブ コンテンツ プロバイダを追加する

アプリのスタブ コンテンツ プロバイダを作成するには、ContentProvider クラスを拡張して必要なメソッドをスタブ化します。次のスニペットは、スタブ プロバイダを作成する方法を示しています。

Kotlin

    /*
     * Define an implementation of ContentProvider that stubs out
     * all methods
     */
    class StubProvider : ContentProvider() {
        /*
         * Always return true, indicating that the
         * provider loaded correctly.
         */
        override fun onCreate(): Boolean  = true

        /*
         * Return no type for MIME type
         */
        override fun getType(uri: Uri): String?  = null

        /*
         * query() always returns no results
         *
         */
        override fun query(
                uri: Uri,
                projection: Array<String>,
                selection: String,
                selectionArgs: Array<String>,
                sortOrder: String
        ): Cursor?  = null

        /*
         * insert() always returns null (no URI)
         */
        override fun insert(uri: Uri, values: ContentValues): Uri? = null

        /*
         * delete() always returns "no rows affected" (0)
         */
        override fun delete(uri: Uri, selection: String, selectionArgs: Array<String>): Int = 0

        /*
         * update() always returns "no rows affected" (0)
         */
        override fun update(
                uri: Uri,
                values: ContentValues,
                selection: String,
                selectionArgs: Array<String>
        ): Int = 0
    }
    

Java

    /*
     * Define an implementation of ContentProvider that stubs out
     * all methods
     */
    public class StubProvider extends ContentProvider {
        /*
         * Always return true, indicating that the
         * provider loaded correctly.
         */
        @Override
        public boolean onCreate() {
            return true;
        }
        /*
         * Return no type for MIME type
         */
        @Override
        public String getType(Uri uri) {
            return null;
        }
        /*
         * query() always returns no results
         *
         */
        @Override
        public Cursor query(
                Uri uri,
                String[] projection,
                String selection,
                String[] selectionArgs,
                String sortOrder) {
            return null;
        }
        /*
         * insert() always returns null (no URI)
         */
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            return null;
        }
        /*
         * delete() always returns "no rows affected" (0)
         */
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            return 0;
        }
        /*
         * update() always returns "no rows affected" (0)
         */
        public int update(
                Uri uri,
                ContentValues values,
                String selection,
                String[] selectionArgs) {
            return 0;
        }
    }
    

マニフェストでプロバイダを宣言する

同期アダプター フレームワークは、アプリがプロバイダをアプリ マニフェストで宣言しているかどうかを確認することにより、そのアプリにコンテンツ プロバイダがあるかどうかを確かめます。マニフェストでスタブ プロバイダを宣言するには、次の属性を持つ <provider> 要素を追加します。

android:name="com.example.android.datasync.provider.StubProvider"
スタブ コンテンツ プロバイダを実装するクラスの完全修飾名を指定します。
android:authorities="com.example.android.datasync.provider"
スタブ コンテンツ プロバイダを特定する URI 認証局。この値に「provider」という文字列を末尾に付けて、アプリのパッケージ名にします。システムに対してスタブ プロバイダを宣言しても、プロバイダ自体にアクセスが試みられることはありません。
android:exported="false"
他のアプリがコンテンツ プロバイダにアクセスできるかどうかを判断します。スタブ コンテンツ プロバイダの場合は、他のアプリでプロバイダを表示できるようにする必要がないため、値を false に設定します。この値は、同期アダプター フレームワークとコンテンツ プロバイダ間のやり取りには影響しません。
android:syncable="true"
プロバイダが同期可能であることを示すフラグを設定します。このフラグを true に設定した場合、コードで setIsSyncable() を呼び出す必要はありません。フラグによって、同期アダプター フレームワークとコンテンツ プロバイダとの間でデータ転送が可能になりますが、転送を行うにはそれを明示的に指定する必要があります。

次のスニペットは、アプリ マニフェストに <provider> 要素を追加する方法を示しています。

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.android.network.sync.BasicSyncAdapter"
        android:versionCode="1"
        android:versionName="1.0" >
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
        ...
        <provider
            android:name="com.example.android.datasync.provider.StubProvider"
            android:authorities="com.example.android.datasync.provider"
            android:exported="false"
            android:syncable="true"/>
        ...
        </application>
    </manifest>
    

同期アダプター フレームワークに必要な依存関係を作成したら、データ転送コードをカプセル化するコンポーネントを作成できます。このコンポーネントは、同期アダプターと呼ばれます。次のレッスンでは、このコンポーネントをアプリに追加する方法について説明します。