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