Android 培训

创建Stub Content Provider

编写:jdneo - 原文:http://developer.android.com/training/sync-adapters/creating-stub-provider.html

Sync Adapter框架是设计成用来和设备数据一起工作的,而这些设备数据应该被灵活且安全的Content Provider管理。因此,Sync Adapter框架会期望应用已经为它的本地数据定义了Content Provider。如果Sync Adapter框架尝试去运行你的Sync Adapter,而你的应用没有一个Content Provider的话,那么你的Sync Adapter将会崩溃。

如果你正在开发一个新的应用,它将数据从服务器传输到一台设备上,那么你务必应该考虑将本地数据存储于Content Provider中。除了它对于Sync Adapter的重要性之外,Content Provider还可以提供许多安全上的好处,更何况它是专门为了在Android设备上处理数据存储而设计的。要学习如何创建一个Content Provider,可以阅读:Creating a Content Provider

然而,如果你已经通过别的形式来存储本地数据了,你仍然可以使用Sync Adapter来处理数据传输。为了满足Sync Adapter框架对于Content Provider的要求,可以在你的应用中添加一个Stub Content Provider。一个Stub Content Provider实现了Content Provider类,但是所有的方法都返回null或者0。如果你添加了一个Stub Content Provider,无论你的数据存储机制是什么,你都可以使用Sync Adapter来传输数据。

如果在你的应用中已经有了一个Content Provider,那么你就不需要创建Stub Content Provider了。在这种情况下,你可以略过这节课程,直接进入:创建Sync Adapter。如果你还没有创建Content Provider,这节课将向你展示如何通过添加一个Stub Content Provider,将你的Sync Adapter添加到框架中。

添加一个Stub Content Provider

要为你的应用创建一个Stub Content Provider,首先继承ContentProvider类,并且在所有需要重写的方法中,我们一律不进行任何处理而是直接返回。下面的代码片段展示了你应该如何创建一个Stub Content Provider:

/*
 * 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 an empty String for MIME type
     */
    @Override
    public String getType() {
        return new String();
    }
    /*
     * 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;
    }
}

在Manifest清单文件中声明提供器

Sync Adapter框架会通过查看应用的清单文件中是否含有<provider>标签,来验证你的应用是否使用了Content Provider。为了在清单文件中声明我们的Stub Content Provider,添加一个<provider>标签,并让它拥有下列属性字段:

android:name="com.example.android.datasync.provider.StubProvider"

指定实现Stub Content Provider类的完整包名。

android:authorities="com.example.android.datasync.provider"

指定Stub Content Provider的URI Authority。用应用的包名加上字符串".provider"作为该属性字段的值。虽然你在这里向系统声明了你的Stub Content Provider,但是这并不会导致对该Provider的访问。

android:exported="false"

确定其它应用是否可以访问Content Provider。对于Stub Content Provider而言,由于没有让其它应用访问该Provider的必要,所以我们将该值设置为false。该值并不会影响Sync Adapter框架和Content Provider之间的交互。

android:syncable="true"

该标识指明Provider是可同步的。如果将这个值设置为true,你将不需要在代码中调用setIsSyncable()。这一标识将会允许Sync Adapter框架和Content Provider进行数据传输,但是仅仅在你显式地执行相关调用时,这一传输时才会进行。

下面的代码片段展示了你应该如何将<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>

现在你已经创建了所有Sync Adapter框架所需要的依赖项,接下来你可以创建封装数据传输代码的组件了。该组件就叫做Sync Adapter。在下节课中,我们将会展示如何将这一组件添加到你的应用中。