実現したいこと
動的に登録したBroadcastReceiverでNotificationに設定したIntentを受け取りたい
前提
最終的な目標として、Service内でループ処理を実行中にNotificationで進捗を表示して、キャンセルアクションをタップすることでループ処理を中止させることを考えています。
ですが今のところうまくいっておらず、原因の切り分けのために、もっとシンプルにBroadcastReceiverを動的に登録、Notification通知を行うだけのシンプルなアプリを作成しましたが、うまくいっておりません。
なお、AndroidManifest.xmlに静的に登録すると、正常に受信できることは確認しました。
しかし、今回は動的に登録したいと考えています。
できなければできないでも別に構わないのですが、Androidデベロッパーのページにも方法が書いてあるのにうまく動かない理由がわかりません。
なにか足りない処理があるのか、もしくはできない理由がわかればご教示ください。
発生している問題・エラーメッセージ
エラーは何も出ません
該当のソースコード
Kotlin
1class MainActivity : AppCompatActivity() { 2 companion object { 3 const val CHANNEL_ID = "a" 4 const val NOTIFICATION_ID = 1 5 const val ACTION_SNOOZE = "com.example.myapp.ACTION_SNOOZE" 6 const val CUSTOM_ACTION = "com.example.myapp.CUSTOM_ACTION" 7 } 8 private lateinit var receiver: MyBroadcastReceiver 9 10 fun createNotification(){ 11 val snoozeIntent = Intent(ACTION_SNOOZE, Uri.EMPTY,this,MyBroadcastReceiver::class.java) 12 val snoozePendingIntent: PendingIntent = 13 PendingIntent.getBroadcast(this, 0, snoozeIntent, 0) 14 15 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 16 val channel = 17 NotificationChannel(CHANNEL_ID, "チャンネル名", NotificationManager.IMPORTANCE_DEFAULT) 18 19 val notificationBuilder = NotificationCompat.Builder(applicationContext, CHANNEL_ID) 20 .setSmallIcon(R.drawable.ic_launcher_foreground) 21 .setContentTitle("My Notification") 22 .setContentText("This is a notification message.") 23 .addAction(R.drawable.ic_launcher_foreground, "タイトル", snoozePendingIntent) 24 25 26 val notificationManager = 27 getSystemService(Service.NOTIFICATION_SERVICE) as NotificationManager 28 notificationManager.createNotificationChannel(channel) 29 notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()) 30 } 31 } 32 33 override fun onCreate(savedInstanceState: Bundle?) { 34 super.onCreate(savedInstanceState) 35 setContentView(R.layout.activity_main) 36 37 val filter = IntentFilter().apply { 38 addAction(ACTION_SNOOZE) //NG 39 addAction(CUSTOM_ACTION) //OK 40 addAction(Intent.ACTION_SCREEN_OFF) //OK 41 addAction(Intent.ACTION_SCREEN_ON) //OK 42 } 43 44 // BroadcastReceiverを登録 45 receiver = MyBroadcastReceiver() 46 registerReceiver(receiver, filter) 47 48 // 通知を作成 49 createNotification() 50 51 //ボタンから独自アクションをsendBroadcast 52 val customIntent = Intent(CUSTOM_ACTION) 53 val buttonTest = findViewById<Button>(R.id.button_test) 54 buttonTest.setOnClickListener{ 55 sendBroadcast(customIntent) //OK 56 } 57 58 // ボタンから通知を作成 59 val buttonNotify = findViewById<Button>(R.id.button_notify) 60 buttonNotify.setOnClickListener{ 61 createNotification() //NG 62 } 63 } 64 65 override fun onDestroy() { 66 super.onDestroy() 67 unregisterReceiver(receiver) 68 69 } 70}
BroadcastReceiverには受信したIntentのactionをそのままログ出力するようにしています。
Kotlin
1class MyBroadcastReceiver : BroadcastReceiver() { 2 override fun onReceive(context: Context, intent: Intent) { 3 Log.d("tag",intent.action.toString()) 4 } 5}
build.gradle
1plugins { 2 id 'com.android.application' 3 id 'org.jetbrains.kotlin.android' 4} 5 6android { 7 namespace 'com.example.myapplication' 8 compileSdk 32 9 10 defaultConfig { 11 applicationId "com.example.myapplication" 12 minSdk 21 13 targetSdk 32 14 versionCode 1 15 versionName "1.0" 16 17 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 } 19 20 buildTypes { 21 release { 22 minifyEnabled false 23 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 24 } 25 } 26 compileOptions { 27 sourceCompatibility JavaVersion.VERSION_1_8 28 targetCompatibility JavaVersion.VERSION_1_8 29 } 30 kotlinOptions { 31 jvmTarget = '1.8' 32 } 33} 34 35dependencies { 36 37 implementation 'androidx.core:core-ktx:1.7.0' 38 implementation 'androidx.appcompat:appcompat:1.4.1' 39 implementation 'com.google.android.material:material:1.5.0' 40 implementation 'androidx.constraintlayout:constraintlayout:2.1.3' 41 testImplementation 'junit:junit:4.13.2' 42 androidTestImplementation 'androidx.test.ext:junit:1.1.5' 43 androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 44}
試したこと
・システムブロードキャストインテントは受信できることを確認しました。
試したのはACTION_SCREEN_OFF
とACTION_SCREEN_OFF
で、実機の電源キーを押してディスプレイをON/OFFさせて確認しました。
・BroadcastReceiverの登録タイミングの問題かと思い、ボタンを押して任意のタイミングでsendBroadcastを送った時には受信できることを確認しました。
・sendBroadcastではなく、ボタンを押してNotificationを通知させてみましたが、こちらはActionをタップしても受信できませんでした。
※試したコードはsendBroadcastの部分をNotification関連のコードに置き換えただけです。
補足情報(FW/ツールのバージョンなど)
・確認中の端末は実機端末OPPO RENO A(Android 7)です。
以下のページを参照してサンプルを作成しています
・通知を作成する | Android デベロッパー | Android developers
・ブロードキャストの概要 | Android デベロッパー | Android developers
・インテントとインテント フィルタ | Android デベロッパー | Android developers
追記(3/12)
よく考えたら「最終的な目的」であるServiceの進捗をキャンセルさせるというだけなら、BroadcastReceiverを介するほうが難してく、自身のServiceに向けてIntentを送ったほうが簡単に実現できることがわかりました。
ですが、疑問は疑問としてあるので質問はそのままにしておきます。
実際のアプリのService内のコード
Kotlin
1 val cancelActionIntent = Intent(this, DownloadService::class.java).apply { 2 action = ACTION_CANCEL 3 } 4 val cancelPendingIntent = 5 PendingIntent.getService(this, 0, cancelActionIntent, 0)
回答1件
あなたの回答
tips
プレビュー