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

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

サーバーからデバイスにデータを転送する新しいアプリを開発する場合は、ローカルデータをコンテンツ プロバイダに保存することを強くおすすめします。コンテンツ プロバイダは、同期アダプターの重要性に加えて、さまざまなセキュリティ上のメリットを提供しており、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>

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