我正在使用SyncAdapter
和GCM通知我的应用程序后端服务器上的不同类型的更改。例如,如果服务器上发生了更改A,我会使用名为change_a的字段执行推送通知,然后通过SyncAdapter
传递给ContentResolver.requestSync()
。这样,SyncAdapter
知道从服务器同步的内容。同样,对于更改B,我发送一个名为change_b的字段。
除了一个用例外,这个功能完美无缺。我发送了change_a通知,它会调用ContentResolver.requestSync()
,但由于没有网络可用性,因此尚未调用SyncAdapter
。如果之后,我发送change_b通知,再次使用新字段调用ContentResolver.requestSync()
。然后,当网络启动时,SyncAdapter
被调用但仅使用最新的字段change_b,因此,它不会同步更改A.
因此,基本上,ContentResolver.requestSync()
会覆盖尚未触发SyncAdapter的所有先前requestSync()
次调用。 SyncAdapter使用发送的最新附件运行。
对此的一个解决方案是不区分变更A和变更B并让SyncAdapter
同步所有内容。但这对带宽来说代价很高。我想控制什么以及何时同步。有什么我可以做的来解决这个问题(也许是一个syncadapter标志)?
答案 0 :(得分:3)
我似乎得出了错误的结论。实际上,经过一些进一步的测试,如果requestSync()
被调用了不同的额外内容,则为每个不同的Bundle调用SyncAdapter
几次。
我的问题出在其他地方。当我收到推送通知时,我会安排一个警报来触发同步请求,我会使用带有PendingIntent
标志的PendingIntent.FLAG_CANCEL_CURRENT
,这意味着如果在警报响起之前发出另一个推送通知,警报将被新数据覆盖。因此,如果设备处于脱机状态,当它处于联机状态时,它会收到所有待处理的推送通知,并且只有一个警报设置包含来自最近推送通知的数据。
我解决此问题的方法是在每个PendingIntent上设置不同的操作,以便设置相同类型的新警报不会覆盖其他类型的警报。
对此的改进是为每种类型的同步添加一个collapse_key,以便每种推送通知中只有一种传递给设备。
答案 1 :(得分:1)
我似乎得出了错误的结论。实际上,经过一些进一步的测试,如果使用不同的附加功能调用requestSync(),则会为每个不同的Bundle多次调用SyncAdapter。
如果您在对requestSync()
的多次调用中使用不同的额外内容,则会为每个performSync()
调用requestSync()
。我想添加证明:SyncOperation.java内的toKey()
调用包含了附加内容Bundle中的值。这可以防止SyncManager
重复这些SyncOperations
。