본문 바로가기
프로그래밍/Android

[Android] Calendar를 이용해 특정시간에 푸시알림 보내기

by Youngs_ 2023. 11. 24.

아래 코드를 쓰면 10초 후에 아래 에러가 나온다 해결방법 찾는중..

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.appname, PID: 8806 android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{887a7c0 u0 com.mygym/.common.alarm.EndMembershipService} at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1945) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7356) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Activity.kt

OnCreate{
...
    binding.testAlarm.setOnClickListener(){
                Log.d("알람 셋팅 현재시간",LocalDateTime.now().toString())

				val calendar: Calendar = Calendar.getInstance().apply {
                    timeInMillis = System.currentTimeMillis()
                    set(Calendar.HOUR_OF_DAY, LocalDateTime.now().hour)
                    set(Calendar.MINUTE, LocalDateTime.now().minute+1)
                }

                startAlarm(calendar)
                // 사용하고자하는 Activity에서 broadcaster 객체를 생성해줍니다.
            }
...
}

private fun startAlarm(c: Calendar){

    Toast.makeText(this,"${c.time.minutes}분 후에 알림이옵니다.", Toast.LENGTH_SHORT).show()
    //알람매니저 선언
    val alarmManager: AlarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager

    val intent = Intent(this, TestReceiver:: class.java)

    //데이터 담기
    val curTime = DateFormat.getTimeInstance(DateFormat.SHORT).format(c.time)
    intent.putExtra("time", curTime)

    val pendingIntent = PendingIntent.getBroadcast(this, 1, intent, 0)

    //설정 시간이 현재시간 이전이면 +1일
    if(c.before(Calendar.getInstance())){

        c.add(Calendar.DATE, 1)
    }

    alarmManager.setExact(AlarmManager.RTC_WAKEUP, c.timeInMillis, pendingIntent)
}

 

Receiver.kt

class TestReceiver : android.content.BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent?) {

        if(intent != null){
            Log.e("알람", System.currentTimeMillis().toString())
        }
        Log.d("리시버실행", LocalDateTime.now().toString())

        val serviceIntent = Intent(context, TestService::class.java) // MyBackgroundService 를 실행하는 인텐트 생성
        context.startForegroundService(serviceIntent)// 서비스 인텐트를 전달한 foregroundService 시작 메서드 실행
    }


}

 

Service.kt

class TestService : Service() {

    
    lateinit var manager: NotificationManager
    lateinit var builder: NotificationCompat.Builder

    //오레오 이상은 반드시 채널을 설정해줘야 Notification이 작동함
    private val CHANNEL_ID = "channel1"
    private val CHANNEL_NAME = "Channel1"

    lateinit var context: Context

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onCreate() {
        context=this
        super.onCreate()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Thread {
            while (true) {
                Log.e("Service", "서비스가 실행 중입니다...")
                Log.e("Service", "" + count)
                try {
                    Thread.sleep(1000)
                    count++
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }.start()

        pushAlert()
        return super.onStartCommand(intent, flags, startId)
    }

    private fun pushAlert()
    {
        val am: AlarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        manager.createNotificationChannel(
            NotificationChannel(
                CHANNEL_ID,
                CHANNEL_NAME,
                NotificationManager.IMPORTANCE_DEFAULT
            )
        )
        builder = NotificationCompat.Builder(context, CHANNEL_ID)

        //알림창 클릭 시 activity 화면 부름
        val intent2 = Intent(context, MainActivity::class.java)
        val pendingIntent =
            PendingIntent.getActivity(context, 101, intent2, PendingIntent.FLAG_UPDATE_CURRENT)

        //알림창 제목
        builder.setContentTitle(LocalDateTime.now().toString())
        //알림창 아이콘
        builder.setSmallIcon(R.drawable.ic_launcher_background)
        //알림창 터치시 자동 삭제
        builder.setAutoCancel(true)
        builder.setContentIntent(pendingIntent)
        val notification: Notification = builder.build()
        manager.notify(1, notification)
    }

}

댓글