前提
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
あなたの回答
tips
プレビュー