1. 程式人生 > >Android複習之旅--BroadcastReceiver

Android複習之旅--BroadcastReceiver

在Android系統中,廣播(Broadcast)是一種運用在應用程式之間傳遞訊息的機制,廣播接收者(BroadcastReceiver)是用來過濾、接收並響應廣播的一類元件。通過廣播接收者可以監聽系統中的廣播資訊,在不同元件之間進行通訊。

收音機 –> 廣播接收者
電臺基站 –> 廣播


為了在某個事件發生後執行某些操作,所以應用中要定義一個廣播接收者,用來監聽某個事件。

廣播接收者

  1. 建立
    建立一個類繼承BroadcastReceiver,讓後重寫onReceiver()方法

    onReceiver()方法執行在主執行緒,儘量不要再onReceiver()方法裡進行耗時的操作,因為該方法的執行時間不能超過10秒,否則會ANR。複雜的業務處理可以開啟一個服務或進入到另一個應用中。此方法執行完畢會自動銷燬

    public class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceiver(Context context, Intent intent) {
                       // TODO 事件發生後回撥此方法
        }
    }
  2. 註冊

    註冊廣播有兩種方式:常駐型廣播、非常駐型廣播

    • 常駐型廣播

    當應用程式關閉後,如果接收到其他應用程式發出的廣播,那麼該程式會自動重新啟動。需要在清單檔案中註冊

    <receiver android:name="cn.rixin.myreceiver.MyReceiver">
        <intent-filter>
            <!-- 簡訊接收 -->
            <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
        </intent-filter>
    </receiver>

    其他系統廣播事件參考百度文庫

    • 非常駐型廣播

    依賴於註冊廣播的元件的生命週期,如在Activity中註冊的廣播接收者在Activity銷燬後廣播也會隨之被移除。需要在程式碼中動態註冊,最好在Activity的onResume()和onPause()方法中進行註冊移除。

    // 在onResume()方法中
    MyBroadcastReceiver receiver = new MyBroadcastReceiver();
    // 例項化過濾器並設定要過濾的廣播
    String action = "android.provider.Telephony.SMS_RECEIVED";
    IntentFilter intentFilter = new IntentFilter(action);
    // 註冊廣播
    registerReceiver(receiver, intentFilter);
    
    // 在onPause()方法中
    // 移除廣播
    unregisterReceiver(receiver);

安全升級

4.0以下的版本,任何廣播接收者apk只要被裝到手機就立刻生效。不管應用程式程序是否執行。

4.0以及4.0以上的版本,要求應用程式必須有UI介面(Activity) 廣播接收者才能生效,如果使用者點選了強行停止,應用程式就完全關閉了,廣播接收者就失效了。如果使用者沒有點選過強行停止,即使應用程式程序不存在,也會自動的執行起來。

Android系統把許多常用的事件內建成了廣播機制,一旦事件產生了就會向全系統傳送一個廣播訊息。例如手機電量不足、有人給你傳送了簡訊、你向外撥打了電話、手機啟動完畢等等,系統都會發送一條相應的廣播。當然,也可以自定義廣播事件,主要用於應用內的通訊。


既然有廣播接收者,那自然是得有廣播才行的,因為得要知道廣播後才能建立相應的廣播接收者

廣播

  • 系統廣播
    Android系統中內建了許多的廣播事件,只要是涉及到手機的基本操作(如開機關機、網路狀態、拍照等)都會發送相應的廣播

    Intent intent = new Intent();
    // 定義廣播的事件型別
    intent.setAction("android.provider.Telephony.SMS_RECEIVED");
    // 可攜帶資料
    // intent.putExtra(key, value);
    // 傳送廣播
    sendBroadcast(intent);

    系統中的廣播事件 – 參考百度文庫,或者自己google搜尋
    注意:有些廣播事件是需要註冊相應的許可權的

  • 自定義廣播

    Intent intent = new Intent();
    // 定義廣播的事件型別,字串(自定義,最好包名+字串)
    intent.setAction("com.rixin.sendBroadcast.FRX");
    // 可攜帶資料
    // intent.putExtra(key, value);
    // 傳送廣播
    sendBroadcast(intent);
    
    // 傳送帶許可權的廣播(許可權自定義)
    sendBroadcast(intent, "com.rixin.sendBroadcast.KEY");
    
    // 廣播接收者接收帶許可權的廣播時需要註冊許可權
    <permission android:label="key" android:name="cn.rixin.sendBroadcast.KEY"></permission>
    <uses-permission android:name="cn.rixin.sendBroadcast.KEY"/>

廣播型別

