日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android四大组件之广播接收器BroadcastReceiver

發(fā)布時間:2024/1/1 Android 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android四大组件之广播接收器BroadcastReceiver 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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()方法

public class MyBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// 廣播接收器接收到相應(yīng)廣播后,會自動回調(diào) onReceive() 方法// 一般情況下,onReceive方法會涉及與其他組件之間的交互,如發(fā)送Notification、啟動Service等// 默認(rèn)情況下,廣播接收器運(yùn)行在UI線程,因此,onReceive()方法不能執(zhí)行耗時操作,否則將導(dǎo)致ANR// TODO 實(shí)現(xiàn)與其他組件之間的交互,如發(fā)送Notification、啟動Service等} }

注意: 默認(rèn)情況下,廣播接收器運(yùn)行在UI線程,因此,onReceive()方法不能執(zhí)行耗時操作,否則將導(dǎo)致ANR。

廣播接收者注冊

類型注冊方式特點(diǎn)應(yīng)用場景
靜態(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)存泄露。

public class MainActivity extends AppCompatActivity {private MyBroadcastReceiver myBroadcastReceiver;@Overrideprotected void onResume() {super.onResume();// 1. 實(shí)例化BroadcastReceiver子類和IntentFiltermyBroadcastReceiver = new MyBroadcastReceiver();IntentFilter intentFilter = new IntentFilter();// 2. 設(shè)置接收廣播的類型intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");// 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);} }

廣播的類型

類型說明
普通廣播(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:

public class MyBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// 廣播接收器接收到相應(yīng)廣播后,會自動回調(diào) onReceive() 方法// 一般情況下,onReceive方法會涉及與其他組件之間的交互,如發(fā)送Notification、啟動Service等// 默認(rèn)情況下,廣播接收器運(yùn)行在UI線程,因此,onReceive()方法不能執(zhí)行耗時操作,否則將導(dǎo)致ANR// TODO 實(shí)現(xiàn)與其他組件之間的交互,如發(fā)送Notification、啟動Service等Toast.makeText(context,intent.getStringExtra("name"),Toast.LENGTH_LONG).show();} }

注冊、注銷和發(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ā)送方式不同:

sendOrderedBroadcast(intent);

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í)例。示例如下:

public class MainActivity extends AppCompatActivity {private MyBroadcastReceiver myBroadcastReceiver;private LocalBroadcastManager localBroadcastManager;@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ā)送廣播localBroadcastManager.sendBroadcast(intent);}});}// 注冊@Overrideprotected void onResume() {super.onResume();// 1. 實(shí)例化BroadcastReceiver子類和IntentFiltermyBroadcastReceiver = new MyBroadcastReceiver();IntentFilter intentFilter = new IntentFilter();// 實(shí)例化LocalBroadcastManager的實(shí)例localBroadcastManager = LocalBroadcastManager.getInstance(this);// 2. 設(shè)置接收廣播的類型,自定義一個廣播intentFilter.addAction("com.haha.haha.this.is.my.broadcast");// 3. 調(diào)用LocalBroadcastManager單一實(shí)例的registerReceiver()方法進(jìn)行動態(tài)注冊localBroadcastManager.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()方法中的廣播//取消注冊應(yīng)用內(nèi)廣播接收器localBroadcastManager.unregisterReceiver(myBroadcastReceiver);} }

系統(tǒng)廣播示例

這個我們也是很常用的。
Android系統(tǒng)廣播action如下:

系統(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
成功安裝APKIntent.ACTION_PACKAGE_ADDED
成功刪除APKIntent.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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。