Android廣播BroadcastReceiver

android中的四大組件之一,也是一種消息機制,可在app內、app間傳遞消息。還可以接受系統發送的廣播(開機廣播、網絡狀態等)

自定義廣播接收器

public class SomeReceiver extends BroadcastReceiver{  
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if("com.my.action.SOME_ACTION".equals(action)){
            //...
        }
    }  
}  

onReceive()方法必須在10秒內完成,否則導致ANR。耗時操作最好發送到Service中執行,因爲BroadcastReceiver生命週期短Thread容易被回收。

註冊

靜態註冊

在AndroidManifest.xml的<application/>中:

<receiver android:name=".SomeReceiver"
     android:exported="true"
     android:permission="string"
     android:process="string">
     <intent-filter android:priority="int">
          <action android:name="com.my.action.SOME_ACTION"/>
     </intent-filter>
</receiver>

一個廣播可以設置多個action。

幾個屬性說明下:

屬性 說明
android:exported 是否接收外部app發送的廣播,如果設置了intent-filter則默認爲true,否則爲false
android:permission 如果設置此屬性,則發送方必須聲明相應權限時發送的廣播才能被接收到
android:process 該廣播接收器組件運行時的進程。app進程或獨立進程
android:priority 優先級設置[-1000, 1000]

動態註冊

public class MainActivity extends Activity {
    public static final String ACTION_1 = "com.my.action.SOME_ACTION";
    private BroadcastReceiver mBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mBroadcastReceiver = new SomeReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ACTION_1);
        registerReceiver(mBroadcastReceiver, intentFilter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mBroadcastReceiver);
    }
}

註冊 / 取消註冊 結對使用。此時廣播接收在Activity生命週期內。

發送/類型

普通廣播(NormalBroadcast)

Intent intent = new Intent();  
intent.setAction("com.my.action.SOME_ACTION");  
context.sendBroadcast(intent);  

被所有廣播接收者接收到

有序廣播(OrderedBroadcast)

Intent intent = new Intent();  
intent.setAction("com.my.action.SOME_ACTION");  
context.sendOrderedBroadcast(intent, null);  

設置優先級android:priority=”int”,範圍[-1000, 1000],值越大優先級別越高;
或 IntentFilter.setPriority() 設置;被接收者依次接收廣播;
如:優先級A > B > C,則傳遞順序A -> B -> C。
可以被攔截而不往下傳遞,BroadcastReceiver.abortBroadcast()此方法意味着廣播不再傳播出去。
可以修改數據,在intent中改數據或者添加數據,後面的接收器可以接收這些數據;

如果都有兩個廣播都設置成1000,會出現啥情況?(因爲沒試過,我也不知道)

關於顯式/隱式意圖

廣播組件一般使用的都是隱式。

顯式意圖發送廣播

發送時指定廣播接收器的具體類(類似一對一私聊)

隱式意圖發送廣播

<intent-filter>  
   <action android:name="com.my.action.SOME_ACTION"/>  
   <category android:name="android.intent.category.DEFAULT"/>  
   <data android:mimeType="*/*"/>  
   <data android:scheme="string" android:host="string"/>  
</intent-filter>  

按接收規則聲明註冊的多個廣播接收器皆可接收到廣播(類似一對多羣發);如發送的action和接收的action一致則接受者都能接收(比很多app都會監聽開機廣播)。

版本變更

Android 3.1(api 12) 對stoped應用的啓動控制
從Android3.1開始,系統包管理器會管理應用是不是stoped狀態, 應用stoped狀態是指第一次安裝還沒有被啓動或者被人爲的在應用管理中強行停止了的狀態。 並且所有由系統發出的廣播都設置了FLAG_EXCLUDE_STOPPED_PACKAGES',這樣做防止了後臺服務的廣播無意的或不必要的啓動那些處於stoped狀態的應用;
要注意的是應用的stoped狀態非指activity的stoped狀態,系統會單獨的管理新加入的狀態,不要混爲一談;
在platform中定義了兩個intent的flag:

    /**
     * If set, this intent will not match any components in packages that
     * are currently stopped.  If this is not set, then the default behavior
     * is to include such applications in the result.
     */
    public static final int FLAG_EXCLUDE_STOPPED_PACKAGES = 0x00000010;

    /**
     * If set, this intent will always match any components in packages that
     * are currently stopped.  This is the default behavior when
     * {@link #FLAG_EXCLUDE_STOPPED_PACKAGES} is not set.  If both of these
     * flags are set, this one wins (it allows overriding of exclude for
     * places where the framework may automatically set the exclude flag).
     */
    public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 0x00000020;

比如發送廣播時,當intent中沒有設置這兩個falg或者都設置了,則廣播都會發送到那些處於stoped狀態的應用;如果只設置了FLAG_EXCLUDE_STOPPED_PACKAGES 則處於stoped狀態的應用不會收到廣播;


Android5.0(21) deprecated粘滯性廣播 Context.sendStickyBroadcast()
此廣播使用時需要設置權限


Android (22) android.support.v4中加入的 LocalBroadcastManager


Android8.0 廣播限制

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