【问题标题】:ListenableWorker does not remove notification iconListenableWorker 不移除通知图标
【发布时间】:2020-03-05 08:45:55
【问题描述】:

我正在使用 ListenableWorker 来执行后台任务。 另外我希望操作系统知道我的服务重要性,所以我打电话给

 setForegroundAsync(new ForegroundInfo(WorkerConstants.NOTIFICATION_FOREGROUND_ID,
 builder.build()));

按照谷歌文档中的建议。

但是当我的服务停止或取消时,我仍然可以看到前台服务通知,我无法删除它。

此外,我在此通知中添加了取消按钮,但它什么也没做,我无法关闭它:

PendingIntent intent = WorkManager.getInstance(getApplicationContext())
                            .createCancelPendingIntent(getId());
                    builder.addAction(R.drawable.ic_redesign_exit,"Stop",intent);

有什么建议吗?

【问题讨论】:

  • 你解决过这个问题吗?我遇到了这个问题,我似乎没有解决它..
  • 是的。请参阅下面的答案

标签: android android-notifications android-workmanager


【解决方案1】:

我向谷歌跟踪器提交了一个问题。并发现它完全磨损了。

官方回应如下:

查看您的示例应用程序,您正在引入一场比赛 完成您的 ListenableFuture 返回的 CallbackToFutureAdaptor 和主循环器。

即使不使用 REPLACE,您的通知更新之一也是 在您的 Worker 标记为成功后发布。

但是,您实际上可以通过等待 调用 setForegroundAsync() 来完成(因为这也是 返回一个 ListenableFuture)。一旦你这样做了——你永远不会有 在您的 Worker 完成后显示的通知。

我也会继续提出改进意见 即使开发人员弄错了,也会自动执行此操作。

try {
    // This ensures that you waiting for the Notification update to be done.
    setForegroundAsync(createForegroundInfo(0)).get();
} catch (Throwable throwable) {
    // Handle this exception gracefully
    Log.e("FgLW", "Something bad happened", throwable);
}

【讨论】:

  • 这对我不起作用。无论我做什么,返回结果后它仍然会尝试完成。
【解决方案2】:

如果您有一些可以立即结束工作人员的分支 - 添加 1 秒延迟以使通知传播。 setForeground 声称是同步的,但显然不是——总是需要显示时间通知。并且在未显示的通知上调用取消没有任何作用。这显然是一种竞争条件,不是由谷歌处理的(我什至不确定这是否可以由应用程序处理)。

扩展解释:

我有在单一场景中可以立即返回的代码。 Worker 长这样:

setForeground(getForegroundInfo())
loggingRepository.uploadLogs()

就是这样,再简单不过了。但是,日志存储库在开始时进行此检查:

if (!userIdentity.isLoggedIn) return

所以如果用户没有登录 - 什么也不做。如果发生这种情况 - 通知就会继续存在。我唯一要做的就是添加这样的延迟(它是一个 CoroutineWorker)

setForeground(getForegroundInfo())
loggingRepository.uploadLogs()
delay(1000)

【讨论】:

    【解决方案3】:

    如果您使用协程,最新版本的工作管理器库中有一个名为 setForeground() 的 ktx 挂起函数,它在侦听器上执行 .await() 并将其变为同步。

    【讨论】:

    • 它实际上不起作用。我正在这样做,但仍然出现错误。
    【解决方案4】:

    最好忘记setForegroundAsync 并按照此处所述采用传统方式: https://developer.android.com/training/notify-user/build-notification

    这是我使用的:

        Context context = getApplicationContext();
        String title = context.getString(R.string.str_synchronisation);
        String cancel = context.getString(R.string.str_cancel_synchronisation);
        // This PendingIntent can be used to cancel the worker
        PendingIntent intent = WorkManager.getInstance(context)
                .createCancelPendingIntent(getId());
        //notificationManager.cancel(notification_ID);
    
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, notif_ch_id)
                .setSmallIcon(R.drawable.ic_sync_black_24dp)
                .setContentTitle(title)
                .setContentText("Use this Content")
                .setOngoing(true)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
    //                // Add the cancel action to the notification which can
    //                // be used to cancel the worker
                .addAction(android.R.drawable.ic_delete, cancel, intent);
        notificationManager.notify(notification_ID, builder.build());
    

    不要忘记保留通知管理器的实例:

    notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
    

    更新您的通知:

    builder.setContentText(context.getString(R.string.str_veuiller_patienter)
                    + ", fichier " + String.valueOf(i + 1) + totalfiles);
    notificationManager.notify(notification_ID, builder.build());
    

    通过以下方式取消您的通知:

    notificationManager.cancel(notification_ID);
    

    【讨论】:

    • 虽然在某些情况下很有用,但这个答案并不能解决原来的问题。当让 WorkManager 工作人员为长时间运行的任务启动前台服务时,必须使用 setForegroundAsync。管理自己的通知可以摆脱通知,但您仍然无法正确使用前台服务功能。这似乎是 WorkManager 库中的一个错误......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-25
    • 2011-02-19
    • 2014-10-07
    相关资源
    最近更新 更多