Ben*_*Ben 112 android android-contentprovider android-syncadapter
我正在尝试实现Google IO中讨论的内容提供商同步适配器模式- 幻灯片26.我的内容提供商正在工作,当我从Dev Tools Sync Tester应用程序触发它时,我的同步工作,但是当我调用ContentResolver时.来自我的ContentProvider的requestSync(帐户,权限,捆绑),我的同步永远不会被触发.
ContentResolver.requestSync(
account,
AUTHORITY,
new Bundle());
Run Code Online (Sandbox Code Playgroud)
编辑 - 添加的清单片段我的清单xml包含:
<service
android:name=".sync.SyncService"
android:exported="true">
<intent-filter>
<action
android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
Run Code Online (Sandbox Code Playgroud)
- 编辑
与我的同步服务关联的syncadapter.xml包含:
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="AUTHORITY"
android:accountType="myaccounttype"
android:supportsUploading="true"
/>
Run Code Online (Sandbox Code Playgroud)
不确定其他代码会有用.传递给requestSync的帐户是"myaccounttype",传递给调用的AUTHORITY与我的syc适配器xml匹配.
ContentResolver.requestSync是否是请求同步的正确方法?看起来同步测试工具直接绑定到服务并调用启动同步,但这似乎违背了与同步架构集成的目的.
如果这是请求同步的正确方法,那么同步测试器为什么会工作,而不是我对ContentResolver.requestSync的调用?我需要在捆绑中传递一些东西吗?
我正在运行2.1和2.2的设备上的模拟器中进行测试.
jcw*_*ger 280
呼叫requestSync()仅适用于系统已知的{Account,ContentAuthority}对.您的应用需要经过多个步骤告诉Android您能够使用特定类型的帐户同步特定类型的内容.它在AndroidManifest中执行此操作.
1.通知Android您的应用程序包提供同步
首先,在AndroidManifest.xml中,您必须声明您有一个同步服务:
<service android:name=".sync.mySyncService" android:exported="true">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/sync_myapp" />
</service>
Run Code Online (Sandbox Code Playgroud)
<service>标签的name属性是连接同步的类的名称...我将在一秒钟内与之交谈.
设置导出的true使其对其他组件可见(需要这样ContentResolver才能调用它).
意图过滤器允许它捕获请求同步的意图.(这Intent来自ContentResolver您调用ContentResolver.requestSync()或相关的调度方法时.)
该<meta-data>标签将在下面讨论.
2.为Android提供用于查找SyncAdapter的服务
所以班级本身......这是一个例子:
public class mySyncService extends Service {
private static mySyncAdapter mSyncAdapter = null;
public SyncService() {
super();
}
@Override
public void onCreate() {
super.onCreate();
if (mSyncAdapter == null) {
mSyncAdapter = new mySyncAdapter(getApplicationContext(), true);
}
}
@Override
public IBinder onBind(Intent arg0) {
return mSyncAdapter.getSyncAdapterBinder();
}
}
Run Code Online (Sandbox Code Playgroud)
你的类必须扩展Service或者它的一个子类必须实现public IBinder onBind(Intent),并且必须SyncAdapterBinder在调用时返回...你需要一个类型的变量AbstractThreadedSyncAdapter.所以你可以看到,那几乎是那个班级的一切.它的唯一原因是提供一个服务,它为Android提供了一个标准界面,可以向您的班级查询您SyncAdapter自己的内容.
3.提供class SyncAdapter实际执行同步的功能.
mySyncAdapter是存储真实同步逻辑的地方.它的onPerformSync()方法在同步时被调用.我想你已经有了这个.
4.在Account-type和Content Authority之间建立绑定
再回顾AndroidManifest,<meta-data>我们服务中的那个奇怪的标签是建立ContentAuthority和帐户之间绑定的关键部分.它从外部引用另一个xml文件(无论你喜欢什么,都可以调用它,与你的app相关.)让我们看一下sync_myapp.xml:
<?xml version="1.0" encoding="utf-8" ?>
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="com.android.contacts"
android:accountType="com.google"
android:userVisible="true" />
Run Code Online (Sandbox Code Playgroud)
好的,那又是什么呢?它告诉Android我们定义的同步适配器(在<service>包含<meta-data>引用此文件的标记的标记的name元素中调用的类...)将使用com.google样式帐户同步联系人.
您的所有contentAuthority字符串必须全部匹配,并与您正在同步的内容匹配 - 如果您正在创建自己的数据库,那么这应该是您定义的字符串,或者如果您正在同步,则应该使用一些现有的设备字符串数据类型(如联系人或日历事件或你有什么.)以上("com.android.contacts")碰巧是联系人类型数据的ContentAuthority字符串(惊讶,惊讶).
accountType还必须匹配已输入的已知帐户类型之一,或者必须匹配您正在创建的帐户类型(这涉及创建AccountAuthenticator的子类以在您的服务器上获取身份验证......值得一篇文章本身.)同样,"com.google"是用于标识... google.com样式帐户凭据的已定义字符串(同样,这不应该是一个惊喜.)
5.在给定的Account/ContentAuthority对上启用同步
最后,必须启用同步.您可以在控制面板的"帐户和同步"页面中执行此操作,方法是转到您的应用并在匹配的帐户中设置应用旁边的复选框.或者,您可以在应用中的某些设置代码中执行此操作:
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
Run Code Online (Sandbox Code Playgroud)
要进行同步,必须启用您的帐户/权限对进行同步(如上所述),并且必须设置系统上的整体全局同步标志,并且设备必须具有网络连接.
如果您的帐户/权限同步或全局同步被禁用,则调用RequestSync()确实有效 - 它设置了一个已请求同步的标志,并将在同步启用后立即执行.
另外,根据mgv,ContentResolver.SYNC_EXTRAS_MANUAL在requestSync的extras包中设置为true将要求android强制同步,即使全局同步已关闭(尊重您的用户!)
最后,您可以使用ContentResolver函数再次设置定期计划同步.
6.考虑多个帐户的含义
可以有多个相同类型的帐户(在一个设备上设置两个@ gmail.com帐户或两个facebook帐户,或两个Twitter帐户等等).您应该考虑这样做的应用含义. ..如果您有两个帐户,您可能不希望尝试将它们同步到同一个数据库表中.也许您需要指定一次只能激活一个,并在切换帐户时刷新表并重新同步.(通过查询存在的帐户的属性页).也许你为每个帐户创建一个不同的数据库,可能是不同的表,也许是每个表中的一个关键列.所有应用程序都具体而且值得一些思考. ContentResolver.setIsSyncable(Account account, String authority, int syncable)可能有兴趣在这里. setSyncAutomatically()控制是否选中或取消选中某个帐户/权限对,同时setIsSyncable()提供取消选中该行的方法并使其灰显,以便用户无法将其打开.您可以将一个帐户设置为Syncable,另一个帐户不可同步(dsabled).
7.注意ContentResolver.notifyChange()
一件棘手的事情.ContentResolver.notifyChange()是ContentProviders用于通知Android本地数据库已更改的函数.这有两个功能,首先,它会导致游标跟随内容uri更新,反过来重新查询和无效并重绘ListView等等......这非常神奇,数据库会ListView自动更新并且只是更新.真棒.此外,当数据库发生更改时,Android将为您请求同步,即使在正常计划之外也是如此,以便这些更改从设备中取出并尽快同步到服务器.也很棒.
但是有一个边缘的情况.如果你从服务器拉出来,并将更新推送到服务器,ContentProvider它会尽职尽责地调用notifyChange(),android会去,"哦,数据库更改,最好把它们放在服务器上!" (Doh!)编写良好的ContentProviders将有一些测试来查看更改是来自网络还是来自用户,syncToNetwork如果是这样,将设置布尔标志为false,以防止这种浪费的双重同步.如果您正在将数据输入a ContentProvider,那么您应该弄清楚如何使其工作 - 否则,当只需要一个时,您最终会执行两次同步.
8.感到高兴!
准备好所有这些xml元数据并启用同步后,Android将知道如何为您连接所有内容,并且同步应该开始工作.在这一点上,很多很好的东西只会点击到位,它会感觉像魔术一样.请享用!
| 归档时间: |
|
| 查看次数: |
44744 次 |
| 最近记录: |