Android 零基礎(chǔ)到精通之廣播機(jī)制
廣播機(jī)制簡(jiǎn)介
Android 中的廣播主要分為兩種類型:
- 標(biāo)準(zhǔn)廣播:一種異步執(zhí)行的廣播,廣播發(fā)出后,所有的 BroadcasterReceiver 幾乎會(huì)在同一時(shí)刻受到這條廣播消息,沒有任何時(shí)間順序
- 有序廣播:一種同步執(zhí)行的廣播,廣播發(fā)出后,同一時(shí)刻只有一個(gè) BroadcasterReceiver 能夠接受這條廣播消息,當(dāng)該 BroadcasterReceiver 中的邏輯執(zhí)行完畢后,廣播才會(huì)繼續(xù)傳遞
接收系統(tǒng)廣播
Android 內(nèi)置了很多系統(tǒng)級(jí)別的廣播,我們可以在應(yīng)用程序中通過監(jiān)聽這些廣播來得到各種系統(tǒng)的狀態(tài)信息
1. 動(dòng)態(tài)注冊(cè)監(jiān)聽時(shí)間變化
新建一個(gè)類,繼承自 BroadcasterReceiver,并重寫父類的 onReceive() 方法,這樣當(dāng)有廣播來時(shí),onReceive() 方法就會(huì)得到執(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()
}
}
}
- 定義了一個(gè)內(nèi)部類 TimeChangeReceiver,繼承自 BroadcasterReceiver 并重寫父類的方法,這樣每當(dāng)系統(tǒng)時(shí)間發(fā)生變化時(shí),就會(huì)使用 Toast 提示一段文本信息
- 在 onCreate() 方法創(chuàng)建一個(gè) IntentFilter 實(shí)例,添加值為 android.intent.action.TIME_TICK 的 action,這也是系統(tǒng)時(shí)間發(fā)生變化時(shí),系統(tǒng)會(huì)發(fā)出的廣播的值
- 創(chuàng)建 TimeChangeReceiver 實(shí)例,然后調(diào)用 registerReceiver() 方法進(jìn)行注冊(cè),將 IntentFilter 實(shí)例和 TimeChangeReceiver 實(shí)例傳進(jìn)去,完成監(jiān)聽功能
2. 靜態(tài)注冊(cè)實(shí)現(xiàn)開機(jī)啟動(dòng)
動(dòng)態(tài)注冊(cè)的 BroadcasterReceiver 相對(duì)靈活,但必須在程序啟動(dòng)后才能接收廣播,要想讓程序在未啟動(dòng)的情況下也能接收廣播,就需要使用靜態(tài)注冊(cè)的方式
創(chuàng)建類 BootCompleteReceiver,Exported 屬性表示是否允許這個(gè) BroadcasterReceiver 接收本程序以外的廣播,Enabled 屬性表示是否啟用這個(gè) BroadcasterReceiver,勾選這兩個(gè)屬性,點(diǎn)擊 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 文件中注冊(cè)才可以使用。由于 Android 系統(tǒng)啟動(dòng)完成后會(huì)發(fā)出一條值為 android.intent.action.BOOT_COMPLETED 的廣播,所以我們?cè)?<receiver> 標(biāo)簽中添加一個(gè) <intent-filter> 標(biāo)簽,并在里面聲明相應(yīng)的 action。另外,還必須在 AndroidManifest.xml 中進(jìn)行權(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)廣播
新建一個(gè) MyBroadcasterReceiver,并在 onReceive() 方法中加入如下代碼:
class MyBroadcasterReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context, "received in MyBroadcasterReceiver", Toast.LENGTH_SHORT).show()
}
}
然后在 AndroidManifest.xml 中對(duì)這個(gè) BroadcasterReceiver 進(jìn)行修改
<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,定義一個(gè)按鈕,作為發(fā)送廣播的觸發(fā)點(diǎn)
<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)
}
}
}
這里對(duì) setPackage() 方法做個(gè)說明,靜態(tài)注冊(cè)的 BroadcasterReceiver 是無法接收隱式廣播的,而默認(rèn)情況下我們發(fā)出的自定義廣播都是隱式廣播,因此這里要調(diào)用 setPackage() 方法,指定這條廣播是發(fā)送給哪個(gè)應(yīng)用程序的,從而讓它變成一條顯式廣播
2. 發(fā)送有序廣播
有序廣播是一種同步執(zhí)行的廣播,并且可以被截?cái)?,我們?cè)傩陆?AnotherBroadcasterReceiver
class AnotherBroadcasterReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context, "received in AnotherBroadcasterReceiver", Toast.LENGTH_SHORT).show()
}
}
然后在 AndroidManifest.xml 中進(jìn)行修改
<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 項(xiàng)目,然后修改 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() 方法接收兩個(gè)參數(shù):第一個(gè)參數(shù)仍然是 Intent;第二個(gè)參數(shù)是一個(gè)與權(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)先級(jí),優(yōu)先級(jí)比較高的 BroadcasterReceiver 就可以先收到廣播。既然 MyBroadcasterReceiver 獲得了接收廣播的優(yōu)先級(jí),那么 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() 方法,就表示將這條廣播截?cái)啵竺娴?BroadcasterReceiver 將無法再接收這條廣播
到此這篇關(guān)于Android 零基礎(chǔ)到精通之廣播機(jī)制的文章就介紹到這了,更多相關(guān)Android 廣播機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android編程創(chuàng)建桌面快捷方式的常用方法小結(jié)【2種方法】
這篇文章主要介紹了Android編程創(chuàng)建桌面快捷方式的常用方法,結(jié)合實(shí)例形式總結(jié)分析了2種常見的實(shí)現(xiàn)方法與相關(guān)操作技巧,需要的朋友可以參考下2017-02-02
Android中的Button自定義點(diǎn)擊效果實(shí)例代碼
Android中的Button自定義點(diǎn)擊效果實(shí)例代碼,需要的朋友可以參考一下2013-05-05
mui.init()與mui.plusReady()區(qū)別和關(guān)系
給大家分享一下在使用MUI進(jìn)行APP開發(fā)的時(shí)候,mui.init()與mui.plusReady()區(qū)別以及使用上不同之處。2017-11-11
Android onbackpressed實(shí)現(xiàn)返回鍵的攔截和彈窗流程分析
很多網(wǎng)友不明白如何在Android平臺(tái)上捕獲Back鍵的事件,Back鍵是手機(jī)上的后退鍵,一般的軟件不捕獲相關(guān)信息可能導(dǎo)致你的程序被切換到后臺(tái),而回到桌面的尷尬情況,在Android上有兩種方法來獲取該按鈕的事件2023-01-01
Flutter學(xué)習(xí)之實(shí)現(xiàn)自定義themes詳解
一般情況下我們?cè)趂lutter中搭建的app基本上都是用的是MaterialApp這種設(shè)計(jì)模式,MaterialApp中為我們接下來使用的按鈕,菜單等提供了統(tǒng)一的樣式,那么這種樣式能不能進(jìn)行修改或者自定義呢?答案是肯定的,一起來看看吧2023-03-03

