同步适配器框架旨在与由灵活且高度安全的内容提供程序框架管理的设备数据一起使用。因此,同步适配器框架期望使用该框架的应用已为其本地数据定义了内容提供程序。如果同步适配器框架尝试运行您的同步适配器,而您的应用没有内容提供程序,则您的同步适配器会崩溃。
如果您正在开发一个将数据从服务器传输到设备的新应用,则应认真考虑将本地数据存储在内容提供程序中。除了对同步适配器的重要性之外,内容提供程序还提供各种安全优势,并且专门设计用于处理 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>
现在,您已创建了同步适配器框架所需的相关依赖项,您可以创建封装数据传输代码的组件。此组件称为同步适配器。下一课将向您展示如何将此组件添加到您的应用中。