본문 바로가기

안드로이드/오류

[프로젝트] 정각에 해야지 - 알림 오류

프로젝트 명 : 정각에 해야지

목표 : 스케쥴과 하루 루틴을 입력하고, 루틴에 대해서는 해당 시간에 알림을 보내 규칙적인 생활을 하기 위함

 

첫번째 문제

테스트용으로 루틴을 1~2분 뒤로 맞춰놓고 테스트하면 정상적으로 실행

그러나 다음날이 되면 알림이 밀려 앱을 실행하면 울리거나 울리지 않는 오류 발생

 

찾아보니 debug모드가 아닌 release모드로 컴파일하는 것을 추천하여 keystore를 생성하여 release모드로 컴파일 하였다.

테스트 결과 1~2분, 30분까지도 정상적으로 작동하였고, 다음날 9시에 루틴을 설정해놓고 기다렸다.

 

9시 5분.. 기다려도 알림이 오지 않아 앱을 실행했더니 알림 발생

 

똑같은 시간 밀림 현상이 발생했다.

 

안드로이드 공식문서에 따르면 (3번째 문단)

https://developer.android.com/reference/android/app/AlarmManager#setExactAndAllowWhileIdle(int,%20long,%20android.app.PendingIntent)

 

AlarmManager  |  Android Developers

 

developer.android.com

OS가 배터리 성능과 같은 것들을 고려하여 유연하게 일정을 변경할 수도 있다고 나와있다.

이는 기기가 절전모드일 때 발생하지만, 아닐 때도 발생할 수 있다고 한다.

 

즉, 자는 동안 기기 절전모드 > OS가 일정 변경일 가능성이 높다.

 

따라서 setExactAndAllowWhileIdle 대신 AlarmClock을 사용해 보기로 했다.

 

setAlarmClock 안드로이드 공식문서

https://developer.android.com/reference/android/app/AlarmManager?_gl=1*kl77u7*_up*MQ..*_ga*OTMxMTU1MzYxLjE3MDk3OTYzNDE.*_ga_6HH9YJMN9M*MTcwOTc5NjM0MS4xLjAuMTcwOTc5NjM0MS4wLjAuMA..#setAlarmClock(android.app.AlarmManager.AlarmClockInfo,%20android.app.PendingIntent)

 

AlarmManager  |  Android Developers

 

developer.android.com

공식문서에 따르면 setAlarmClocksetExactAndAllowWhileIdle와 비슷한 기능이라고 나와있다.

또한 setExactAndAllowWhileIdle에서는 RTC_WAKEUP으로 DOZE모드를 깨웠는데

AlarmClock에는 RTC_WAKEUP과 같은 기능이 포함되어 있다고 한다.

 

테스트 결과

테스트로 9시와 14시로 루틴을 설정해놓았다.

9시에 폰을 확인해보았는데 알림이 오지 않아 좌절하고 앱을 들어가봤는데 setting에서 알림 허용이 꺼져있었다.

다시 한번 14시를 노리고 기다린 결과 14시에 등록한 알림이 정확이 옴으로써 문제를 해결했다.

 

알림이 밀리는 현상은 setExactAndAllowWhileIdle의 OS 문제가 맞았고, AlarmClock으로 해결이 가능했다.

 

두번째 문제

사소한 문제였지만 설정한 시간이 현재 시간보다 이전이면 루틴 등록 시점에 알림이 와버린다.

val calendar : Calendar = Calendar.getInstance().apply {
            timeInMillis = System.currentTimeMillis()
            set(Calendar.HOUR_OF_DAY, hour)
            set(Calendar.MINUTE, minute)
            set(Calendar.SECOND, 0)
        }
        
        
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//       alarmManager?.setExactAndAllowWhileIdle(
//           AlarmManager.RTC_WAKEUP,
//           calendar.timeInMillis,
//           pendingIntent
//       )
    val alarmClock = AlarmManager.AlarmClockInfo(calendar.timeInMillis, pendingIntent)
    alarmManager?.setAlarmClock(alarmClock, pendingIntent)
}

 

위와 같이 Calendar를 이용하여 시간 설정 이후 AlarmManager에 등록해주는 방식이다.

 

처음에는 Calender와 AlarmManager 중 무엇이 문제인지 몰라 setEactAndAllowWhileIdle에서 AlarmClock으로 바꿔보았다.

 

현상은 그대로..

 

Calendar 문제라 생각하여 다음과 같은 코드를 추가해 주었더니 문제가 해결되었다.

if (calendar.time < Date()) {
    calendar.add(Calendar.DAY_OF_MONTH, 1)
}

 

세번째 문제

앱을 처음 설치 후 루틴을 등록하면 알림이 안온다.

그 이유는 알림 허용이 안되어 있기 때문에

 

알림이 와야하는 시간에 알림대신 알림 허용 메시지가 온다.

 

처음엔 그냥 권한 요청만 넣어서 앱 처음 실행 시 권한 요청 받고 시작하면 문제 없다고 생각했다.

 

SCHEDULE_EXACT_ALARM은 요청해도 안오고... 문제는 그대로

 

알고보니 POST_NOTIFICATIONS 권한을 요청해야 알림 메시지가 온다.

그러나 Manifest.permission에 POST_NOTIFICATIONS이 없었다.

 

사람들은 잘 사용하던데 왜 나는 없는걸까

 

찾아보니 버전문제였다.

 

https://medium.com/%EB%B0%95%EC%83%81%EA%B6%8C%EC%9D%98-%EC%82%BD%EC%A7%88%EB%B8%94%EB%A1%9C%EA%B7%B8/%EC%95%8C%EB%A6%BC-%EA%B6%8C%ED%95%9C-%EC%9A%94%EC%B2%AD%EC%97%90-%EA%B4%80%ED%95%9C-%EB%AA%A8%EB%93%A0%EA%B2%83-feat-android-13-5f20d17b5d09

 

안드로이드 알림 권한에 관한 모든것(feat. Android 13)

targetSdkVersion만 안올리면 아직 대응 안해도 된다고 생각하셨나요? targetSdkVersion과 상관없이 Android 13 기기부터 알림 권한 팝업이 뜨기 시작합니다. 대응하면서 알아야 할것들과 공식문서에는 없는

medium.com

 

무차별적인 알림과 같은 악용으로 인해 Android 8.0부터 알림 채널(Notification Channel)을 도입시켜 용도에 맞는 채널에 알림을 보내게 하고, 채널 별로 On/Off가 가능하도록.

 

채널 이후(안드로이드 버전 13)로 추가 된 기능이 알림 권한 POST_NOTIFICATIONS 였다. 

 

따라서 POST_NOTIFICATIONS는 target SDK version이 33 이상일 경우 제공되었고 나의 버전은 32였기 때문에 해당 기능이 보이지 않았던 것이다.

 

이후 버전을 33으로 올린 후 알림 권한 요청 기능을 추가할 수 있었다.

 

알림 권한 요청 시 다음과 같은 에러가 발생한다면

 java.lang.SecurityException needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms

 

Menifest에 <uses-permission android:name="android.permission.USE_EXACT_ALARM" /> 를 추가해주면 된다.