Android學習筆記----廣播接收者

/*********************************************************************************************************************/

此博客原本是本人學習Android過程中自己所做的學習筆記,在此分享出來供大家學習,因爲之前只是個人筆記僅供自己回顧複習,所以筆記裏可能借鑑了其他人的一些資料,整理博客的過程中已經忘了資料的來源,所以未做標註,望被鄙人借鑑了資料的原創者們見諒。

/*********************************************************************************************************************/

廣播分類

Android 中的廣播主要可以分爲兩種類型,標準廣播和有序廣播

標準廣播( Normal broadcasts) 是一種完全異步執行的廣播,在廣播發出之後,所有的廣播接收器幾乎都會在同一時刻接收到這條廣播消息,因此它們之間沒有任何先後順序可言。這種廣播的效率會比較高,但同時也意味着它是無法被截斷的。標準廣播的工作流程:


注:標準廣播也叫無序廣播,無序廣播不能設置優先級,沒有abortbroadcast()方法。

有序廣播( Ordered broadcasts) 則是一種同步執行的廣播,在廣播發出之後,同一時刻只會有一個廣播接收器能夠收到這條廣播消息,當這個廣播接收器中的邏輯執行完畢後,廣播纔會繼續傳遞。所以此時的廣播接收器是有先後順序的,優先級高的廣播接收器就可以先 收到廣播消息,並且前面的廣播接收器還可以截斷正在傳遞的廣播,這樣後面的廣播接收器就無法收到廣播消息了。有序廣播的工作流程:

注:有序廣播可以設置優先級,abortbroadcast()方法

/*********************************************************************************************************************/

接收系統廣播

/*********************************************************************************************************************/

創建廣播接收器

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

class NetworkChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager connectionManager = (ConnectivityManager)        .getSystemService(Context.CONNECTIVITY_SERVICE); //獲取網絡狀態管理器
        NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo(); //獲取網絡狀態信息
        if (networkInfo != null && networkInfo.isAvailable()) {
            Toast.makeText(context, "network is available", Toast.LENGTH_SHORT).show(); 
        } else {
            Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show(); 
        }
    }
}

注意:

權限:<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

註冊廣播接收器

廣播接收器可以自由地對自己感興趣的廣播進行註冊,這樣當有相應的廣播發出時,廣播接收器就能夠收到該廣播,並在內部處理相應的邏輯。註冊廣播的方式一般有兩種:
代碼中註冊和在 AndroidManifest.xml 中註冊,其中前者也被稱爲動態註冊,後者也被稱爲靜態註冊。

動態註冊廣播接收器

private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;

intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); //添加廣播接收器想要接收的廣播,此處表示接收網絡狀態變化的廣播
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver, intentFilter);

注意:
動態註冊的廣播接收器一定都要取消註冊才行,這裏我們是在 onDestroy()方法中通過調用 unregisterReceiver(networkChangeReceiver)方法來實現的。

靜態註冊廣播接收器

動態註冊的廣播接收器可以自由地控制註冊與註銷,在靈活性方面有很大的優勢,但是它也存在着一個缺點,即必須要在程序啓動之後才能接收到廣播,因爲註冊的邏輯是寫在onCreate()方法中的,靜態註冊可以讓程序在未啓動的情況下就能接收到廣播一旦應用程序被部署到手機, 廣播接收者就會生效。


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest"
android:versionCode="1"
android:versionName="1.0" >
……
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />//訪問網絡狀態需要的權限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />//監聽系統開機廣播需要的權限
<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    ……
    <receiver android:name=".BootCompleteReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />//標記該廣播接收器接收系統發出的開機廣播
        </intent-filter>
    </receiver>

</application>
</manifest>

注:BootCompleteReceiver是一個自定義的廣播接收器,作用接收開機廣播,然後彈出吐司,顯示開機啓動了

注意:不要在 onReceive()方法中添加過多的邏輯或者進行任何的耗時操作,因爲廣播接收器是運行在主線程中的,而且在廣播接收器中是不允許開啓線程的(因爲廣播接收器的生命週期非常短,開啓線程的話,可能當廣播接收器被回收的時候,而開啓的線程還沒有運行完,導致出錯),當 onReceive()方法運行了較長時間而沒有結束時,程序就會報ANR異常。因此廣播接收器更多的是扮演一種打開程序其他組件的角色,比如創建一條狀態欄通知,或者啓動一個服務等。 

