🐈
AndroidでBroadcastReceiverを使う際に引っかかった事
私が Android の BroadcastReceiver を使う際に引っかかった2つのポイントをまとめます。
結論
- レシーバーをコンテキストから登録する際にflagに
RECEIVER_NOT_EXPORTED
を指定する場合はsendBroadcastをする際にIntentにsetPackage
を指定しないと受け取れない - AndroidManifestからReceiverを登録する際はintent-filterを指定しないと受け取れない
1. コンテキストからレシーバーを登録(プログラムから登録)する際に引っかかった点
こんな感じで BroadcastReceiver を作成して登録したとします。
val serviceReceiver =
object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Handle the broadcast message here
println("onReceive")
if(intent.action == SampleService.ACTION_RESULT) {
val status = intent.getStringExtra(SampleService.PROCESS_STATUS)
println("Received broadcast: $status")
}
}
}
/// 省略
override fun onResume() {
super.onResume()
val filter = IntentFilter(SampleService.ACTION_RESULT)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(serviceReceiver, filter, RECEIVER_NOT_EXPORTED)
} else {
registerReceiver(serviceReceiver, filter)
}
}
// 渡すのユースケースではServiceの処理の結果を受け取るためにsendBroadcastを呼び出す
sendBroadcast(
Intent().apply {
action = ACTION_RESULT
putExtra(PROCESS_STATUS, "success")
}
)
そしてsendBroadcastで送信して受け取ろうとしたのですが、受け取れませんでした。
原因としてはsendBroadcastを送る際にsetPackageを呼び出していなかったことが原因でした。
sendBroadcast(
Intent().apply {
action = ACTION_RESULT
putExtra(PROCESS_STATUS, "test")
setPackage("com.example.hogehoge")
}
)
また、registerReceiver
を呼び出してレシーバーを登録する際の第3引数のフラグをRECEIVER_EXPORTED
を設定する事でも呼び出されるように修正する事もできる
おそらくこのあたりのドキュメントが関係していそう
2.AndroidManifestからレシーバーを登録する際に引っかかった点
intent-filterをAndroidManifestから登録する際に指定しないとsendBroadcastを呼び出そうとしてonReceiveが呼ばれませんでした。
これは私の思い込みなのですが、filterという名前的に別に指定しなくても動くと思い込んでいたので詰まってしまいました。
そのため以下のようにintent-filterを指定する必要がありました。
<receiver android:name=".MyReceiver" android:exported="false">
<intent-filter>
<action android:name="com.example.backgroundservicewithbroadcast.SampleService.RESULT" />
</intent-filter>
</receiver>
まとめ
思い込みはよくない
Discussion