Android系統中根據廣播的執行順序不同分為無序廣播和有序廣播。

  • 無序廣播(非同步執行)

    廣播發送的時候,接收者接收沒有先後順序,無序廣播不可以被攔截,不可以修改結果資料
    中央人民廣播電臺:每晚7點整 –> sendBroadcast() —>所有人

  • 有序廣播(同步執行)

    廣播發送的時候,接收者是按照優先順序先後順序接收的,有序廣播可以被攔截,可以修改結果資料。如果指定了最終的接收者,最終的接收者一定會收到訊息。
    中央向地方下達檔案:中央–>省–>市–>鄉–>農民

    Intent intent = new Intent();
    intent.setAction("cn.rixin.zhongyang.bokuan");
    // 傳送無許可權的有序廣播
    sendOrderedBroadcast(intent, null);
    
    /** 傳送帶資料的有序廣播
     *
     * intent:意圖
     * receiverPermission:接收者的許可權
     * resultReceiver:指定接收者(設定為null後無論什麼情況,都會接收到廣播資訊)
     * scheduler:訊息處理者(一般設定為null)
     * initialCode:初始碼 
     * initialData:資料
     * initialExtras:intent裡面攜帶的額外引數
     */
    sendOrderedBroadcast(intent, "cn.rixin.orderbroadcast.shoukuan", null, null, 8, "撥款100萬元", null);

    高優先順序的廣播接收者接收到廣播後可以對廣播進行一些操作,比如修改資料,終止廣播等。

    setResultData(String data); // 修改有序廣播中的資料
    abortBroadcast(); // 終止有序廣播

    有序廣播的優先順序是在intent-filter過濾器裡設定priority屬性,屬性值範圍在-1000~1000之間。如果兩個廣播接收者的優先順序相同,則先註冊的元件優先收到廣播;如果兩個應用監聽了同一個廣播事件並設定了相同的優先順序,則先安裝的應用優先接收到廣播。

    <receiver android:name="cn.rixin.orderbroadcast.ShengReceiver">
        <intent-filter android:priority="1000">
            <action android:name="cn.rixin.zhongyang.bokuan"/>
        </intent-filter>
    </receiver>

最後,獻上一些常用的系統廣播事件吧

  • 網路狀態
<intent-filter>
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
</intent-filter>
// 記得新增許可權
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  • 電量不足和電量充足
<intent-filter>
    <action android:name="Intent.ACTION_BATTERY_LOW"></action>
    <action android:name="Intent.ACTION_BATTERY_OKAY"></action>
</intent-filter>
  • 插入耳機
<intent-filter>
    <action android:name="Intent.ACTION_HEADSET_PLUG"></action>
</intent-filter>
// 記得新增許可權
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
  • 開機,關機,重啟裝置
<intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED"></action>
    <action android:name="Intent.ACTION_SHUTDOWN"></action>
    <action android:name="Intent.ACTION_REBOOT"></action>
</intent-filter>
// 記得新增許可權
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  • 應用程式的安裝、解除安裝、替換
<intent-filter>
    <action android:name="android.intent.action.PACKAGE_ADDED"></action> 
    <action android:name="android.intent.action.PACKAGE_REMOVED"></action> 
    <action android:name="android.intent.action.PACKAGE_REPLACED"></action> 
    <!-- 資料的型別是一個apk的包 package:// --> 
    <data android:scheme="package"></data>
</intent-filter>
  • SD卡的狀態(裝載,解除安裝,不存在)
<intent-filter>
    <action android:name="android.intent.action.MEDIA_MOUNTED"></action>
    <action android:name="android.intent.action.MEDIA_REMOVED"></action>
    <action android:name="android.intent.action.MEDIA_UNMOUNTED"></action>
    <!-- 資料的型別是一個檔案 --> 
    <data android:scheme="file"></data>
</intent-filter>


  • 螢幕鎖屏和解鎖

這是一組特殊的廣播事件,接收這些廣播事件採用清單檔案Mainfast.xml配置是不生效的。需要在程式碼中動態註冊
ScreenOnReceiver receiver = new ScreenOnReceiver()
registerReceiver(receiver, new IntentFilter("android.intent.action.SCREEN_ON"));

ScreenOffReceiver receiver = new ScreenOffReceiver()
registerReceiver(receiver, new IntentFilter("android.intent.action.SCREEN_OFF"));

// 記得移除
unregisterReceiver(receiver);

如果這個廣播事件經常發生,一般就不允許採用清單檔案註冊,只能採用程式碼註冊的方式註冊才會生效。程式執行生效–程式停止執行失效。


希望對您有所幫助,歡迎指(吐)(嘈)