首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android8.0的广播-熟悉的陌生人

Android8.0的广播-熟悉的陌生人

作者头像
PhoenixZheng
发布2018-08-23 14:40:32
6340
发布2018-08-23 14:40:32
举报

Android 8.0正式版上线到现在已经有一年了,很多厂商的2018年的机型上已经用上了这个系统。

8.0 的系统代号是 Orea,对..奥利奥, 新系统有很多行为上的变更,今天说一下比较有意思的广播行为上的新政策。

8.0前的广播

做Android的都知道广播是四大组件之一, 它有两种注册方式,

  • AndroidManifest注册的静态广播
  • registerReceiver注册的动态广播

在8.0以前这了两种方式注册的广播都是有效的,除了接收时机的差异之外,没有什么限制。

做过项目的同学应该对 ACTION_BOOT_COMPLETED 这个系统广播很熟悉, 很多时候我们会用这个广播在系统启动后用来拉起自己的应用, 在几年前的是这个保活手段还算有用, 但是在后来各大厂商的系统管理机制完善起来后也就渐渐失效了。

笔者曾经闲的无聊去分析了在手机上监听这个广播的app, 发现竟然有70+个进程在监听它。。 这种现象会导致在系统启动后变的很慢很卡,毕竟要开70+个进程,RAM也受不了, 所以几年前的Android机的慢和卡的通病..大部分原因是流氓软件导致的..

Google认识到这个问题后慢慢的在系统机制上进行迭代,下面是一段来自Google FW团队Dianne Hackborn的原文,

To help understand what is going on, I need to clarify that the purpose of this change is not directly related to battery use, but rather to address long-standing issues we have had in the platform where devices that are under memory pressure can get in to bad thrashing states. Very often these states are due to broadcasts: some broadcast or broadcasts are being sent relatively frequently, which a lot of applications are listening to through their manifest (so need to be launched to receive it), but there is not enough RAM to keep all of those app proceses in cache, so the system ends up continually thrashing through processes each time the broadcast is sent.

翻译过来的意思是说,8.0对广播机制的修改对电池的优化是次要的, 主要的原因是来自内存的压力,因为太多静态注册的广播了,系统不得不开很多进程来维护这些广播,导致消耗了大量的内存。 所以解决方案是什么呢, 不再使用隐式静态广播

8.0之后的广播

如果你在8.0+开发中遇到这样的问题

04-11 14:12:36.340 753-763/? W/BroadcastQueue: Background execution not allowed: receiving Intent

那么八成是发了个隐式静态广播的原因了。 要导致这个问题只需要两个条件,

  • 在manifest中静态注册了广播
  • 发送广播时没有指定包名

当然这里有个前提条件是 targetSdk > 25,低版本的app即使在8.0系统上也不会受到这个政策的影响。 就算发的隐式广播是在自己的app里的AnroidManifest上注册的,在8.0上也照样收不到。

解决办法目前有三种,

  • 修改 targetSdk < 26
  • 动态注册广播,用 registerReceiver注册的不受影响
  • 发广播的时候指定包名

对于第三个方法,如果要发广播给其他进程怎么办呢,这里给一段简单代码, 思路就是获取注册了这个广播action的接收器,然后拿他们的包名,构造一个显示广播再发出去,

private static void sendImplicitBroadcast(Context ctxt, Intent i) {
  PackageManager pm=ctxt.getPackageManager();
  List<ResolveInfo> matches=pm.queryBroadcastReceivers(i, 0);

  for (ResolveInfo resolveInfo : matches) {
    Intent explicit=new Intent(i);
    ComponentName cn=
      new ComponentName(resolveInfo.activityInfo.applicationInfo.packageName,
        resolveInfo.activityInfo.name);

    explicit.setComponent(cn);
    ctxt.sendBroadcast(explicit);
  }
}

==== 今日沙雕 ====

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android每日一讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 8.0前的广播
  • 8.0之后的广播
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档