一、簡介
1.定義:廣播接收器,即接收通過某一頻道(Action)發送的廣播,發送者可以是Activity和Service。
2、作用:
1) 監聽系統的廣播,並做相應的處理,如電量過低時需要保存相關數據,或發出通知警告用戶
2)後臺運行的服務,如經過耗時操作後,獲取了網絡數據,通過廣播的方式通知用戶。
3、常用的系統廣播:注意:系統廣播要嚴格按照官方API的說明方式使用
1)Intent.ACTION_BOOT_COMPLETED 系統開機啓動完成
2)Intent.ACTION_SHUTDOWN 關機提醒廣播
3)Intent.ACTION_BATTERY_LOW 低電量提醒廣播
4)Intent.ACTION_BATTERY_CHANGED 電量發生變化廣播(僅支持代碼中註冊)
5)Intent.ACTION_SCREEN_OFF 屏幕被關閉
6)Intent.ACTION_SCREEN_ON 屏幕已經被打開
7)Intent.ACTION_USER_PRESENT 屏幕解鎖廣播
8)Intent.ACTION_NEW_OUTGOING_CALL 撥號廣播
9) TelephonyManager.ACTION_PHONE_STATE_CHANGED 來電時電話狀態變化廣播,如響玲、空置、掛斷
10) Telephony.Sms.Intents.SMS_RECEIVED_ACTION 接收短信的廣播
二、用法
1.步驟
1)創建類,繼承BroadcastReceiver類
2) 重寫onReceiver(Context,Intent)方法
3) 註冊廣播
-在AndroidManifest.xml中註冊(全局)
-動態註冊(局部):registerReceiver(BroadcastReceiver,IntentFilter)
4)發送廣播
- Context.sendBroadcast(Intent)
- Context.sendBroadcast(Intent,String) 帶有權限發送廣播
三、廣播的生命週期
1.繼承後需要重寫的唯一 一個方法onReceiver(Context,Intent)
2.在這個方法裏可以做的事情
1)Toast
2)NotifyManager
3)Context.startActivity(Intent)
4)Context.sendBroadcast
5)Context.startService
6)IBinder BroadcastReciver.peekService(Context,Intent)
3.注意事項
1)廣播接收者的生命週期是非常短暫的,在接收到廣播的時候創建,onReceive()方法結束之後銷燬
2)廣播接收者中不要做一些耗時的工作,否則會彈出Application No Response錯誤對話框
3)最好也不要在廣播接收者中創建子線程做耗時的工作,因爲廣播接收者被銷燬後進程就成爲了空進程,很容易被系統殺掉
4)耗時的較長的工作最好放在服務中完成
四、廣播的分類
1、標準廣播:
是一種完全異步執行的廣播,在廣播發出之後,所有的廣播接收器幾乎都會在同一時刻接收到這條廣播信息,因此它們之間沒有任何先後順序可言。這種廣播的效率會比較高,但同時也意味着它是無法被攔截的。
2、有序廣播:
是一種同步執行的廣播,在廣播發出之後,同一時刻只會有一個廣播接收器能接受到這條廣播消息,當這個廣播接收器中的邏輯執行完畢後,廣播纔會繼續傳遞。所以此時的廣播接收是有先後順序的,優先級高的廣播接收器就可以先接收到廣播消息,並且前面的廣播接收器還可以截斷正在傳遞的廣播,這樣後面的廣播接收器就無法接收到廣播消息了。
3、粘性廣播
1)特點:普通的廣播如果onReceive方法執行時間太長,超過10秒的時候系統會將這個廣播置爲可以幹掉的candidate,一旦系統資源不夠的時候,就會幹掉這個廣播而讓它不執行
2)Intent會一直保留到廣播事件結束,沒有所謂的10秒限制
3)sendStickyBroadcast() 發送粘性的廣播
4)android.Manifest.permission.BROADCAST_STICKY 聲明權限
五、廣播的安全性
1.發送廣播時
1)發送帶權限的廣播sendBroadcast(Intent,permission)
2)指定接收廣播的應用包名Intent.setPackage(“com.trainmobile.ss”)
2.在AndroidManifest.xml清單中配置
1)<permisson android:name="" /> 定義權限
2)<uses-permission android:name=".."> 使用權限
3.註冊接收廣播時
1)Context.registBroadcast(Intent,String),String爲接收廣播的權限
2)<receiver androd:exported="false" ..>不接收外部應用的廣播
4.使用本地廣播接收者LocalBroadcastManager
1)所在包:android.support.v4.content
2)LocalBroadcastManager.getInstance(Context)
3)registReceiver(BroadcastReceiver,IntentFilter)
4)sendBroadcast(Intent)
5)sendBroadcastSync(Intent intent)
6)unregisterReceiver(BroadcastReceiver receiver)
六、廣播接收者的使用
1、案例1:接收電池電量改變時發送的廣播
步驟:
接收系統廣播(三大要素:廣播的Action、接收廣播的權限、廣播中包含的數據)
1)自定義廣播接收器類,繼承BroadcastReceiver,並重寫onReceiver()方法
2)註冊廣播接收器,同時通過IntentFilter聲明廣播接收器可以接收的廣播頻道(Action)
3)在廣播接收的方法中,實現相關的操作(UI線程中執行的)
class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//TODO 接收廣播的方法--UI線程中執行的方法
//3.獲取廣播中的數據,並顯示在UI控件上
//獲取電量的等級信息(百分比)
String action = intent.getAction();
Log.i("--", action);
int level = 0;
if(action == Intent.ACTION_BATTERY_CHANGED){
level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
textview.setText("當前電量:" + level + "%");
if(level < 10){
//...
}
} else if(action == Intent.ACTION_BATTERY_LOW){
textview.setText("電量過低");
}else if(action == Intent.ACTION_POWER_CONNECTED){
textview.setText("電源連接");
}else if(action == Intent.ACTION_POWER_DISCONNECTED){
textview.setText("電源斷開");
Intent infoIntent = new Intent(context, InfoActivity.class);
context.startActivity(infoIntent);
}
}
}
myReceiver = new MyReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
//增加可以接收的廣播頻道
filter.addAction(Intent.ACTION_BATTERY_LOW);
filter.addAction(Intent.ACTION_POWER_CONNECTED);//電源連接的廣播
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);//電源斷開連接的廣播
//2.註冊廣播接收器-接收系統點亮改變的廣播
registerReceiver(myReceiver, filter);
2、案例2:開機自自動:實現很簡單
1)自定義一個廣播接收者
public class RootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent mainIntent = new Intent(context, MainActivity.class);
context.startActivity(mainIntent);
}
}
2)在清單文件中註冊廣播接收者
<receiver android:name="com.example.broadcastreceiver_2.RootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_USER_PRESENT" />
<action android:name="android.intent.action.ACTION_SCREEN_OFF" />
<action android:name="android.intent.action.ACTION_SCREEN_ON" />
</intent-filter>
</receiver>
3)關機開機試試看,實際開發中,一般的應用開機自啓動都會被拒絕
3、案例3:有序廣播的發送
1)定義三個自定義廣播接收器
2)在清單文件中註冊
<receiver android:name="com.beiing.broadcastreceiver_4.MyReceiver_1" >
<intent-filter>
<action android:name="com.beiing.broadcast.print" />
</intent-filter>
</receiver>
<receiver android:name="com.beiing.broadcastreceiver_4.MyReceiver_2" >
<intent-filter>
<action android:name="com.beiing.broadcast.print" />
</intent-filter>
</receiver>
<!-- android:exported="false" 不接受外部應用發送的廣播 -->
<receiver android:name="com.beiing.broadcastreceiver_4.MyReceiver_3" >
<!-- 設置優先級 -1000~1000 -->
<intent-filter android:priority="100" >
<action android:name="com.beiing.broadcast.print" />
</intent-filter>
</receiver>
3)發送廣播,看三個廣播接收器的打印日誌
4)測試:當發送標準廣播時,sendBroadcast(。。),三個廣播接收者會按註冊的先後打印日誌,然後把廣播接收者3設置優先級高於1和2發送一個有序廣播,sendOrderedBroadcast(。。),這樣3會最先接收,然後1、2接收,如果這時候在3中調用切斷廣播的方法abortBroadcast();
廣播將不會再往後發送。
最後說一點:之前講到的handler可以進行子線程和主線程通信,現在通過發送廣播和接收廣播的方式也可以進行子線程和主線程通信。