/*********************************************************************************************************************/

發送自定義廣播

/*********************************************************************************************************************/


發送標準廣播

//自定義廣播接收器,接收發送的自定義廣播
public class MyBroadcastReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show(); 
            }
}

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest"
android:versionCode="1"
android:versionName="1.0" >
……
<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    ……
    <receiver android:name=".MyBroadcastReceiver">//註冊自定義的廣播接收器
        <intent-filter>
            <action android:name="com.example.broadcasttest. MY_BROADCAST"/>//標註該廣播接收器接收的廣播類型
            <category android:name="android.intent.category.DEFAULT"/>//注意這個一定要加上不然的話會接收不到廣播  
          </intent-filter>
    </receiver>

</application>
</manifest>

代碼中註冊

        MyBroadcastReceiver rec = new MyBroadcastReceiver();
        IntentFilter intentFileter = new IntentFilter();
        intentFileter.addAction("com.example.broadcasttest. MY_BROADCAST");
        intentFileter.addCategory(Intent.CATEGORY_DEFAULT); //一定要加上addCategory(Intent.CATEGORY_DEFAULT)不然會接收不到自定義的廣播
        registerReceiver(rec,intentFileter);


//發送自定義廣播
Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST"); 
sendBroadcast(intent);

注:應用程序發出的廣播是可以被其他的應用程序接收到的。
         記得動態註冊的廣播接收者都要取消註冊

發送有序廣播
 
只需要將發送標準廣播的代碼改成sendOrderedBroadcast(intent,null)即可

注:第二個參數是一個與權限相關的字符串,這裏傳入 null 就行了

有序廣播可以在AndroidManifest.xml 文件中設置廣播的優先級(通過設置 android:priority屬性)或者在代碼中通過setPriority()方法設置,高優先級的廣播接收器先接收到廣播,可以選擇在高優先級的廣播接收器中,對接收到的廣播進行中斷(調用abortbroadcast()方法)或者對廣播的數據進行修改,讓低優先級的廣播接收器接收到經過修改後的數據。


發送本地廣播

如果只想讓本應用接收到自己發送的廣播,不想讓手機上的其他應用接收到廣播,可以利用”本地廣播“。本地廣播主要就是使用了一個 LocalBroadcastManager 來對廣播進行管理,並提供了發送廣播和註冊廣播接收器的方法。

private IntentFilter intentFilter;

private LocalBroadcastManager localBroadcastManager;

private MyBroadcastReceiver myBroadcastReceiver;

localBroadcastManager = LocalBroadcastManager.getInstance(this);// 獲取實例廣播
 
myBroadcastReceiver 
= new 
MyBroadcastReceiver 
();

intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");

localBroadcastManager.registerReceiver(localReceiver, intentFilter); 
// 註冊本地廣播監聽器


Intent intent = new Intent("
com.example.broadcasttest.LOCAL_BROADCAST
");
localBroadcastManager.sendBroadcast(intent); // 發送本地廣播

注:本地廣播是無法通過靜態註冊的方式來接收的。其實這也完全可以理解,因爲靜態註冊主要就是爲了讓程序在未啓動的情況下也能收到廣播,而發送本地廣播時,我們的程序肯定是已經啓動了,因此也完全不需要使用靜態註冊的功能。

使用本地廣播的幾點優勢 :
1. 可以明確地知道正在發送的廣播不會離開我們的程序,因此不需要擔心機密數據泄漏的問題。
2. 其他的程序無法將廣播發送到我們程序的內部,因此不需要擔心會有安全漏洞的隱患。
3. 發送本地廣播比起發送系統全局廣播將會更加高效。






此博客原本是本人學習Android過程中自己所做的學習筆記,在此分享出來供大家學習,因爲之前只是個人筆記僅供自己回顧複習,所以筆記裏可能借鑑了其他人的一些資料,整理博客的過程中已經忘了資料的來源,所以未做標註,忘被鄙人借鑑了資料的原創者們見諒。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章