1. 程式人生 > >FC 5 廣播機制

FC 5 廣播機制

廣播的註冊方式:

  • 動態註冊
  • 靜態註冊

廣播的傳送方式:

  • 普通廣播
  • 有序廣播
  • 本地廣播

特殊說明

  • 不要在onreceive中新增過多的邏輯或超時操作
  • 本地廣播無法通過靜態註冊方式來接受

關於動態註冊&關於靜態註冊

一種是在活動裡通過程式碼動態註冊,另一種在配置檔案裡靜態註冊。動態註冊的接收器必須要在程式啟動之後才能接收到廣播,而靜態註冊的接收器即便程式未啟動也能接收到廣播,比如想接收到手機開機完成後系統發出的廣播就只能用靜態註冊了。

//動態註冊
public class MainActivity extends AppCompatActivity {
    private IntentFilter intentFilter;
    private NetworkchangeReceiver networkchangeReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /**
         * 首先建立IntentFilter例項,,
         * 添加了android.net.conn.CONNECTIVITY_CHANGE的action,當系統發出這個廣播時,我們就能收到
         * 建立了NetworkchangeReceiver例項,
         * 呼叫registerReceiver對廣播進行動態註冊
         */
        intentFilter = new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        networkchangeReceiver = new NetworkchangeReceiver();
        registerReceiver(networkchangeReceiver, intentFilter);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //動態註冊的廣播必須取消註冊。在onDestroy呼叫unregisterReceiver方法
        unregisterReceiver(networkchangeReceiver);
    }
    /**
     * 定義內部類,NetworkchangeReceiver,
     * 繼承BroadcastReceiver,重寫父類的onReceive方法
     * 每當網路狀態發生變化時,就會執行,這裡簡單toast。
     */
    private class NetworkchangeReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
        }
    }
}
//靜態註冊
//1、new other broadcast Receiver,建立廣播器MyReceiver,重寫onReceive方法
//2、在配置檔案中新增<intent-filter>
//3、新增網路許可權  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>


public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
    }
}


//AndroidManifest的配置檔案裡
      <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
            </intent-filter>
      </receiver>

關於普通廣播

也就是標準廣播,普通廣播是一種完全非同步執行的廣播,在廣播發出之後,所有的廣播接收器幾乎都會在同一時刻接收到這條廣播訊息,因此它們接收的先後是隨機的。另外,接收器不能截斷普通廣播。

  1. 建立廣播接收器
  2. AndroidManifest進行靜態註冊,新增對應的許可權
  3. 介面新增按鈕,mainactivity裡對按鈕新增單擊事件,傳送廣播。
public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "received BroadcastReceiver", Toast.LENGTH_SHORT).show();
    }
}
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
        <receiver
            android:name=".MyReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
 public void onclick(View view) {
        Intent intent = new Intent("firstcode.zs.com.fc_5.MyReceiver");
        sendBroadcast(intent);
    }

關於有序廣播

它是一種同步執行的廣播,在廣播發出之後,同一時刻只會有一個廣播接收器能夠收到這條廣播訊息,當這個廣播接收器中的邏輯執行完畢後,廣播才會繼續傳遞,所以此時的廣播接收器是有先後順序的,且優先順序(priority)高的廣播接收器會先收到廣播訊息。有序廣播可以被接收器截斷使得後面的接收器無法收到它。

  1. 傳送一個有序廣播和普通廣播的方法有細微的區別,只需要將sendBroadcast()方法改成sendOrderedBroadcast()方法, 它接收兩個引數,第一個引數仍是Intent,第二個引數是一個與許可權相關的字串,這裡傳入 null就行。
  2. 只要在註冊的時候設定它的優先順序android:priority為100,數值越大優先順序就越高,現在就能保證它一定會在MyReceiver之前收到廣播。
  3. 如果在AnotherReceiver的onReceive()方法中呼叫了abortBroadcast()方法,表示將這條廣播截斷,後面的廣播接收器將無法再接收到這條廣播。現在重新執行程式,並點選一下按鈕,然後會發現,只有AnotherReceiver中的Toast資訊彈出,說明這條廣播經過AnotherReceiver之後確實是終止傳遞了。

關於本地廣播

使用本地廣播,自己在之前用過,參考這篇文章

前面學到的的廣播都屬於系統全域性廣播,即發出的廣播可被其他應用程式接收到,且我們也可接收到其他任何應用程式傳送的廣播。為了能夠簡單地解決全域性廣播可能帶來的安全性問題,Android引入了一套本地廣播機制,使用這個機制發出的廣播只能夠在應用程式的內部進行傳遞,並且廣播接收器也只能接收本應用程式發出的廣播。

實現本地廣播的傳送和接收也很簡單,主要使用了一個LocalBroadcastManager來對廣播進行管理,並提供了相應的傳送廣播和註冊廣播接收器的方法。

public class MainActivity extends AppCompatActivity {
    private IntentFilter intentFilter;
    private LocalReceiver localReceiver;
    private LocalBroadcastManager localBroadcastManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        localBroadcastManager = LocalBroadcastManager.getInstance(this); // 獲取例項
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("firstcode.zs.com.fc_5.LOCAL_BROADCAST");
                localBroadcastManager.sendBroadcast(intent); // 傳送本地廣播
            }
        });
        intentFilter = new IntentFilter();
        intentFilter.addAction("firstcode.zs.com.fc_5.LOCAL_BROADCAST");
        localReceiver = new LocalReceiver();
        localBroadcastManager.registerReceiver(localReceiver, intentFilter); // 註冊本地廣播監聽器
    }

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

    class LocalReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "received local broadcast", Toast.LENGTH_SHORT).show();
        }
    }
}

關於不要在onreceive中新增過多的邏輯或超時操作:

廣播接收器不允許開啟執行緒。當onreceive方法運行了較長時間沒有結束時,程式就會報錯。

關於本地廣播無法通過靜態註冊方式來接收

靜態註冊主要是為了讓程式在未啟動的情況下也能收到廣播,而傳送本地廣播是我們的程式肯定已經啟動了,完全不需要靜態註冊。

FC系列文章,均參考郭神的《第一行程式碼》,所以這裡的文章均為轉載