前略: BroadcastReceiver の概要とポイントをまとめた
開発チーム内での共通認識レベルとして必要かなと思われる概要とポイントをまとめました。図とかあったらよいかと思ったんですが、そこまでできていないです。文字だけです。そして、基本は公式サイトを抜粋・文言変更して作ってます。
ブロードキャスト(ブロードキャストメッセージ)とは
BroadcastReceiver を調べると、用語としてブロードキャスト(またはブロードキャストメッセージ)というのが出てきますので、念の為それも整理します。
そもそもブロードキャストとは?調べてみると、
「コンピューター-ネットワークで、接続されているすべての端末に対し相手を特定せずにデータを送ること。」
というようなことが書いてあります。
なので、 ブロードキャストメッセージとは
「コンピューター-ネットワークで、接続されているすべての端末に対し相手を特定せずに送られるデータのこと。」
と言えそうです。これらを念頭に置くと、以下がわかりやすくなるかもしれません。
BroadcastReceiver is
Android は OS やアプリから、なんらかのイベントが発生したことをシステム全体に対して送受信することができます。まず、これが Android におけるブロードキャストです。
たとえば、端末の起動、デバイスの充電の開始など、さまざまなシステムイベントが発生したときに、OSがイベント発生をブロードキャストします。
また、アプリから独自のブロードキャストを送信することもでき、この場合はアプリ間のイベント通知として使用されたりするのが一般的です。
Androidでは、そういったOSやアプリから送信されるブロードキャストを受信するためのコンポーネントとして、 BroadcastReceiver というものを用意しています。
アプリは BroadcastReceiver を使って、特定のブロードキャストを受信するように登録することで、そのブロードキャストをシステムから受信できる仕組みになっています。
ブロードキャストメッセージの実態は intent を使うようになっており、ブロードキャストをアプリが受信すると、受信した BroadcastReceiver の onReceive が動き、引数の intent にその中にイベント発生を表すアクション文字列が入ってくるようになっています。たとえば、機内モードに切り替えたときであれば android.intent.action.AIRPLANE_MODE という文字列がアクションとして intent に入っています。
電源ONや機内モード切り替えなどのシステムのイベント発生によるブロードキャストをシステムブロードキャストといいます。システムブロードキャストのアクション一覧は BROADCAST_ACTIONS.TXT に記載されています。(ググれば出てきます。)
システムブロードキャストの動作変更
Android OSのバージョンアップに応じて、システムブロードキャストの動作についても定期的に変更されています。特に、OSのバージョンが挙がっていくにあたって、ブロードキャストに対する制約が増えていく傾向にありますので実装観点でも注意が必要です。
- Android 9(API レベル 28)以降
NETWORK_STATE_CHANGED_ACTION のブロードキャストはユーザーの位置情報や個人を特定できるデータを受信しなくなっている。Android 9 以降のデバイスは、Wi-Fi からのシステム ブロードキャストに SSID、BSSID、接続情報、スキャン結果は含まれない。- - Android 8.0(API レベル 26)以降
システムはマニフェストで宣言されたレシーバーに対して追加の制限を課します。アプリのtargetSdkVersionが Android 8.0 以降である場合は、マニフェストを使用して、ほとんどの暗黙的なブロードキャスト(アプリを具体的に指定しないブロードキャスト)のレシーバーを宣言することはできない。ユーザーがアプリをアクティブに使用している場合でも、コンテキスト登録されたレシーバーを使用できます。- - Android 7.0(API レベル 24)
Android 7.0以降では、次のシステムブロードキャストは送信されません。ACTION_NEW_PICTUREACTION_NEW_VIDEO また、 targetSdkVersion がAndroid 7.0 以降のアプリでは、マニフェストで CONNECTIVITY_ACTION の BroadcastReceiver を宣言することができません。
ブロードキャストの受信
アプリは、マニフェストで宣言されたレシーバーとコンテキスト登録されたレシーバーによる、2 つの方法でブロードキャストを受信できます。
ブロードキャストの送信
Android では、アプリがブロードキャストを送信する 3 つの方法が用意されていて、メジャーな2つを紹介します。参考。
- sendBroadcast(Intent) メソッドは、すべてのレシーバーにブロードキャストを送信しますが、順序は定義されません。これは、ノーマルブロードキャストと呼ばれます。これはより効率的ですが、レシーバーが他のレシーバーから結果を読み取ることはできません。また、ブロードキャストから受信したデータの伝達や、ブロードキャストの破棄もできません。
- LocalBroadcastManager.sendBroadcast メソッドは、送信側と同じアプリ内にあるレシーバーにブロードキャストを送信します。アプリ間でブロードキャストを送信する必要がない場合は、プロセス間の通信が不要で効率的な実装を行えます。ブロードキャストを他のアプリが送受信できることから生じるセキュリティの問題を考慮する必要もありません。
利用時の注意点
onReceive メソッドはメインスレッドで実行されるため、迅速に処理を終わらせないとUIUXに大きな影響がでる可能性があります。そういった理由もあり、処理に10秒以上かかるとANRも発生する仕様になっています。また、長めの処理を行う場合は goAsync() メソッドを使ってバックグラウンド処理に移行し、処理完了時に goAsync を使って取得した PendingResult を終了させます(参考)。
頻繁にブロードキャストに応答して、バックグラウンドでジョブを実行しすぎると、システムパフォーマンスの低下につながる可能性があるので注意が必要です。