如何仅针对 Internet 连接安排同步
How to schedule synchronization for Internet connectivity only
我正在使用 Sync Adapter 为我的应用执行同步。它已设置自动同步:
// Inform the system that this account supports sync
ContentResolver.setIsSyncable(account, AuthenticatorService.AUTHORITY, 1);
// Inform the system that this account is eligible for auto sync when the network is up
ContentResolver.setSyncAutomatically(account, AuthenticatorService.AUTHORITY, true);
如果我请求同步:
Bundle b = new Bundle();
// Disable sync backoff and ignore sync preferences. In other words...perform sync NOW!
b.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
b.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
ContentResolver.requestSync(AuthenticatorService.GetAccount(), AuthenticatorService.AUTHORITY, b);
它运行良好——一旦网络启动,就会调用 SyncAdapter.onPerformSync()。但是,存在一个问题:如果网络正常但未连接到 Internet(例如没有网络共享的热点),仍然会调用 onPerformSync()。
当然,由于无法连接到服务器,因此同步代码失败。更糟糕的是,系统认为一切正常,并且 不会再进行任何同步调用,除非我的数据发生变化 。
我的问题是:我能否将同步标记为不成功以便系统稍后尝试(例如在另一个 CONNECTED 事件或几秒钟后)或更好地告诉系统仅在以下情况下执行同步是否存在真正的互联网连接?
我可以监控网络状态并自己进行连接检查,但这会违背同步适配器的全部目的,不是吗?我能想到的唯一解决方法是安排定期同步(使用 ContentResolver.addPeriodicSync()),当我的同步代码成功时,将其关闭。但我对此也不是很满意(耗尽电池)。
编辑: 至于我问题的第一部分,this answer 正是我要找的。它部分解决了我的问题,但是如果有连续数量的 "non-working" 连接,当设备与真实连接相关联时,同步需要几十分钟(因为指数退避算法)。
感谢 csenga 的建议,我找到了一个解决方案:使用 GcmNetworkManager 来安排同步。它看起来有点愚蠢,因为我必须声明 另一个 服务只是为了调用 ContentResolver.requestSync() 如果出现问题我必须重新安排我的任务而不是设置 SyncResult.stat 标志(我在这里实际上是在复制 Sync Adapter 的工作)但仍然比处理我自己的 NETWORK_STATE_CHANGED_ACTION 接收器要好。
我正在使用 Sync Adapter 为我的应用执行同步。它已设置自动同步:
// Inform the system that this account supports sync
ContentResolver.setIsSyncable(account, AuthenticatorService.AUTHORITY, 1);
// Inform the system that this account is eligible for auto sync when the network is up
ContentResolver.setSyncAutomatically(account, AuthenticatorService.AUTHORITY, true);
如果我请求同步:
Bundle b = new Bundle();
// Disable sync backoff and ignore sync preferences. In other words...perform sync NOW!
b.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
b.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
ContentResolver.requestSync(AuthenticatorService.GetAccount(), AuthenticatorService.AUTHORITY, b);
它运行良好——一旦网络启动,就会调用 SyncAdapter.onPerformSync()。但是,存在一个问题:如果网络正常但未连接到 Internet(例如没有网络共享的热点),仍然会调用 onPerformSync()。
当然,由于无法连接到服务器,因此同步代码失败。更糟糕的是,系统认为一切正常,并且 不会再进行任何同步调用,除非我的数据发生变化 。
我的问题是:我能否将同步标记为不成功以便系统稍后尝试(例如在另一个 CONNECTED 事件或几秒钟后)或更好地告诉系统仅在以下情况下执行同步是否存在真正的互联网连接?
我可以监控网络状态并自己进行连接检查,但这会违背同步适配器的全部目的,不是吗?我能想到的唯一解决方法是安排定期同步(使用 ContentResolver.addPeriodicSync()),当我的同步代码成功时,将其关闭。但我对此也不是很满意(耗尽电池)。
编辑: 至于我问题的第一部分,this answer 正是我要找的。它部分解决了我的问题,但是如果有连续数量的 "non-working" 连接,当设备与真实连接相关联时,同步需要几十分钟(因为指数退避算法)。
感谢 csenga 的建议,我找到了一个解决方案:使用 GcmNetworkManager 来安排同步。它看起来有点愚蠢,因为我必须声明 另一个 服务只是为了调用 ContentResolver.requestSync() 如果出现问题我必须重新安排我的任务而不是设置 SyncResult.stat 标志(我在这里实际上是在复制 Sync Adapter 的工作)但仍然比处理我自己的 NETWORK_STATE_CHANGED_ACTION 接收器要好。