zoukankan      html  css  js  c++  java
  • [技术博客]升级 API 面临的问题

    升级 API 面临的问题

    我们使用的上一届的版本中,使用的底层的 安卓的 API 是 Android7.0 。在这一版本中,我们将 API进行了升级,为了更好的兼容新功能。(发送通知),我们在升级 API中遇到的主要问题就是,在 Android7.0 到 Android8.0 这两个版本之间的时候,安卓会禁用隐式的静态广播,至于什么是安卓的广播与广播的机制,我们推荐这篇博客,传送门

    广播主要用于 Android 中的不同进程之间的通信。一般执行的操作主要是 唤醒,或者发送通知,启动等等。

    广播的主要工作流程是

    1.广播接收者BroadcastReceiver通过Binder机制向AMS(Activity Manager Service)进行注册;

    2.广播发送者通过binder机制向AMS发送广播;

    3.AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(一般情况下是Activity)相应的消息循环队列中;

    4.消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。

    Android8.0 对广播的限制

    安卓系统不断地升级的过程中,对广播机制做了很多的改变,这是因为广播的机制对资源的占用与消耗。因此在 Android 不断地升级的过程中对这个广播机制做出了更多的限制。

    不同Android API版本中广播机制相关API重要变迁

    1).Android5.0/API level 21开始粘滞广播和有序粘滞广播过期,以后不再建议使用;

    2).”静态注册的广播接收器即使app已经退出,主要有相应的广播发出,依然可以接收到,但此种描述自Android 3.1开始有可能不再成立“

    Android 3.1开始系统在Intent与广播相关的flag增加了参数,分别是FLAG_INCLUDE_STOPPED_PACKAGES和FLAG_EXCLUDE_STOPPED_PACKAGES。

    FLAG_INCLUDE_STOPPED_PACKAGES:包含已经停止的包(停止:即包所在的进程已经退出)

    FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已经停止的包

    而在安卓的官方文档中可以看到 Android8.0 对广播机制做出的更加严格限制:

    Android8.0上突破隐式广播的限制

    1. 面对这一问题常用的解决方法有下面几种:
    2. 能动态注册,就不静态注册
    3. 如果一定要静态注册, 发送的时候指定包名,即发送显式广播
    4. 如果要接收系统广播,而对应的广播在Android8.0中无法被接收,那么只能暂时把App的 targetSdkVersion 改为25或以下,但这招已经不顶用了,工信部要求 targetSDK 必须26以上

    但是有时候,我们还是想使用静态广播来发送提醒或者是在 APP 关闭的情况下接收广播。

    突破隐式限制的方法就是发送广播的时候携带intent.addFlags(0x01000000);

    我们看一下 Android8.0 的开源代码,在1278行有一个 skip = true;

    1267						} else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
    1268                            || (r.intent.getComponent() == null
    1269                                && r.intent.getPackage() == null
    1270                                && ((r.intent.getFlags()
    1271                                        & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
    1272                                && !isSignaturePerm(r.requiredPermissions))) {
    1273                        mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
    1274                                component.getPackageName());
    1275                        Slog.w(TAG, "Background execution not allowed: receiving "
    1276                                + r.intent + " to "
    1277                                + component.flattenToShortString());
    1278                        skip = true;
    1279                    }
    

    我们想要进去的话,就不带 FLAG_RECEIVER_INCLUDE_BACKGROUND 标志位就可以了,于是我们设置

    public static final int FLAG_RECEIVER_INCLUDE_BACKGROUND = 0x01000000;
    
  • 相关阅读:
    题解——草莓(树上切割)
    题解——碰杯
    SCOI2019凉凉记
    题解rotinv
    矩阵快速幂
    质数及线性筛
    题解[ZJOI2007]矩阵游戏
    【实验舱国庆营模拟】Day3 A.code
    【实验舱国庆营模拟】Day2 A.divide
    【纪中集训2019.08.25】【JZOJ6371】树
  • 原文地址:https://www.cnblogs.com/PureMan6/p/10983741.html
Copyright © 2011-2022 走看看