Background execution not allowed,廣播無法接收原因及解決方法

    出現此報錯的原因是Android O中對隱式廣播做了限制,這種限制主要是把廣播用於進程間通信時,廣播Receiver無法接收到廣播,如果發生了此現象,可以通過shell下 logcat -s BroadcastQueue 可以看到是否報出了這樣的警告。

11-01 13:58:45.617 2432 2549 W BroadcastQueue: Background execution not allowed: receiving Intent:***

應對方案

    一、這裏的AndroidO並不是運行的Android版本,而是在AndroidManifest文件中定義的targetSdkVersion的值,因此我們第一種方法也是最穩定的方法即把項目文件中的targetSdkVersion設置爲25及以下的版本號,重新編譯即可,如果用的AndroidStudio,還要修改module/build.gradle中的該項配置。
在這裏插入圖片描述
    二、如果項目依賴Android O,無法修改編譯版本的話,可以把靜態廣播修改爲動態廣播,因爲此項限制的原因即是系統與後臺應用自啓之間的戰爭,動態廣播在申請某項權限時會經過用戶同意,因此是系統允許的,修改爲動態廣播後即可正常接收。
    三、如果不是接收系統廣播,只是兩個應用間進行通信的話,可以在發送時爲intent指定包名,這樣接受者靜態註冊也是可以接收到廣播的。

Intent mIntent = new Intent(Broadcast_Action);
mIntent.setPackage(Package_Name);
sendBroadcast(mIntent);

    四、如果項目必須以一對多的方式發送廣播,並且接收者無法動態註冊的話,那麼可以給Intent增加一個FLAG_RECEIVER_INCLUDE_BACKGROUND的Flag,不過這個標誌位在源碼中被hide掉了。
在這裏插入圖片描述
但我們可以直接用他的屬性值,這樣也是有效的。

intent.addFlags(0x01000000);

具體原因可以看下BroadcastQueue的源碼:

                    } 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;
                    }

    之所以打印了Background execution not allowed的log,是滿足了這個if的4個條件:

1、r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0
2、r.intent.getComponent() == null
3、r.intent.getPackage() == null
4、(r.intent.getFlags() & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0 && !isSignaturePerm(r.requiredPermissions)

    首先,我們不會指定Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND,因此條件1肯定爲false,而Component和Package如果沒有設置的話這裏條件2,3就爲true了,所以關鍵就是看條件4是否滿足了,只要在Intent中包含了FLAG_RECEIVER_INCLUDE_BACKGROUND標誌位,條件4就肯定爲false了,這個if的條件就不滿足了,後續邏輯也就正常執行。
    但是,這畢竟是谷歌hide的方式,項目緊急可以使用,但也相當於埋下一個坑,如果後需源碼發生變化,項目進行更新的話,很可能踩到這個坑上,因此使用還需謹慎。
    以上各種方法希望能幫助到各位~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章