美文网首页
2023-03-01

2023-03-01

作者: 皓皓amous | 来源:发表于2023-02-28 17:25 被阅读0次

https://www.jianshu.com/p/8c83e06c0ef9

Handler和Message的使用之四
https://blog.csdn.net/jincf2011/article/details/6435156

<meta charset="utf-8">

从Android O(Android 8.0)开始,Android限制了隐式广播的接收(https://developer.android.com/about/versions/oreo/background
),在开发过程中遇到“Background execution not allowed: receiving”log输出,梳理具体情况如下

哪些情况受到影响?

1.隐式发送的广播 ,一般为AndroidManifest.xml中静态注册的Receiver
这种类型一般是隐式的,即发送方没有指明接收者
(注意但如果是上述静态注册的Receiver但发送者指明了接收者,这类广播还是能收到的)

哪些情况不受影响?

1.发送方:显式广播 ,即发送方发送广播的时候指明接收者
通过Intent setPackage或Intent setComponent
2.接收方:Receiver接收者动态注册的方式
通过registerReceiver的方式
3.发送方:发送广播的时候添加了FLAG_RECEIVER_INCLUDE_BACKGROUND的flag
4.接收方:发送的广播需要接收者有权限校验,并且这个权限是系统定义并且安全级别为仅签名 (signature)的
这个有点坑,查看google的提交记录,他们早期考虑是第三方也适用的,只要这个广播有权限校验便不受限制,后来
最后的版本添加了只有系统定义的权限才适用

   /**
     * Return true if all given permissions are signature-only perms.
     */
    final boolean isSignaturePerm(String[] perms) {
        if (perms == null) {
            return false;
        }
        IPackageManager pm = AppGlobals.getPackageManager();
        for (int i = perms.length-1; i >= 0; i--) {
            try {
                PermissionInfo pi = pm.getPermissionInfo(perms[i], "android", 0);
                if (pi == null) {
                    // a required permission that no package has actually
                    // defined cannot be signature-required.
                    return false;
                }
                if ((pi.protectionLevel & (PermissionInfo.PROTECTION_MASK_BASE
                        | PermissionInfo.PROTECTION_FLAG_PRIVILEGED))
                        != PermissionInfo.PROTECTION_SIGNATURE) {
                    // If this a signature permission and NOT allowed for privileged apps, it
                    // is okay...  otherwise, nope!
                    return false;
                }
            } catch (RemoteException e) {
                return false;
            }
        }
        return true;
    }

5.系统发送的部分广播 :系统白名单的广播不受影响
系统发送这些广播的时候带了 FLAG_RECEIVER_INCLUDE_BACKGROUND标志的广播:
https://developer.android.google.cn/guide/components/broadcast-exceptions
配置白名单:
源码目录/frameworks/base/data/etc/framework-sysconfig.xml

        if (action != null) {
            if (getBackgroundLaunchBroadcasts().contains(action)) {
                if (DEBUG_BACKGROUND_CHECK) {
                    Slog.i(TAG, "Broadcast action " + action + " forcing include-background");
                }
                intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            }

6.发送方:PendingIntent.getBroadcast
通过查看系统源码逻辑(安全方面考虑),这种方式是显式发送

    @UnsupportedAppUsage
    public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
            Intent intent, int flags, UserHandle userHandle) {
        String packageName = context.getPackageName();
        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
                context.getContentResolver()) : null;
        try {
            intent.prepareToLeaveProcess(context);
            IIntentSender target =
                ActivityManager.getService().getIntentSender(
                    ActivityManager.INTENT_SENDER_BROADCAST, packageName,
                    null, null, requestCode, new Intent[] { intent },
                    resolvedType != null ? new String[] { resolvedType } : null,
                    flags, null, userHandle.getIdentifier());
            return target != null ? new PendingIntent(target) : null;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
7.APP:APP升级了targetsdk>=26,但是跑在Android 0以下的机器,自然没有这个特性 

解决方法

1.接收方:动态注册
2.接收方:使用JobScheduler(网络状态等条件可替代部分广播功能,注意国内os对后台特性的修改)
2.发送方:发送广播时增加FLAG_RECEIVER_INCLUDE_BACKGROUND标志
3.接收方:添加权限校验(对第三方应用不适用)
4.常驻后台应用中转(对第三方应用不适用)

技术细节与原理

限制隐式广播的关键代码逻辑如下 (BroadcastQueue.java)

             } else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
                        || (r.intent.getComponent() == null
                            && r.intent.getPackage() == null
                            && ((r.intent.getFlags()
                                    & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
                            && !isSignaturePerm(r.requiredPermissions))) {
                    mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
                            component.getPackageName());
                    Slog.w(TAG, "Background execution not allowed: receiving "
                            + r.intent + " to "
                            + component.flattenToShortString());
                    skip = true;
                }
            }
        }

为什么动态注册的广播不受限制?
通过查看系统源码BroadcastQueue的逻辑得知

参考:
https://www.jianshu.com/p/c0458738d97d

作者:zcxohh
链接:https://www.jianshu.com/p/8c83e06c0ef9
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关文章

  • 公众号“有梦不觉人生苦”《令人头疼的弟弟》转载

    本文原创为马嘉,经公众号“有梦不觉人生苦” 发布(2023-03-01 13:01)。 这周有件令我...

  • 2023-03-01

    稻盛和夫说,一个女人成熟的标志就是人不作话,不多事,不拖与自己无关的事情,不问、不想、也不说。 愿你能做风雨里单手...

  • 2023-03-01

    今天我依然感到焦虑的情绪,但是我似乎又感到一丝欣慰。 中午和亚萍姐,以及新来的蔡一起去了面馆吃饭,很久没有去面馆吃...

  • 2023-03-01

    晚饭后啥也不想干,本来想找人聊聊天的。后来一想聊天最没意思了,聊来聊去啥都没有,最后一盘点,一场空。 ...

  • 2023-03-01

    3月1日 星期三 这个早上, 还没有到7:30, 我就在书桌前, 一边看着那些富有哲理的视频, 一边悠闲的享受老妈...

  • 2023-03-01

    2023.3.1今日体验:将来的事,变化莫测,生活中充满不确定性,人生不必为还没有发生的事情而感到焦虑。核心:担忧...

  • 2023-03-01

    外表看似光鲜的人,未必过得光鲜,外表看似寒酸的人,未必过得寒酸。但外表光鲜的人一定热爱生活,外表寒酸的人生活一定马...

  • 2023-03-01

    母亲和弟弟弟妹在家里住下,今天是表弟结婚的日子,掌柜和弟一早就跟着新郎去接亲了。小宝宝今天比昨晚感觉好多了,没有再...

  • 2023-03-01

    2023.3.1日精进 今日体验。常用配件香河备货价格好,要不着急发不来,着急的东西安排好不忙的时候想着哪个东西备货

  • 2023-03-01

    回想过去,每当自己能够真的做好一件事的时候,是因为自己“准备好了”。那种感觉就像是你为自己开辟了一个新的心理空间,...

网友评论

      本文标题:2023-03-01

      本文链接:https://www.haomeiwen.com/subject/qwqlldtx.html