質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

0回答

415閲覧

BroadcastReceiverでイベントを受け取った後にComposableを切り替えられない。

Rf_i.m

総合スコア6

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2022/08/20 06:21

前提

Kotlin,Jetpack Composeで目覚まし時計アプリを作っています。
設定した時刻になったら画面を遷移する機能を実装したいのですが、BroadcastReceiverからoverrideしたonReceiveが発火されたタイミングでComposableを表示する方法がわからず行き詰まっています。

実現したいこと

  • アラームがカウントされていっている画面(AlarmCountingScreen)が、AlarmManagerで設定した時刻になり登録されたBroadcastのonReceiveが呼び出されたタイミングで別の画面(AlarmRingingScreen)に遷移させること。

以下の画面を設定した時刻になったタイミングで別の画面に切り替えたいです。
イメージ説明

発生している問題・エラーメッセージ

BroadCastReceiverを継承したAlarmReceiverの中にコールバックインターフェースを作り、
Composableの中でonReceiveしたことを検知しようとしているのですが、デバックしたところ、コールバックを呼び出しているもとでは、呼び出せる関数がないと表示され、実際に時間になっても画面は遷移しません。(時間になると通知が来るようNotification Manager を設定しているのですが、そちらは時間になったら呼び出されています。)
イメージ説明

該当のソースコード

kotlin

1@RequiresApi(Build.VERSION_CODES.M) 2@Composable 3fun AlarmCountingScreen(selectedTime: String, 4 navController: NavHostController, 5 context: Context, 6 alarmState: AlarmState){ 7 androidx.compose.material.Surface { 8 Column( 9 Modifier 10 .fillMaxSize() 11 .fillMaxHeight() 12 .fillMaxWidth(), 13 horizontalAlignment = Alignment.CenterHorizontally, 14 verticalArrangement = Arrangement.Center 15 ) { 16 17 val receiver = AlarmReceiver() 18 receiver.setListener(object : 19 AlarmReceiver.onFinishBroadCastListener{ 20 override fun onReceiveOk(broadcastReceiver: BroadcastReceiver) { 21 navController.navigate("AlarmRingingScreen") 22 } 23 } 24 ) 25 26 Text( 27 text = "${selectedTime}時に起こします", 28 modifier = Modifier.fillMaxWidth(), 29 textAlign = TextAlign.Center, 30 fontSize = 25.sp, 31 ) 32 Spacer(modifier = Modifier.height(20.dp)) 33 AndroidView( 34 factory = { context1 -> 35 TextClock(context1).apply { 36 // on below line we are setting 12 hour format. 37 format12Hour?.let { this.format12Hour = "hh:mm:ss a" } 38 // on below line we are setting time zone. 39 timeZone?.let { this.timeZone = it } 40 // on below line we are setting text size. 41 textSize.let { this.textSize = 30f } 42 } 43 }, 44 modifier = Modifier.padding(5.dp), 45 ) 46 Button(onClick = { 47 navController.navigateUp() 48 OperateAlarm(context,selectedTime).cancelAlarm() 49 alarmState.isCanceled = true 50 }) { 51 Text(text = "キャンセル") 52 } 53 } 54 } 55}

kotlin

1class AlarmReceiver : BroadcastReceiver(){ 2 3 interface onFinishBroadCastListener{ 4 fun onReceiveOk(broadcastReceiver: BroadcastReceiver) 5 } 6 7 public fun setListener(listener: onFinishBroadCastListener){ 8 mListener = listener 9 } 10 11 private var mListener:onFinishBroadCastListener? = null 12 13 override fun onReceive(context: Context, intent: Intent) { 14 try { 15 showNotification(context,"Like Share","Subscripiton") 16 playRingTone(context) 17 mListener?.onReceiveOk(this) 18 Log.d("Receive Success","ちゃんと受け取れているよー") 19 20 } 21 catch (e:Exception) { 22 Log.d("Receive Exeption",e.printStackTrace().toString()) 23 } 24 } 25} 26 27private fun playRingTone(context: Context){ 28 var alarmUri: Uri? = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM) 29 if (alarmUri == null) { 30 alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) 31 } 32 // setting default ringtone 33 val ringtone = RingtoneManager.getRingtone(context, alarmUri) 34 // play ringtone 35 ringtone.play() 36} 37 38 39private fun showNotification(context: Context,title:String,description: String){ 40 val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager 41 val channelName = "message_channel" 42 val channelId = "message_id" 43 44 if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){ 45 val channel = NotificationChannel(channelId,channelName,NotificationManager.IMPORTANCE_DEFAULT) 46 manager.createNotificationChannel(channel) 47 } 48 val builder = NotificationCompat.Builder(context,channelId) 49 .setContentTitle(title) 50 .setContentText(description) 51 .setSmallIcon(R.drawable.ic_launcher_foreground) 52 manager.notify(1,builder.build()) 53} 54

AlarmCountingScreen.kt

1 2

試したこと

すでに作っていたインターフェースのisRingingをtrueにすることによる遷移の方法も考えたのですが、AlarmStateをBroadcastReceiver内で扱う方法がわからなかったです。

kotlin

1@Stable 2interface AlarmState{ 3 var isCanceled:Boolean 4 var isRinging:Boolean 5 var isSuccesfullyStopAlarm:Boolean 6} 7 8// どれか一つだけがTrueになるという仕組みにする必要あり 9class AlarmStateClass:AlarmState{ 10 override var isCanceled = false 11 override var isRinging = false 12 override var isSuccesfullyStopAlarm = false 13} 14

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問