1. 程式人生 > >Android 本地廣播與全域性廣播

Android 本地廣播與全域性廣播

1. 全域性廣播和本地廣播的區別

  • 全域性廣播:發出去的廣播可以被任何應用程式接收到

  • 本地廣播:發出去的廣播只能被本應用程式接收到,一般使用LocalBroadcastManager對廣播進行管理。

2.註冊廣播

註冊廣播的方式一般有兩種:

  • 在程式碼註冊(動態註冊)
  • 在AndroidManifest.xml中註冊(靜態註冊)

動態註冊廣播監聽

新建一個類,讓它繼承自BroadcastReceiver並重寫父類的onReceive()方法就行了。當廣播到來時,onReceive()方法會得到執行,開發者就可以在這個方法中進行處理相應的邏輯。

//動態註冊廣播
 IntentFilter myIntentFilter = new
IntentFilter(); myIntentFilter.addAction(Constant.ACTION_NAME); registerReceiver(new MyReceiver(), myIntentFilter);
public class MyReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            //相應邏輯處理
        }
    }

靜態註冊廣播監聽

動態註冊廣播缺點:動態註冊的廣播接收器可以自由的控制註冊於登出,在靈活性方面有很大的優勢,但是它也存在一個缺點,即必須要在程式啟動之後才能接收廣播。

靜態註冊就可以很好的彌補這個缺點,想要使用靜態註冊必須滿足兩點:

  • 靜態註冊同樣是要新建一個類繼承BroadcastReceiver並重寫onReceive()方法
  • 還需要在AndroidManifest.xml中將這個廣播接收器的類名註冊進去
public class MyReceiver extends BroadcastReceiver {

        @Override
        public void onReceive
(Context context, Intent intent) { //相應邏輯處理 } }
AndroidManifest.xml

<receiver android:name=".MyReceiver"/>

2.廣播接收器

Android中廣播接收器主要可分兩種型別:

  • 標準廣播

    標準廣播是一種完全非同步執行的廣播,在廣播發出去之後,所有的廣播接收
    器幾乎都會在同一時刻接收到這條訊息,因此它們之間無任何先後順序可言。這種廣播的效率會比較高,但同時也意味著它是無法被截斷的。

  • 有序廣播

    有序廣播則是一種同步執行的廣播,在廣播發出去之後,同一時刻只會有一個廣播接收器能夠收到這條訊息,當這個廣播接收器中的邏輯執行完畢後,廣播才會繼續傳遞。所以此時的廣播接收器是有先後順序的,優先順序高的廣播接收器就可以先接收到廣播訊息,並且前面的廣播接收器還可以截斷正在傳遞的關公,這樣的廣播接收器就無法接收到訊息了。

傳送標準廣播

1.先定義一個廣播接收器來準備接受此廣播

public static class MyBroadcast extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
         Toast.makeText(context, "接收到了自定義廣播", Toast.LENGTH_SHORT).show();
    }
}
2.在AndroidManifest.xml中註冊這個廣播接收器

<receiver android:name=".MyBroadcast">
     <intent-filter>
          <action android:name="com.example.mybroadcast" />
     </intent-filter>
</receiver>
3.傳送一個廣播

button.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
         Intent intent = new Intent("com.example.mybroadcast");
         sendBroadcast(intent);
      }
});

傳送有序廣播

為了直觀的研究有序廣播,我又新建了一個專案。這個專案的內容和之前的一樣
(廣播接收器名為 MyBroadcast_B)

傳送有序廣播只需要改動一行程式碼,即將sendBroadcast()方法改成sendOrderedBroadcast()方法。sendOrderedBroadcast()方法接收兩個引數,第一個仍是Intent,第二個引數是與許可權相關的字串,這裡傳入null就行了

button.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
        Intent intent = new Intent("com.example.mybroadcast");
        sendOrderedBroadcast(intent, null);
     }
});

通過android:priority屬性給廣播接收器設定優先順序,從而設定廣播接收器的先後順序,優先順序比較高的接收器就可以先收到廣播。

<receiver android:name=".MyBroadcast_B">
    <intent-filter android:priority="100">
       <action android:name="com.example.mybroadcast" />
    </intent-filter>
</receiver>

既然已經獲得了優先權,那麼我就可以讓MyBroadcastReceive選擇是否允許廣播繼續傳遞了,可以在onReceive()方法中新增abortBroadcast()方法,用來截斷廣播。

public static class MyBroadcast_B extends BroadcastReceiver {

   @Override
   public void onReceive(Context context, Intent intent) {
      Toast.makeText(context, "接收到了自定義廣播", Toast.LENGTH_SHORT).show();

      /*當MyBroadcast_B 接收到訊息後 並截斷。
       *此時MyBroadcast將不會再接收到廣播 
       */
      abortBroadcast();
   }
}

全域性廣播安全性

為了提高全域性廣播的安全性,一般會增加許可權等控制

<permission android:name="com.example.mybroadcast"/>

<receiver  android:name=".MyBroadcast_B"
           android:exported="true"
           android:permission="com.example.mybroadcast">
     <intent-filter>
        <action android:name="com.example.mybroadcast" />
     </intent-filter>
</receiver>

3.本地廣播

之前所講的傳送和接收廣播都是屬於系統全域性廣播,也就是說發出的廣播可以被其他任何應用程式接收到,這樣大大降低了安全性。因此Android中引入了一套本地廣播機制,使用這個機制發出的廣播只能夠在應用程式的內部進行傳遞,並且廣播接收器也只接收來自本地應該程式發出的廣播,大大的解決了廣播的安全性問題。用法並不複雜,主要就是使用了一個LocalBroadcastManager來對廣播進行管理,並提供了傳送廣播和註冊廣播接收器的方法

public class LocalBroadcastMngActivity extends AppCompatActivity {

    private IntentFilter intentFilter;
    private LocalReceiver localReceiver;
    private LocalBroadcastManager localBroadcastManager;

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

        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("com.example.mybroadcast");
                localBroadcastManager.sendBroadcast(intent);//傳送本地廣播
            }
        });
        intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.mybroadcast");
        localReceiver = new LocalReceiver();
        //註冊本地廣播監聽器
        localBroadcastManager.registerReceiver(localReceiver, intentFilter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(localReceiver);//取消註冊
    }
}
class LocalReceiver extends BroadcastReceiver {
 @Override
 public void onReceive(Context context, Intent intent) {
    Toast.makeText(LocalBroadcastMngActivity.this, "接收到本地廣播", Toast.LENGTH_SHORT).show();
 }
}

地廣播的用法和之前動態註冊廣播的用法大致相同,只不過現在首先是通過LocalBroadcastManagergetInstance()方法得到了它的一個例項;然後再註冊廣播接收器的時候呼叫的是LocalBraodcastManagersendBroadcast()方法,僅此而已。
另外一點還需要說明,本地廣播是無法通過靜態註冊的方式來接收的。

本地廣播的優點

  1. 可以明確的知道正在傳送的廣播不會離開我們的程式,因此不需要擔心機密資料洩露問題

  2. 其他的程式無法將廣播發送到我們程式的內部,因此不需要擔心會有安全漏洞的隱患。

  3. 傳送本地廣播比起傳送系統全域性廣播將會更加高效。