Android四大组件之广播接收器BroadcastReceiver
Android系統(tǒng)的廣播有一個全局監(jiān)聽器,專門用于監(jiān)聽/接收應(yīng)用程序發(fā)出的廣播消息。
廣播的作用
- 可以實(shí)現(xiàn)不同組件之間的通信(這些組件可以是同一應(yīng)用內(nèi)的或不同應(yīng)用內(nèi)的。)
- 多線程通信
- 與Android系統(tǒng)通信,如電話呼入、網(wǎng)絡(luò)可用時等。
廣播的通信模型
廣播的使用流程
自定義廣播接收者BroadcastReceiver
(1)繼承BroadcastReceiver
(2)重寫onReceive()方法
注意: 默認(rèn)情況下,廣播接收器運(yùn)行在UI線程,因此,onReceive()方法不能執(zhí)行耗時操作,否則將導(dǎo)致ANR。
廣播接收者注冊
| 靜態(tài)注冊 | 在AndroidManifest.xml里通過標(biāo)簽聲明 | 常駐,不受任何組件的生命周期影響,即使應(yīng)用程序關(guān)閉后,有廣播消息來,程序依舊會被系統(tǒng)調(diào)用。缺點(diǎn):耗電、占內(nèi)存 | 需要時刻監(jiān)聽廣播 |
| 動態(tài)注冊 | 在代碼中調(diào)用Context.registerReceiver()方法 | 不常駐,生命周期跟隨組件變化 ,組件結(jié)束,廣播就結(jié)束,在組件結(jié)束前,必須移除廣播接收者,否則會造成內(nèi)存泄漏。 | 在特定時刻需要監(jiān)聽廣播 |
靜態(tài)注冊:
// 用于指定此廣播接收器將接收的廣播類型// 本示例中給出的是用于接收網(wǎng)絡(luò)狀態(tài)改變時發(fā)出的廣播<receiver android:name=".MyBroadcastReceiver"><intent-filter><action android:name="android.net.conn.CONNECTIVITY_CHANGE"/></intent-filter></receiver>屬性說明:
<receiver// 能否接收其他App發(fā)出的廣播 // 默認(rèn)值是由receiver中有無intent-filter決定的:如果有的話,為true,否則為falseandroid:enabled=["true" | "false"]android:exported=["true" | "false"]android:icon="drawable resource"android:label="string resource"// 繼承BroadcastReceiver子類的類名android:name=".mBroadcastReceiver"// 具有相應(yīng)權(quán)限的廣播發(fā)送者發(fā)送的廣播才能被此BroadcastReceiver所接收;android:permission="string"// BroadcastReceiver運(yùn)行所處的進(jìn)程// 默認(rèn)為app的進(jìn)程,可以指定獨(dú)立的進(jìn)程// 注:Android四大基本組件都可以通過此屬性指定自己的獨(dú)立進(jìn)程android:process="string" >// 指定此廣播接收者將接收的廣播類型<receiver android:name=".MyBroadcastReceiver"><intent-filter><action android:name="android.net.conn.CONNECTIVITY_CHANGE"/></intent-filter></receiver> </receiver>動態(tài)注冊:
動態(tài)廣播最好在Activity 的 onResume()注冊、onPause()注銷。有注冊就必然得有注銷,否則會導(dǎo)致內(nèi)存泄漏。重復(fù)注冊、注銷是不允許出現(xiàn)的。
-
之所以不在onCreate() & onDestory() 或 onStart() & onStop()注冊、注銷是因?yàn)?#xff1a;
當(dāng)系統(tǒng)因?yàn)閮?nèi)存不足時要回收Activity占用的資源時,Activity在執(zhí)行完onPause()方法后就會被銷毀,有些生命周期方法onStop(),onDestory()就不會執(zhí)行。當(dāng)再回到此Activity時,是從onCreate方法開始執(zhí)行。如:假設(shè)我們將廣播的注銷放在onStop(),onDestory()方法里的話,有可能在Activity被銷毀后還未執(zhí)行onStop(),onDestory()方法,即廣播仍還未注銷,從而導(dǎo)致內(nèi)存泄露。但是,onPause()一定會被執(zhí)行,從而保證了廣播在App銷毀前一定會被注銷,從而防止了內(nèi)存泄露。
廣播的類型
| 普通廣播(Normal Broadcast) | 自定義 intent的廣播(最常用) |
| 系統(tǒng)廣播(System Broadcast) | Android中內(nèi)置的系統(tǒng)廣播,如開機(jī)、網(wǎng)絡(luò)狀態(tài)變化、拍照等等,每個廣播都有特定的intent-filter和具體的action |
| 有序廣播(Ordered Broadcast) | 發(fā)送出去的廣播被廣播接收者按照先后順序接收 |
| App應(yīng)用內(nèi)廣播(Local Broadcast) | 廣播的發(fā)送者和接收者都同屬于一個App。 |
普通廣播示例
發(fā)送廣播如下:
Intent intent = new Intent(); // 對應(yīng)BroadcastReceiver中intentFilter的action intent.setAction(BROADCAST_ACTION); // 發(fā)送廣播 sendBroadcast(intent);完整例子:
MyBroadcastReceiver:
注冊、注銷和發(fā)送廣播:
public class MainActivity extends AppCompatActivity {private MyBroadcastReceiver myBroadcastReceiver;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 發(fā)廣播findViewById(R.id.me).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent();intent.putExtra("name","wongkyunban");// 對應(yīng)BroadcastReceiver中intentFilter的actionintent.setAction("com.haha.haha.this.is.my.broadcast");// 發(fā)送廣播sendBroadcast(intent);}});}// 注冊@Overrideprotected void onResume() {super.onResume();// 1. 實(shí)例化BroadcastReceiver子類和IntentFiltermyBroadcastReceiver = new MyBroadcastReceiver();IntentFilter intentFilter = new IntentFilter();// 2. 設(shè)置接收廣播的類型,自定義一個廣播intentFilter.addAction("com.haha.haha.this.is.my.broadcast");// 3. 動態(tài)注冊:調(diào)用Context的registerReceiver()方法registerReceiver(myBroadcastReceiver, intentFilter);}// 注銷// 注冊廣播后,要在相應(yīng)位置記得銷毀廣播// 即在onPause() 中unregisterReceiver(mBroadcastReceiver)// 當(dāng)此Activity實(shí)例化時,會動態(tài)將MyBroadcastReceiver注冊到系統(tǒng)中// 當(dāng)此Activity銷毀時,動態(tài)注冊的MyBroadcastReceiver將不再接收到相應(yīng)的廣播。@Overrideprotected void onPause() {super.onPause();//銷毀在onResume()方法中的廣播unregisterReceiver(myBroadcastReceiver);} }注意:
若發(fā)送廣播有相應(yīng)權(quán)限,那么廣播接收者也需要相應(yīng)權(quán)限,通過屬性字段配置的。
有序廣播示例
廣播接收者接收廣播的順序規(guī)則:
- 按照Priority屬性值從大-小排序;
- Priority屬性相同者,動態(tài)注冊的廣播優(yōu)先;
先接收的廣播接收者可以對廣播進(jìn)行截斷,即后接收的廣播接收者將不再接收到此廣播;
先接收的廣播接收者可以對廣播進(jìn)行修改,那么后接收的廣播接收者將接收到被修改后的廣播。
有序廣播的使用過程與普通廣播類似,只是在于廣播的發(fā)送方式不同:
App應(yīng)用內(nèi)廣播示例
Android中的廣播可以跨App直接通信(exported對于有intent-filter情況下默認(rèn)值為true)。這種情況 可能帶來一些問題,如:
(1)其他App發(fā)出與當(dāng)前App intent-filter相匹配的廣播,將導(dǎo)致當(dāng)前App不斷接收廣播并處理;
(2)其他App注冊與當(dāng)前App一致的intent-filter用于接收廣播,獲取廣播具體信息,而導(dǎo)致的安全性問題。
解決方案:
使用App應(yīng)用內(nèi)廣播(Local Broadcast),使得廣播的發(fā)送者和接收者都同屬于一個App。這樣可以提高App的安全性高和效率。
-
方法1: 將全局廣播設(shè)置成局部廣播
注冊廣播時將exported屬性設(shè)置為false,使得非本App內(nèi)部發(fā)出的此廣播不被接收;
在廣播發(fā)送和接收時,增設(shè)相應(yīng)權(quán)限permission,用于權(quán)限驗(yàn)證;
發(fā)送廣播時指定該廣播接收器所在的包名,此廣播將只會發(fā)送到此包中的App內(nèi)與之相匹配的有效廣播接收器中。通過intent.setPackage(packageName)指定包名。
-
方法2:使用封裝好的LocalBroadcastManager類
對于LocalBroadcastManager方式發(fā)送的應(yīng)用內(nèi)廣播,只能通過LocalBroadcastManager動態(tài)注冊,不能靜態(tài)注冊。
注冊/注銷廣播接收器和發(fā)送廣播時將參數(shù)的context變成了LocalBroadcastManager的單一實(shí)例。示例如下:
系統(tǒng)廣播示例
這個我們也是很常用的。
Android系統(tǒng)廣播action如下:
| 監(jiān)聽網(wǎng)絡(luò)變化 | android.net.conn.CONNECTIVITY_CHANGE |
| 關(guān)閉或打開飛行模式 | Intent.ACTION_AIRPLANE_MODE_CHANGED |
| 充電時或電量發(fā)生變化 | Intent.ACTION_BATTERY_CHANGED |
| 電池電量低 | Intent.ACTION_BATTERY_LOW |
| 電池電量充足(即從電量低變化到飽滿時會發(fā)出廣播 | Intent.ACTION_BATTERY_OKAY |
| 系統(tǒng)啟動完成后(僅廣播一次) | Intent.ACTION_BOOT_COMPLETED |
| 按下照相時的拍照按鍵(硬件按鍵)時 | Intent.ACTION_CAMERA_BUTTON |
| 屏幕鎖屏 | Intent.ACTION_CLOSE_SYSTEM_DIALOGS |
| 設(shè)備當(dāng)前設(shè)置被改變時(界面語言、設(shè)備方向等) | Intent.ACTION_CONFIGURATION_CHANGED |
| 插入耳機(jī)時 | Intent.ACTION_HEADSET_PLUG |
| 未正確移除SD卡但已取出來時(正確移除方法:設(shè)置–SD卡和設(shè)備內(nèi)存–卸載SD卡) | Intent.ACTION_MEDIA_BAD_REMOVAL |
| 插入外部儲存裝置(如SD卡) | Intent.ACTION_MEDIA_CHECKING |
| 成功安裝APK | Intent.ACTION_PACKAGE_ADDED |
| 成功刪除APK | Intent.ACTION_PACKAGE_REMOVED |
| 重啟設(shè)備 | Intent.ACTION_REBOOT |
| 屏幕被關(guān)閉 | Intent.ACTION_SCREEN_OFF |
| 屏幕被打開 | Intent.ACTION_SCREEN_ON |
| 關(guān)閉系統(tǒng)時 | Intent.ACTION_SHUTDOWN |
| 重啟設(shè)備 | Intent.ACTION_REBOOT |
關(guān)于廣播就寫這么多先啦。
謝謝閱讀。
總結(jié)
以上是生活随笔為你收集整理的Android四大组件之广播接收器BroadcastReceiver的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最新百度文库下载软件,还能下载源文件!
- 下一篇: android 人脸识别demo,And