【问题标题】:SyncAdapter process killed when app process is terminated应用程序进程终止时,SyncAdapter 进程被终止
【发布时间】:2016-01-27 16:05:41
【问题描述】:

为什么从应用切换器列表中滑动应用时 SyncAdapter 进程 (:sync) 会被终止?我认为这里的全部目的是让它们解耦。

编辑:

以下是使用的代码。 mUploadTask 是一个 AsyncTask 即时执行,它从 sqlite 表中读取信息(使用 getContext().getContentResolver())并将相关数据上传到后端(使用 HttpPost)。非常直接。

另外,我只实现了一个onSyncCanceled(),因为我的SyncAdapter 不支持并行同步多个帐户。

public class SyncAdapter extends AbstractThreadedSyncAdapter implements UploadTaskListener {

private static final String TAG = SyncAdapter.class.getSimpleName();

private static volatile UploadTask mUploadTask;

/**
 * Set up the sync adapter
 */
public SyncAdapter(Context context, boolean autoInitialize) {
    super(context, autoInitialize);
}

/**
 * Set up the sync adapter. This form of the
 * constructor maintains compatibility with Android 3.0
 * and later platform versions
 */
public SyncAdapter(
        Context context,
        boolean autoInitialize,
        boolean allowParallelSyncs) {
    super(context, autoInitialize, allowParallelSyncs);
}

@Override
public void onPerformSync(Account account, Bundle extras, String authority,
        ContentProviderClient provider, SyncResult syncResult) {

    MHLog.logI(TAG, "onPerformSync");

    ContentResolver.setSyncAutomatically(account, authority, true);

    if (mUploadTask == null) {
        synchronized (SyncAdapter.class) {
            if (mUploadTask == null) {
                mUploadTask = new UploadTask(getContext(), this).executeOnSettingsExecutor();
                MHLog.logI(TAG, "onPerformSync - running");
            }
        }
    }
}

@Override
public void onSyncCanceled() {
    MHLog.logI(TAG, "onSyncCanceled");
    if(mUploadTask != null){
        mUploadTask.cancel(true);
        mUploadTask = null;
    }
}

【问题讨论】:

  • 你的 UploadTask 是什么,这只是一个 AsyncTask 吗?
  • @AsafK 首先在哪里创建帐户等?查看文档示例。其次,如果onPerformSync本身运行在worker线程中,为什么还需要异步任务?

标签: android android-syncadapter


【解决方案1】:

来自文档:

框架可以随时取消同步。例如,非用户启动且持续时间超过 30 分钟的同步将被视为超时并取消。类似地,该框架将尝试通过在一分钟内监视其网络活动来确定适配器是否正在取得进展。如果此窗口上的网络流量足够接近为零,则同步将被取消。您也可以通过cancelSync(Account, String)cancelSync(SyncRequest) 请求取消同步。

通过在同步线程上发出interrupt() 来取消同步。您在onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult) 中的代码必须检查interrupted(),或者您必须覆盖onSyncCanceled(Thread)/onSyncCanceled() 之一(取决于您的适配器是否支持并行同步多个帐户)。如果您的适配器不遵守框架发出的取消操作,您将面临应用整个进程被终止的风险。

您是否确保遵守 SyncAdapter 框架的规则?

此外,很高兴看到您的一些代码以深入了解框架取消您的同步的原因...

【讨论】:

  • 查看我更新的问题。如您所见,我确实遵守规则。此外,SyncAdapter 完成的工作不到 30 分钟,基本上包括通过网络上传数据。不知道我在这里做错了什么。
  • 什么是“[...] 非用户启动且持续时间超过 30 分钟的同步 [...]”?是否存在确定用户何时启动此过程的方法?在我们的例子中,发起此操作的用户是...如何通知 Android?我们的流程是内部的,我们不使用互联网连接,只使用电话地址簿同步联系人。有时,如果进程超过 30 或 45 分钟,Android 框架会终止该进程。很少,但它会发生,即使延迟 60 分钟也能让我们顺利完成...
【解决方案2】:

onPerformSync() 在单独的线程上工作。因此,您不需要创建任何执行器变量来实现后台工作。

我遇到了同样的问题 - 我的适配器一直在 onPerformSync() 方法中使用执行器,它执行操作(现在 - 多了一个线程)。 这是一个原因 - 如果系统在其线程中的 onPerformSync() 方法中看不到任何作业(因为您已经创建了在另一个线程中执行操作的执行程序) - onSyncCanceled( ) 方法将被调用 - 这只是时间问题。

短时间的操作会完成,但长时间(10分钟)会被onSyncCanceled()终止。

您可以在适配器中覆盖 onSyncCanceled() - 但您应该了解真正的问题并避免它。

这是项目示例https://github.com/Udinic/SyncAdapter。在onPerformSync()方法中做client-server的实现,没有问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 2011-01-21
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多