Android O 广播限制

作者: 最忆是深秋 | 来源:发表于2018-07-29 23:19 被阅读478次

    背景

    • 最近编写代码,在使用广播的时候遇到了些问题,发现有的广播按原来的使用方式,竟然不灵了...主要是关于一些静态广播的注册问题。以前写APP总是会在AndroidManifest中静态监听很多系统广播,希望能尽量延长APP的存活时间,提升自启能力,当然这只是其中的一种方法。很多APP都是这么干的。所以Google加强了对这块的优化,防止应用频繁拉起,降低功耗。

    如何确定一个action是否不支持静态注册?

    • 静态注册系统广播时,在检查代码没有问题的情况下,基本上都可以确定是系统禁止了。而不同的Android大版本对这些action的禁止策略又是不相同的。像 ConnectivityManager.CONNECTIVITY_ACTION 就是从Android N开始才不支持静态注册的,当然还有其他的。那么如何确定一个action 是否不支持静态注册了呢?
      我大概整理的一些:
      ConnectivityManager.CONNECTIVITY_ACTION Android 7.0 (API level 24)及以上开始,必须要动态注册
      应用无法发送或接收ACTION_NEW_PICTUREACTION_NEW_VIDEO 此项优化会影响所有应用,而不仅仅是面向 Android 7.0 的应用。
      frameworks\base\core\java\android\content\Intent.java里注释的几个 明确不允许 静态注册的广播
        /**
         * You <em>cannot</em> receive this through components declared in
         * manifests, only by explicitly registering for it with
         * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
         * Context.registerReceiver()}.
         */
        public static final String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
        public static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
        public static final String ACTION_TIME_TICK = "android.intent.action.TIME_TICK";
        public static final String ACTION_CONFIGURATION_CHANGED = "android.intent.action.CONFIGURATION_CHANGED";
        public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";
    

    其他的 Action 不确定的可以在源码下查找发送该 Action 对应广播的地方,看 Intent 有没有带上Intent.FLAG_RECEIVER_REGISTERED_ONLY这个flag,也就是声明了这个 Action 只允许动态注册的 receiver 接收。

        /**
         * If set, when sending a broadcast only registered receivers will be
         * called -- no BroadcastReceiver components will be launched.
         */
        public static final int FLAG_RECEIVER_REGISTERED_ONLY = 0x40000000;
    

    Android O(8.0)上对隐式广播的限制

    • 在Android O上,从应用A向应用B发送广播,以前都是这么写的:
        Intent intent = new Intent();
        intent.setAction("com.broadcast.test.action");
        sendBroadcast(intent);
    

    而B中只需要注册一个 监听了 "com.broadcast.test.action"的广播即可,无论静态注册还是动态注册。
    而在Android O的机器上,这样操作B无论如何都是收不到消息的。
    07-27 15:58:57.653: W/BroadcastQueue(4268): Background execution not allowed: receiving Intent { act=com.broadcast.test.action flg=0x4000010 (has extras) } to com.broadcast.test.demo/.MyReceiver
    当然这也同时取决于 B 应用的 targetVersion , 经过试验,只有当 B 的 targetVersion 是 26 (Android 8.0)时才会有问题。所以这种情况是出现在 targetVersion 在26及以上的APP 运行在 Android 8.0及以上版本的机器上时,在接收隐式intent时会出现问题

    • 怎么办呢?
    1. 接收方APP targetVersion改成低于 26 的,就直接没有这个问题了
    2. 系统需要明确知道你到底是想发送给谁?用以下几种方式都可以,我都实操过
    Intent intent = new Intent();
    方法1:
    intent.setAction("com.broadcast.test.action");
    intent.setPackage("com.broadcast.test.demo");
    方法2:
    intent.setClassName("com.broadcast.test.demo", "com.broadcast.test.demo.MyReceiver");
    方法3:
    intent.setComponent(new ComponentName("com.broadcast.test.demo", "com.broadcast.test.demo.MyReceiver"));
    getApplicationContext().sendBroadcast(intent);
    ,

    相关文章

      网友评论

        本文标题:Android O 广播限制

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