Context.startForegroundService() 没有在计划的 AlarmClockInfo 上调用 Service.startForeground() 错误,而现有服务已经存在

问题描述 投票:0回答:1

TLDR:如果计划的alarmClockInfo(PendingIntent)打开一个服务实例,而应用程序位于前面,并且通过

context.bindService()
有一个活动服务实例... 并且警报不会触发通知... 出现
Context.startForegroundService() did not then call Service.startForeground()
错误。

详情:

我的目标是当应用程序位于前端时,通知以静默方式排队...这意味着当正在处理一个通知时(打开活动的操作),传入的预定警报会填充服务实例内的队列...并且不显示任何抬头通知。

我的问题是...与这里的大多数情况相反,我无法控制服务启动的方式,在本例中是通过 AlarmManager 调度。

@RequiresApi(api = Build.VERSION_CODES.O)
        public static PendingIntent foregroundServicePendingIntent(Context context, int reqCode, Supplier<Intent> intentSupplier) {
            assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
            return PendingIntent.getForegroundService(myService,
                    reqCode,
                    intentSupplier.get(),
                    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
            );
        }

意图是基本的东西......使用上下文+目标构造函数(

android.content.Intent#Intent(android.content.Context, java.lang.Class<?>)
),以及包含信息的包。以 MyService.class 作为目的地。

请注意,PednignIntent 正在安排一个从 MyService 到同一个 MyService 的预定警报。

(我已经看到了广播中介选项,但我还不明白如果广播者仍然被迫进入服务顺序事件循环,为什么需要这种间接)

日程安排如下:

assert isAtLeastOreo;
                    PendingIntent pendingIntent =
                            PendingIntent.getActivity( // This defines what will get shown when clicking in the clock icon on top of the android status bar.
                                    context,
                                    prefix_code + id,
                                    openAlarmsFragmentIntent,
                                    flag);
                    manager.setAlarmClock(
                            new AlarmManager.AlarmClockInfo(timeMillis, pendingIntent),
                               foregroundServicePendingIntent // variable created via foregroundServicePendingIntent(context, intent)
                    );

由于不再允许“VERSION O (26+)” Trampoline 事件,这意味着无论 Service 在解析 Trampoline Action 之前执行什么逻辑,现在都需要在创建/到达 Activity 目标后在目标中进行解析,因此,活动目标中的服务实例必须在

onCreate()
onNewIntent(Intent)
中解析 Intent 的捆绑包。

这可能是导致错误的原因...

当服务处理平视通知时...虽然应用程序尚未出现在前面,但什么也没有发生,一切都很好。 多个通知可以处理同一个 Service 实例并且不会出现错误......很好。

** 案例A:

如果我安排一个闹钟...不会出现错误:

当单个通知的

Action
打开“MainActivity”时...

根据通知的要求,此 Activity 必须实现 Intent 的捆绑解析,必须获取 Service 实例...

我有一个单例,当警报第一次调用服务时,它会被分配,当服务调用

onDestroy()
时,它会被清除。

一旦Activity打开,我就可以使用Service来执行更多的闹钟调度任务。搬迁、推迟...等等...

没有出现错误。

现在,如果第二个通知在事件发生后到达,则错误出现,无论此警报是在 Activity 被置于前面之后立即出现、5 秒还是 1 分钟后出现。

** 情况 B:

如果 MainActivity 首先实例化服务,也会发生这种情况...通过:

context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

在这种情况下,服务变得活跃...绑定了 MainActivity 生命周期,该服务还存储在一个被清除的单例中

onDestroy()

没有错误,当:

  1. 后台有 Activity 和 Service...

  2. 单个计划警报打开服务实例(MainActivity 中的同一实例),构建并显示通知。

  3. Notification Action 打开Activity实例触发

    onNewIntent(Intent)

  4. Activity 使用 Service 实例继续 Intent 操作+额外的东西...

...完成...没问题。

错误发生时间:

在步骤“3”之后,如果第二个警报响起

onStartCommand(Intent intent, int flags, int startId)
,则应用程序将在 5 秒后出现 ANR 错误。

我无法控制警报如何决定打开服务,因为这是在创建 AlarmClockInfo 时指定的,所以我不知道应该如何解决这个问题...

一个关键事实是...一旦选择了通知中的操作(打开活动),随后由计划的 PendingIntents 触发的每个

onStartCommand(Intent intent, int flags, int startId)
将不会构建并显示任何新的平视通知。

java android-intent notifications alarmmanager android-anr-dialog
1个回答
0
投票

当我让通知出现时,错误消失了。

这意味着...当服务通过由计划的 AlarmClockInfo 触发的 PendingIntent 打开时...甚至可能来自其他来源...

服务有义务让通知出现...

这很奇怪,因为它与服务根据文档应该服务的目的不一致,这不一定是显示通知,但它也可能用于执行其他后台任务......

另一个罪魁祸首可能是 AlarmScheduler 触发服务激活的方式,这表明它的唯一功能应该是显示通知。

总而言之,这似乎是一种安全对策……老实说,这对我来说似乎没问题。

© www.soinside.com 2019 - 2024. All rights reserved.