BroadcastReceiver

概念:Android四大組件之一,沒有可視化界面,用于不同組件和多線程之間的通信。

目錄

  • 靜態(tài)注冊和動態(tài)注冊的區(qū)別
  • Android 8.0靜態(tài)廣播失效解決辦法
  • 有序廣播
  1. 靜態(tài)注冊和動態(tài)注冊的區(qū)別
  • 靜態(tài)注冊:在AndroidManifest.xml 中,通過標簽來聲明
  <receiver android:name="com.yirong.library.NetStateReceiver">
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
    </intent-filter>
  </receiver>

優(yōu)點:不受其他組件生命周期影響,即使應用程序被關(guān)閉,也能接收廣播。
缺點:耗電,占內(nèi)存。
適用場景:需要時刻監(jiān)聽的廣播
事實上在,google因為電池優(yōu)化的原因從7.0開始已經(jīng)對靜態(tài)注冊做出了一些限制(權(quán)限),并在8.0使大部分靜態(tài)注冊失效了,極少數(shù)例如ACTION_BOOT_COMPLETED, ACTION_HEADSET_PLUG, ACTION_CONNECTION_STATE_CHANGED 等廣播依舊有效。可以說,未來使用動態(tài)注冊已經(jīng)是一種趨勢,不過在兼容低版本時,靜態(tài)注冊依舊好用。

  • 動態(tài)注冊:在代碼中注冊
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        receiver = new NetStateReceiver();
        registerReceiver(receiver, intentFilter);
        unregisterReceiver(receiver);

優(yōu)點:靈活,不耗電,易控,省內(nèi)存
缺點:需要手動注銷
適用場景:需要特定時候監(jiān)聽的廣播

  1. Android 8.0靜態(tài)廣播失效解決辦法
    Intent intent = new Intent("com.yirong.library.receiver");
    intent.putExtra("receive","helloworld!");
    intent.setPackage(getPackageName());
    //intent.setComponent(...)
    sendBroadcast(intent);
  • 看源碼,使用@hide API
   if (!skip) {
            final int allowed = mService.getAppStartModeLocked(
                    info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
                    info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false, false);
            if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                // We won't allow this receiver to be launched if the app has been
                // completely disabled from launches, or it was not explicitly sent
                // to it and the app is in a state that should not receive it
                // (depending on how getAppStartModeLocked has determined that).
                if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
                    Slog.w(TAG, "Background execution disabled: receiving "
                            + r.intent + " to "
                            + component.flattenToShortString());
                    skip = true;
                } 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;
                }
            }
        }

攜帶 FLAG_RECEIVER_INCLUDE_BACKGROUND 這個標志位的intent,可以調(diào)用靜態(tài)廣播。
發(fā)送廣播的時候攜帶intent.addFlags(0x01000000); 即能讓廣播突破隱式廣播限制。
解決方法:https://blog.csdn.net/jingwen3699/article/details/83107017

  1. 有序廣播

一般廣播都是所有接收者同時執(zhí)行的,有序廣播有所不同。
他根據(jù)廣播的優(yōu)先級,按順序執(zhí)行。只有當優(yōu)先級高的廣播接收者onReceive()方法執(zhí)行完畢,才會執(zhí)行優(yōu)先級低的廣播接受者的onReceive()方法。同時,當前正在執(zhí)行的廣播接收者能夠終止廣播的傳播。

Tips:粘性廣播已經(jīng)被棄用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容