Android 零基礎到精通之廣播機制
廣播機制簡介
Android 中的廣播主要分為兩種類型:
- 標準廣播:一種異步執(zhí)行的廣播,廣播發(fā)出后,所有的 BroadcasterReceiver 幾乎會在同一時刻受到這條廣播消息,沒有任何時間順序
- 有序廣播:一種同步執(zhí)行的廣播,廣播發(fā)出后,同一時刻只有一個 BroadcasterReceiver 能夠接受這條廣播消息,當該 BroadcasterReceiver 中的邏輯執(zhí)行完畢后,廣播才會繼續(xù)傳遞
接收系統(tǒng)廣播
Android 內(nèi)置了很多系統(tǒng)級別的廣播,我們可以在應用程序中通過監(jiān)聽這些廣播來得到各種系統(tǒng)的狀態(tài)信息
1. 動態(tài)注冊監(jiān)聽時間變化
新建一個類,繼承自 BroadcasterReceiver,并重寫父類的 onReceive() 方法,這樣當有廣播來時,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 并重寫父類的方法,這樣每當系統(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> 標簽中添加一個 <intent-filter> 標簽,并在里面聲明相應的 action。另外,還必須在 AndroidManifest.xml 中進行權限聲明。
<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ā)送標準廣播
新建一個 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 是無法接收隱式廣播的,而默認情況下我們發(fā)出的自定義廣播都是隱式廣播,因此這里要調(diào)用 setPackage() 方法,指定這條廣播是發(fā)送給哪個應用程序的,從而讓它變成一條顯式廣播
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ā)出的都是標準廣播,要發(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ù)是一個與權限相關的字符串,這里傳入 null 即可
接下來設定 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 設置優(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 將無法再接收這條廣播
到此這篇關于Android 零基礎到精通之廣播機制的文章就介紹到這了,更多相關Android 廣播機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解決Android studio用真機調(diào)試時logcat一直輸出日志問題
這篇文章主要介紹了解決Android studio用真機調(diào)試時logcat一直輸出日志問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04
Android實現(xiàn)Flip翻轉(zhuǎn)動畫效果
這篇文章主要介紹了Android實現(xiàn)Flip翻轉(zhuǎn)動畫效果,對Android程序設計人員有很好的參考借鑒價值,需要的朋友可以參考下2014-08-08
Android自定義可點擊的ImageSpan并在TextView中內(nèi)置View
這篇文章主要為大家詳細介紹了Android自定義可點擊的ImageSpan并在TextView中內(nèi)置"View",具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11
android完美實現(xiàn) 拍照 選擇圖片 剪裁等代碼分享
本文給大家分享了2個安卓實現(xiàn)實現(xiàn) 拍照 選擇圖片 剪裁等的代碼,都是從正式項目中提取出來了,非常實用,有需要的小伙伴可以參考下。2016-01-01

