Android 應用程式可透過 Android 系統傳送或接收廣播訊息, 和其他 Android 應用程式一樣 發布-訂閱 設計模式發生特定事件時,系統就會傳送這些廣播訊息。 舉例來說,Android 系統會在各種系統事件時傳送廣播訊息 ,例如系統啟動或裝置開始充電時。應用程式 也可以傳送自訂廣播訊息,例如 他們可能感興趣的事物 (例如 下載完成)。
系統會最佳化廣播的傳遞作業, 最佳系統健康狀態因此,聯播網的發送時間 保證。需要低延遲處理序間通訊的應用程式,應該 請考慮使用「繫結服務」。
應用程式可以註冊,接收特定廣播訊息。傳送廣播訊息時 系統會自動將廣播訊息路由至 接收特定類型的廣播訊息。
一般來說,廣播訊息可做為跨應用程式傳訊系統。 以及正常使用者流程之外的平台但是,您必須小心不要濫用 回應廣播訊息以及在背景執行工作 也可能導致系統效能緩慢
關於系統廣播訊息
當各種系統事件發生時,系統會自動傳送廣播訊息。 例如系統切換及退出飛航模式的時間系統 廣播訊息會傳送至所有訂閱 活動。
廣播訊息本身會包裝在 Intent
中
物件,其動作字串會識別已發生的事件 (例如
android.intent.action.AIRPLANE_MODE
)。意圖還包括
補充資訊。例如:飛機
模式意圖包含額外布林值,用於指出是否飛機
模式已開啟。
如要進一步瞭解如何讀取意圖,以及如何從 請參閱意圖和意圖 篩選器。
如需完整的系統廣播動作清單,請參閱
Android SDK 中的 BROADCAST_ACTIONS.TXT
檔案。每個廣播動作都有
常數欄位。例如
ACTION_AIRPLANE_MODE_CHANGED
是
android.intent.action.AIRPLANE_MODE
。各廣播動作的說明文件
即為相關常數欄位。
系統廣播訊息變更
隨著 Android 平台不斷演進,它會定期變更系統廣播的方式 運作。請注意,以下變更將支援所有 Android 版本。
Android 14
應用程式在快取儲存時
狀態,廣播放送作業
且專為系統健康狀態最佳化舉例來說,較不重要的系統廣播訊息,
因為 ACTION_SCREEN_ON
是
在應用程式處於快取狀態時延後。應用程式從快取載入後
將狀態轉換成主動程序
生命週期時,系統會提供
任何延遲廣播訊息
資訊清單暫時從快取中移除應用程式 提交狀態
Android 9
從 Android 9 (API 級別 28) 開始,
NETWORK_STATE_CHANGED_ACTION
敬上
廣播不會接收使用者的所在位置或個人識別資訊
識別資料
此外,如果應用程式安裝在搭載 Android 9 以上版本的裝置上
透過 Wi-Fi 連線的系統廣播不包含 SSID、BSSID 和連線
或掃描結果如要取得這項資訊,請呼叫
getConnectionInfo()
敬上
。
Android 8.0
從 Android 8.0 (API 級別 26) 開始,系統會建議 資訊清單宣告接收器的相關限制。
如果應用程式指定 Android 8.0 以上版本,您就無法使用資訊清單 為大部分隱含廣播 (未指定的廣播訊息) 宣告接收器 您的應用程式)。您仍然可以使用 使用情境註冊的接收器 使用者的主動使用應用程式的次數。
Android 7.0
Android 7.0 (API 級別 24) 以上版本不會傳送下列系統 廣播:
此外,指定 Android 7.0 以上版本的應用程式也必須註冊 CONNECTIVITY_ACTION
廣播。
使用 registerReceiver(BroadcastReceiver, IntentFilter)
。
在資訊清單中宣告接收器無法運作。
接收廣播訊息
應用程式可透過兩種方式接收廣播訊息:透過資訊清單宣告的接收器 和已註冊使用情境的接收端
資訊清單宣告的接收器
如果您在資訊清單中宣告廣播接收器,系統會啟動 應用程式 (如果應用程式尚未執行的話)。
如要在資訊清單中宣告廣播接收器,請按照下列步驟操作:
指定
<receiver>
元素。<!-- If this receiver listens for broadcasts sent from the system or from other apps, even other apps that you own, set android:exported to "true". --> <receiver android:name=".MyBroadcastReceiver" android:exported="false"> <intent-filter> <action android:name="APP_SPECIFIC_BROADCAST" /> </intent-filter> </receiver>
意圖篩選器會指定接收器訂閱的廣播動作。
子類別
BroadcastReceiver
並實作onReceive(Context, Intent)
。 廣播接收器 :Kotlin
private const val TAG = "MyBroadcastReceiver" class MyBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { StringBuilder().apply { append("Action: ${intent.action}\n") append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n") toString().also { log -> Log.d(TAG, log) val binding = ActivityNameBinding.inflate(layoutInflater) val view = binding.root setContentView(view) Snackbar.make(view, log, Snackbar.LENGTH_LONG).show() } } } }
Java
public class MyBroadcastReceiver extends BroadcastReceiver { private static final String TAG = "MyBroadcastReceiver"; @Override public void onReceive(Context context, Intent intent) { StringBuilder sb = new StringBuilder(); sb.append("Action: " + intent.getAction() + "\n"); sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n"); String log = sb.toString(); Log.d(TAG, log); ActivityNameBinding binding = ActivityNameBinding.inflate(layoutInflater); val view = binding.root; setContentView(view); Snackbar.make(view, log, Snackbar.LENGTH_LONG).show(); } }
如要啟用檢視區塊繫結 在模組層級設定 viewBinding build.gradle 檔案。
系統套件管理員會在應用程式安裝時註冊接收器。 接收端會成為應用程式的獨立進入點, 系統可在非應用程式的情況下啟動應用程式,並放送廣播訊息 目前運作中的 Pod
系統會建立新的 BroadcastReceiver
元件
物件來處理收到的每則廣播訊息。這個物件只能用於
等待呼叫 onReceive(Context, Intent)
。一旦您的程式碼
從這個方法傳回後,系統就會認為該元件不再
有效。
已註冊使用情境的接收器
已註冊使用情境的接收器只要完成註冊,就能接收廣播訊息
。舉例來說,如果您在
Activity
只要活動沒有刪除,您就會收到廣播。如果發生以下情況:
使用「應用程式」結構定義來註冊,只要應用程式就會發送廣播訊息
正在運作。
如要依據背景資訊註冊接收器,請執行下列步驟:
在應用程式模組層級建構檔案中,納入 1.9.0 以上版本 AndroidX Core Library:
Groovy
dependencies { def core_version = "1.13.1" // Java language implementation implementation "androidx.core:core:$core_version" // Kotlin implementation "androidx.core:core-ktx:$core_version" // To use RoleManagerCompat implementation "androidx.core:core-role:1.0.0" // To use the Animator APIs implementation "androidx.core:core-animation:1.0.0" // To test the Animator APIs androidTestImplementation "androidx.core:core-animation-testing:1.0.0" // Optional - To enable APIs that query the performance characteristics of GMS devices. implementation "androidx.core:core-performance:1.0.0" // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google implementation "androidx.core:core-google-shortcuts:1.1.0" // Optional - to support backwards compatibility of RemoteViews implementation "androidx.core:core-remoteviews:1.1.0" // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12 implementation "androidx.core:core-splashscreen:1.2.0-alpha01" }
Kotlin
dependencies { val core_version = "1.13.1" // Java language implementation implementation("androidx.core:core:$core_version") // Kotlin implementation("androidx.core:core-ktx:$core_version") // To use RoleManagerCompat implementation("androidx.core:core-role:1.0.0") // To use the Animator APIs implementation("androidx.core:core-animation:1.0.0") // To test the Animator APIs androidTestImplementation("androidx.core:core-animation-testing:1.0.0") // Optional - To enable APIs that query the performance characteristics of GMS devices. implementation("androidx.core:core-performance:1.0.0") // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google implementation("androidx.core:core-google-shortcuts:1.1.0") // Optional - to support backwards compatibility of RemoteViews implementation("androidx.core:core-remoteviews:1.1.0") // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12 implementation("androidx.core:core-splashscreen:1.2.0-alpha01") }
建立以下項目的執行個體:
BroadcastReceiver
:Kotlin
val br: BroadcastReceiver = MyBroadcastReceiver()
Java
BroadcastReceiver br = new MyBroadcastReceiver();
建立以下項目的執行個體:
IntentFilter
:Kotlin
val filter = IntentFilter(APP_SPECIFIC_BROADCAST)
Java
IntentFilter filter = new IntentFilter(APP_SPECIFIC_BROADCAST);
選擇是否應將廣播接收器匯出且瀏覽權限如下 裝置上的其他應用程式。如果這個接收器正在監聽已傳送的廣播訊息 從您的系統或其他應用程式 (甚至是您擁有的其他應用程式) 中,使用
RECEIVER_EXPORTED
標記。反之,如果這個接收器只會監聽 透過應用程式傳送的廣播訊息,請使用RECEIVER_NOT_EXPORTED
標記。Kotlin
val listenToBroadcastsFromOtherApps = false val receiverFlags = if (listenToBroadcastsFromOtherApps) { ContextCompat.RECEIVER_EXPORTED } else { ContextCompat.RECEIVER_NOT_EXPORTED }
Java
boolean listenToBroadcastsFromOtherApps = false; if (listenToBroadcastsFromOtherApps) { receiverFlags = ContextCompat.RECEIVER_EXPORTED; } else { receiverFlags = ContextCompat.RECEIVER_NOT_EXPORTED; }
如要註冊接收器,請呼叫
registerReceiver()
:Kotlin
ContextCompat.registerReceiver(context, br, filter, receiverFlags)
Java
ContextCompat.registerReceiver(context, br, filter, receiverFlags);
如要停止接收廣播訊息,請呼叫
unregisterReceiver(android.content.BroadcastReceiver)
。 不再需要接收者時,請務必取消註冊,或是 相關資訊已失效請留意您在何處註冊及取消註冊接收方 舉例來說,如果您使用活動的內容在
onCreate(Bundle)
中註冊接收器, 應在onDestroy()
中取消註冊 避免接收器洩漏出活動內容註冊 「onResume()
」中的接收器,您應 請在「onPause()
」中取消註冊 多次註冊 (如果不希望收到廣播訊息) 進而減少不必要的系統負擔。禁止事項 取消註冊「onSaveInstanceState(Bundle)
」, 因為使用者返回記錄堆疊時,系統不會呼叫此方法。
對程序狀態的影響
是否為BroadcastReceiver
是否影響其包含的程序,因此可以改變
系統終止可能性前景程序會執行接收器的 onReceive()
方法。
系統會執行此程序,但在極度記憶體壓力之下除外。
BroadcastReceiver 會在 onReceive()
後停用。接收端的主機
程序的重要性取決於應用程式元件如果只有該程序主機
資訊清單宣告的接收器 (使用者從未安裝應用程式經常發生)
或最近沒有互動),系統可能會在 onReceive()
後終止運作,
其他關鍵程序可用的資源
因此,廣播接收器不應啟動長時間執行的背景執行緒。
系統可以在 onReceive()
後隨時停止程序來收回
終止已建立的執行緒。如要讓程序保持運作,請排定
JobService
使用 JobScheduler
從接收器接收
讓系統知道程序仍在執行中。
背景工作總覽提供更多詳細資料。
正在傳送廣播訊息
Android 為應用程式提供三種傳送廣播的方式:
sendOrderedBroadcast(Intent, String)
方法一次會向一個接收器傳送廣播訊息。每個接收器 可以將結果傳播至下一個接收器 完全取消播送,不會傳遞至其他廣播 接收器。執行的順序接收者可以使用 相符意圖篩選器的 android:Priority 屬性;含有 優先順序將按任意順序執行sendBroadcast(Intent)
方法會傳送 會以未定義的順序向所有接收器廣播訊息。這稱為「正常」 廣播。效率會更高,但接收端無法讀取 接收來自其他接收器的結果、傳播從廣播訊息接收到的資料,或 取消廣播。
下列程式碼片段示範如何建立廣播訊息,以傳送廣播訊息
意圖並呼叫 sendBroadcast(Intent)
。
Kotlin
Intent().also { intent -> intent.setAction("com.example.broadcast.MY_NOTIFICATION") intent.putExtra("data", "Nothing to see here, move along.") sendBroadcast(intent) }
Java
Intent intent = new Intent(); intent.setAction("com.example.broadcast.MY_NOTIFICATION"); intent.putExtra("data", "Nothing to see here, move along."); sendBroadcast(intent);
廣播訊息會包裝在 Intent
物件中。
意圖的動作字串必須提供應用程式的 Java 套件名稱語法,
可明確識別廣播活動。您可以附加其他資訊
透過 putExtra(String, Bundle)
傳送至意圖。
你也可以:
在意圖上呼叫 setPackage(String)
。
限制具有權限的廣播訊息
取得權限可讓你限制廣播訊息,只針對處於保留狀態的應用程式 對特定權限的存取權您可以對寄件者強制執行限制,或 廣播接收器。
正在傳送並授予相關權限
呼叫 sendBroadcast(Intent, String)
或
sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
,您可以指定
權限參數。僅接收提出要求者
Kotlin
sendBroadcast(Intent(BluetoothDevice.ACTION_FOUND), Manifest.permission.BLUETOOTH_CONNECT)
Java
sendBroadcast(new Intent(BluetoothDevice.ACTION_FOUND), Manifest.permission.BLUETOOTH_CONNECT)
如要接收廣播訊息,接收端應用程式必須透過以下方式要求權限: 如下所示:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
您可以指定現有的系統權限,例如
BLUETOOTH_CONNECT
也可以定義自訂權限
<permission>
元素。適用對象
有關權限和安全性的一般資訊,請參閱「系統
權限。
正在根據權限接收
如果您在註冊廣播接收器時指定權限參數
(透過 registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
或在
<receiver>
標記
清單),則只有向電視台提出權限要求的電視台
<uses-permission>
標記
並授予相關權限 (如果應用程式已取得相關權限,
危險) 要求傳送意圖給接收器。
舉例來說,假設您接收的應用程式具有資訊清單宣告的接收器: 如下所示:
<receiver android:name=".MyBroadcastReceiver"
android:permission="android.permission.BLUETOOTH_CONNECT">
<intent-filter>
<action android:name="android.intent.action.ACTION_FOUND"/>
</intent-filter>
</receiver>
或者,接收端應用程式含有已註冊使用情境的接收器,如下所示:
Kotlin
var filter = IntentFilter(Intent.ACTION_FOUND) registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null )
Java
IntentFilter filter = new IntentFilter(Intent.ACTION_FOUND); registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null );
接著,傳送應用程式必須符合下列條件,才能傳送廣播訊息給這些接收器。 要求權限,如下所示:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
安全性考量和最佳做法
以下是與郵件傳送及通訊相關的安全性注意事項和最佳做法 接收廣播:
如果多個應用程式已註冊接收相同的廣播訊息 可能會使系統啟動大量應用程式 對裝置效能和使用者體驗造成重大影響。為了避免 因此建議使用情境註冊,而非資訊清單宣告。 有時 Android 系統本身會強制使用已註冊的情境 接收器。舉例來說,系統會放送
CONNECTIVITY_ACTION
廣播訊息 只會提供給已註冊使用情境的接收器請勿使用隱含意圖播送機密資訊。 任何註冊接收廣播的應用程式都能讀取資訊。 你可以透過下列三種方式控管哪些人可以接收廣播訊息:
- 您可以在傳送廣播時指定權限。
- 在 Android 4.0 以上版本中,您可以指定
套件搭配
傳送以下值時
setPackage(String)
廣播。系統會運用一組應用程式將廣播限制在 與套件配對
註冊接收器後,任何應用程式都能傳送潛在的惡意內容 並廣播至應用程式的接收器有幾種方法可以限制 廣播訊息:
- 您可以在註冊廣播接收器時指定權限。
- 對於資訊清單宣告的接收器,您可以設定 android:exported 屬性設為「false」。接收者未收到 來自應用程式外部來源的廣播訊息。
廣播動作的命名空間是全域性質。請確保動作名稱 和其他字串都是編寫於您擁有的命名空間中 避免與其他應用程式衝突
因為接收器的
onReceive(Context, Intent)
方法會在以下位置執行: 主執行緒後,它應該會快速執行並傳回。如果需要 執行長時間執行的工作,注意產生執行緒或開始執行 因為系統會在 會傳回onReceive()
。詳情請參閱「對程序的影響 狀態:為了執行長時間執行的工作 建議:- 系統將在以下位置呼叫
goAsync()
: 接收器的onReceive()
方法,並將BroadcastReceiver.PendingResult
傳遞至背景執行緒。 這樣一來,從onReceive()
傳回後,廣播訊息會保持啟用狀態。 然而,即使採用這種做法,系統仍希望您 播送速度非常快 (不到 10 秒)。可讓你 執行作業,避免主執行緒發生故障。 - 使用
JobScheduler
安排工作排程。如要 相關資訊,請參閱情報工作 排定時間。
- 系統將在以下位置呼叫
基於使用者體驗,請勿從廣播接收器啟動活動 很刺耳;尤其是在有多個接收器時。相反地 顯示通知。