创建存根内容提供程序

同步适配器框架旨在与通过灵活且高度安全的 content provider 框架管理的设备数据一起使用。因此,同步适配器框架期望使用该框架的应用程序已经为其本地数据定义了 content provider。如果同步适配器框架尝试运行您的同步适配器,而您的应用程序没有 content provider,则您的同步适配器会崩溃。

如果您正在开发一个将数据从服务器传输到设备的新应用程序,您应该认真考虑将本地数据存储在 content provider 中。除了对同步适配器的重要性外,content provider 还提供了各种安全优势,并且专门设计用于处理 Android 系统上的数据存储。要了解有关创建 content provider 的更多信息,请参阅创建内容提供程序

但是,如果您已经以其他形式存储本地数据,您仍然可以使用同步适配器来处理数据传输。为了满足同步适配器框架对 content provider 的要求,请将存根内容提供程序添加到您的应用程序。存根提供程序实现 content provider 类,但其所有必需方法都返回null0。如果您添加了存根提供程序,您就可以使用同步适配器从您选择的任何存储机制传输数据。

如果您已经在应用程序中拥有 content provider,则不需要存根 content provider。在这种情况下,您可以跳过此课程并继续进行创建同步适配器课程。如果您还没有 content provider,本课程将向您展示如何添加存根 content provider,使您能够将同步适配器插入框架。

添加存根内容提供程序

要为您的应用程序创建存根内容提供程序,请扩展类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;
    }
}

在清单中声明提供程序

同步适配器框架通过检查您的应用程序是否在其应用程序清单中声明了提供程序来验证您的应用程序是否具有 content provider。要在清单中声明存根提供程序,请添加一个<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>

现在您已经创建了同步适配器框架所需的依赖项,您可以创建封装数据传输代码的组件。此组件称为同步适配器。下一课将向您展示如何在您的应用程序中添加此组件。