Android 零基礎(chǔ)到精通之廣播機制
廣播機制簡介
Android 中的廣播主要分為兩種類型:
- 標(biāo)準(zhǔn)廣播:一種異步執(zhí)行的廣播,廣播發(fā)出后,所有的 BroadcasterReceiver 幾乎會在同一時刻受到這條廣播消息,沒有任何時間順序
- 有序廣播:一種同步執(zhí)行的廣播,廣播發(fā)出后,同一時刻只有一個 BroadcasterReceiver 能夠接受這條廣播消息,當(dāng)該 BroadcasterReceiver 中的邏輯執(zhí)行完畢后,廣播才會繼續(xù)傳遞
接收系統(tǒng)廣播
Android 內(nèi)置了很多系統(tǒng)級別的廣播,我們可以在應(yīng)用程序中通過監(jiān)聽這些廣播來得到各種系統(tǒng)的狀態(tài)信息
1. 動態(tài)注冊監(jiān)聽時間變化
新建一個類,繼承自 BroadcasterReceiver,并重寫父類的 onReceive() 方法,這樣當(dāng)有廣播來時,onReceive() 方法就會得到執(zhí)行
class MainActivity : AppCompatActivity() { lateinit var timeChangeReceiver: TimeChangeReceiver override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val intentFilter = IntentFilter() intentFilter.addAction("android.intent.action.TIME_TICK") timeChangeReceiver = TimeChangeReceiver() registerReceiver(timeChangeReceiver, intentFilter) } inner class TimeChangeReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { Toast.makeText(context, "Time has changed", Toast.LENGTH_SHORT).show() } } }
- 定義了一個內(nèi)部類 TimeChangeReceiver,繼承自 BroadcasterReceiver 并重寫父類的方法,這樣每當(dāng)系統(tǒng)時間發(fā)生變化時,就會使用 Toast 提示一段文本信息
- 在 onCreate() 方法創(chuàng)建一個 IntentFilter 實例,添加值為 android.intent.action.TIME_TICK 的 action,這也是系統(tǒng)時間發(fā)生變化時,系統(tǒng)會發(fā)出的廣播的值
- 創(chuàng)建 TimeChangeReceiver 實例,然后調(diào)用 registerReceiver() 方法進行注冊,將 IntentFilter 實例和 TimeChangeReceiver 實例傳進去,完成監(jiān)聽功能
2. 靜態(tài)注冊實現(xiàn)開機啟動
動態(tài)注冊的 BroadcasterReceiver 相對靈活,但必須在程序啟動后才能接收廣播,要想讓程序在未啟動的情況下也能接收廣播,就需要使用靜態(tài)注冊的方式
創(chuàng)建類 BootCompleteReceiver,Exported 屬性表示是否允許這個 BroadcasterReceiver 接收本程序以外的廣播,Enabled 屬性表示是否啟用這個 BroadcasterReceiver,勾選這兩個屬性,點擊 Finish 完成創(chuàng)建
class BootCompleteReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show() } }
靜態(tài)的 BroadcasterReceiver 要在 AndroidManifest.xml 文件中注冊才可以使用。由于 Android 系統(tǒng)啟動完成后會發(fā)出一條值為 android.intent.action.BOOT_COMPLETED 的廣播,所以我們在 <receiver> 標(biāo)簽中添加一個 <intent-filter> 標(biāo)簽,并在里面聲明相應(yīng)的 action。另外,還必須在 AndroidManifest.xml 中進行權(quán)限聲明。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.fragmenttest"> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.FragmentTest"> ... <receiver android:name="com.example.broadcasttest.BootCompleteReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> </application> </manifest>
發(fā)送自定義廣播
1. 發(fā)送標(biāo)準(zhǔn)廣播
新建一個 MyBroadcasterReceiver,并在 onReceive() 方法中加入如下代碼:
class MyBroadcasterReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Toast.makeText(context, "received in MyBroadcasterReceiver", Toast.LENGTH_SHORT).show() } }
然后在 AndroidManifest.xml 中對這個 BroadcasterReceiver 進行修改
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.fragmenttest"> ... <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.FragmentTest"> ... <receiver android:name="com.example.broadcasttest.MyBroadcasterReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.example.broadcasttest.MyBroadcasterReceiver" /> </intent-filter> </receiver> </application> </manifest>
接下來修改 activity_main.xml,定義一個按鈕,作為發(fā)送廣播的觸發(fā)點
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Send Broadcast" /> </LinearLayout>
修改 MainActivity 中的代碼
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) button.setOnClickListener { val intent = Intent("com.example.broadcasttest.MyBroadcasterReceiver") intent.setPackage(packageName) sendBroadcast(intent) } } }
這里對 setPackage() 方法做個說明,靜態(tài)注冊的 BroadcasterReceiver 是無法接收隱式廣播的,而默認(rèn)情況下我們發(fā)出的自定義廣播都是隱式廣播,因此這里要調(diào)用 setPackage() 方法,指定這條廣播是發(fā)送給哪個應(yīng)用程序的,從而讓它變成一條顯式廣播
2. 發(fā)送有序廣播
有序廣播是一種同步執(zhí)行的廣播,并且可以被截斷,我們再新建 AnotherBroadcasterReceiver
class AnotherBroadcasterReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Toast.makeText(context, "received in AnotherBroadcasterReceiver", Toast.LENGTH_SHORT).show() } }
然后在 AndroidManifest.xml 中進行修改
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.fragmenttest"> ... <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.FragmentTest"> ... <receiver android:name="com.example.broadcasttest.AnotherBroadcasterReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.example.broadcasttest.MyBroadcasterReceiver" /> </intent-filter> </receiver> ... </application> </manifest>
到目前為止,程序發(fā)出的都是標(biāo)準(zhǔn)廣播,要發(fā)送有序廣播,就要重新回到 BroadcasterTest 項目,然后修改 MainActivity 中的代碼
class MainActivity : AppCompatActivity() { ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) button.setOnClickListener { val intent = Intent("com.example.broadcasttest.MyBroadcasterReceiver") intent.setPackage(packageName) sendOrderedBroadcast(intent, null) } ... } }
sendOrderedBroadcast() 方法接收兩個參數(shù):第一個參數(shù)仍然是 Intent;第二個參數(shù)是一個與權(quán)限相關(guān)的字符串,這里傳入 null 即可
接下來設(shè)定 BroadcasterReceiver 的先后順序,修改 AndroidManifest.xml 中的代碼
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.fragmenttest"> ... <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.FragmentTest"> <receiver android:name="com.example.broadcasttest.MyBroadcasterReceiver" android:enabled="true" android:exported="true"> <intent-filter android:priority="100"> <action android:name="com.example.broadcasttest.MyBroadcasterReceiver" /> </intent-filter> </receiver> ... </application> </manifest>
通過 android:priority 屬性給 BroadcasterReceiver 設(shè)置優(yōu)先級,優(yōu)先級比較高的 BroadcasterReceiver 就可以先收到廣播。既然 MyBroadcasterReceiver 獲得了接收廣播的優(yōu)先級,那么 MyBroadcasterReceiver 就可以選擇是否允許廣播繼續(xù)傳遞了
class MyBroadcasterReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Toast.makeText(context, "received in MyBroadcasterReceiver", Toast.LENGTH_SHORT).show() abortBroadcast() } }
在 onReceive() 方法中調(diào)用 abortBroadcaster() 方法,就表示將這條廣播截斷,后面的 BroadcasterReceiver 將無法再接收這條廣播
到此這篇關(guān)于Android 零基礎(chǔ)到精通之廣播機制的文章就介紹到這了,更多相關(guān)Android 廣播機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android編程創(chuàng)建桌面快捷方式的常用方法小結(jié)【2種方法】
這篇文章主要介紹了Android編程創(chuàng)建桌面快捷方式的常用方法,結(jié)合實例形式總結(jié)分析了2種常見的實現(xiàn)方法與相關(guān)操作技巧,需要的朋友可以參考下2017-02-02mui.init()與mui.plusReady()區(qū)別和關(guān)系
給大家分享一下在使用MUI進行APP開發(fā)的時候,mui.init()與mui.plusReady()區(qū)別以及使用上不同之處。2017-11-11Android onbackpressed實現(xiàn)返回鍵的攔截和彈窗流程分析
很多網(wǎng)友不明白如何在Android平臺上捕獲Back鍵的事件,Back鍵是手機上的后退鍵,一般的軟件不捕獲相關(guān)信息可能導(dǎo)致你的程序被切換到后臺,而回到桌面的尷尬情況,在Android上有兩種方法來獲取該按鈕的事件2023-01-01Flutter學(xué)習(xí)之實現(xiàn)自定義themes詳解
一般情況下我們在flutter中搭建的app基本上都是用的是MaterialApp這種設(shè)計模式,MaterialApp中為我們接下來使用的按鈕,菜單等提供了統(tǒng)一的樣式,那么這種樣式能不能進行修改或者自定義呢?答案是肯定的,一起來看看吧2023-03-03