创建桩内容提供器

同步适配器框架专用于处理由灵活且高度安全的内容提供器框架管理的数据。因此,同步适配器框架要求使用它的应用具备为其本地数据定义的内容提供器。如果同步适配器框架尝试运行您的同步适配器时,您的应用不具有内容提供器,您的同步适配器将会崩溃。

如果您正在开发将数据从服务器传输到设备的新应用,则强烈建议您将本地数据存储在内容提供器中。除了对于同步适配器十分重要之外,内容提供器还提供各种安全优势,并且是专为处理 Android 系统上的数据存储而设计的。要详细了解如何创建内容提供器,请参阅创建内容提供器

不过,即便您已经以其他方式存储本地数据,您仍然可以使用同步适配器来处理数据传输。为了满足同步适配器框架对于内容提供器的要求,可以在您的应用中添加桩内容提供器。桩提供器会实现内容提供器类,但其所有必需的方法都会返回 null0。如果添加了桩提供器,则可以使用同步适配器从您选择的任何存储机制传输数据。

如果您的应用中已经有内容提供器,则不需要添加桩内容提供器。在这种情况下,您可以跳过这节课,继续学习创建同步适配器一课。如果您还没有内容提供器,本课将为您介绍如何添加桩内容提供器,以便您将同步适配器插入到框架中。

添加桩内容提供器

要为您的应用创建桩内容提供器,请扩展 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>
    

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