[技術博客]升級 API 面臨的問題

升級 API 面臨的問題

咱們使用的上一屆的版本中,使用的底層的 安卓的 API 是 Android7.0 。在這一版本中,咱們將 API進行了升級,爲了更好的兼容新功能。(發送通知),咱們在升級 API中遇到的主要問題就是,在 Android7.0 到 Android8.0 這兩個版本之間的時候,安卓會禁用隱式的靜態廣播,至於什麼是安卓的廣播與廣播的機制,咱們推薦這篇博客,傳送門html

廣播主要用於 Android 中的不一樣進程之間的通訊。通常執行的操做主要是 喚醒,或者發送通知,啓動等等。java

廣播的主要工做流程是android

1.廣播接收者BroadcastReceiver經過Binder機制向AMS(Activity Manager Service)進行註冊;api

2.廣播發送者經過binder機制向AMS發送廣播;app

3.AMS查找符合相應條件(IntentFilter/Permission等)的BroadcastReceiver,將廣播發送到BroadcastReceiver(通常狀況下是Activity)相應的消息循環隊列中;ui

4.消息循環執行拿到此廣播,回調BroadcastReceiver中的onReceive()方法。code

Android8.0 對廣播的限制

安卓系統不斷地升級的過程當中,對廣播機制作了不少的改變,這是由於廣播的機制對資源的佔用與消耗。所以在 Android 不斷地升級的過程當中對這個廣播機制作出了更多的限制。component

不一樣Android API版本中廣播機制相關API重要變遷htm

1).Android5.0/API level 21開始粘滯廣播和有序粘滯廣播過時,之後再也不建議使用;blog

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;
相關文章
相關標籤/搜索