如何检测Android O的进程前景

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

在我们的应用程序上,通常在Application.OnCreate期间启动服务(直接调用context.startService),随后又通过AlarmManager启动(正在进行重构以将其某些工作迁移到JobScheduler)。

我们的应用程序还具有直接出于启动目的的BroadcastReceiver

鉴于Android Oreo(https://developer.android.com/about/versions/oreo/android-8.0-changes.html)的新限制,我们遇到了如下问题:

  • 应用程序/进程在后台/死机
  • BroadcastReceiver被操作系统解雇
  • Application.onCreate()在BroadcastReceiver之前执行
  • Application.onCreate()代码尝试运行服务

这会导致崩溃,并显示“ IllegalStateException:不允许启动服务意图”。

我知道CommonsWare在此处https://stackoverflow.com/a/44505719/906362回答的启动服务的新推荐方法,但是对于这种特定情况,我只是想拥有if(process in foreground) { startService }。我当前正在使用以下方法,它似乎可以工作:

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static boolean isProcessInForeground_V21(Context context) {
        ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
        List<ActivityManager.AppTask> tasks = am.getAppTasks();
        return tasks.size() > 0;
    }

但是我无法找到Android Oreo正在做的确切检查(我在https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/ContextImpl.java方法上到达了startServiceCommon的位置,但是从那里requireForeground标志似乎去了一些本机实现)

所以我的问题:

出于Android Oreo新限制的特定目的,如何在调用startService之前检查进程是否为前台?

android android-broadcastreceiver android-8.0-oreo
1个回答
0
投票

继续调查:(TL; DR:在底部的水平线之间看到]


免责声明,我对Android不太了解,我只喜欢挖掘源代码。注意:如果您跳到文件而不是类,也可以在Android Studio中导航代码:enter image description here或在项目和图书馆]中搜索文本。enter image description here


IActivityManager由AIDL定义,这就是为什么没有源的原因:https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/app/IActivityManager.aidl#145

基于how AIDL needs to be implemented,我发现ActivityManagerService extends IActivityManager.Stub(上帝保佑Google编制索引)。

注意,我也发现了这一点,如果您真的很感兴趣内部的工作原理,这可能是一个有趣的阅读。https://programmer.group/android-9.0-source-app-startup-process.html

[ActivityManagerService sources显示位于ActivityManagerService中的in Oreo startService is forwarded to ActiveServices

假设我们正在寻找这样的异常:

java.lang.IllegalStateException:不允许启动服务意图{...}:应用程序在后台uid UidRecord {af72e61 u0a229 CAC bg:+ 3m52s273ms空闲过程:1 seq(0,0,0)}] >>

我们必须继续沿着兔子洞前进:startService。允许的条件取决于ActiveServices返回的启动模式。

有4种启动模式:

APP_START_MODE_DISABLED

所以拒绝的原因只是针对O。我认为关于OS如何确定您的应用是前台还是后台的问题的最终答案是appServicesRestrictedInBackgroundLocked

appServicesRestrictedInBackgroundLocked

我的猜测是,缺少记录意味着它没有在运行,而https://stackoverflow.com/a/46445436/253468意味着它在后台。请注意,在我的异常消息中,APP_START_MODE_NORMAL表示它处于空闲状态,并且已后台运行3m52s。

我偷看了您的appRestrictedInBackgroundLocked,它基于most likely suspect,所以我想这很接近为您的应用列出 int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) { // Apps that target O+ are always subject to background check if (packageTargetSdk >= Build.VERSION_CODES.O) { return ActivityManager.APP_START_MODE_DELAYED_RIGID; }


不确定是否有帮助,但是我还是会张贴它,因此,如果有人想进行更多调查,他们会获得更多信息。

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