본문 바로가기

Development/Android

Android Oreo로 타겟을 변경할때 겪었던 이슈들..


Google Playstore에서는 올해 11월 부터는 기존 등록된 애플리케이션에 대해서 targetsdkversion을 26(8.0)이상으로 변경하지 않으면 더이상 업데이트가 불가하도록 정책을 정하였다.

신규앱의경우 이달(8월)부터 targetsdkversion 26이상으로 적용하지 않으면 등록도 불가능 하도록 제한되었다. 아래의 post를 참조.

일반적으로 23이상의 runtime permission 은 익히 알려진 부분이고, 이전에 이미 target이 25였으므로 특별한 문제는 없었는데, 다른 몇몇 이슈들이 나를 당황하게 하였다.


BackgroundService 제한

개발하고 있는 서비스에서 잠금화면을 구현하기 위해서는 필수적으로 서비스가 구동되어야 한다. 서비스라고 해서 특별히 배터리를 소모하는 부분이 있는것이 아니라 Screen on / off receiver를 수신하도록 처리하는 broadcast를 위해 필요한데, 이전에는 backgroundService로 처리하면 되었으나, 현재는 startForegroundService로 Notification과 함께 구동하도록 하지 않으면 일정시간이 지난후 os level에서 해당하는 service는 kill된다.

Broadcast는 명시적으로 호출해야 한다.

위의 포스트에서 확인 할 수 있듯 ACTION_PACKAGE_REPLACEDACTION_POWER_CONNECTED 는 더이상 AndroidManifest에 등록하는것만으로 수신이 불가능하다.

ACTION_PACKAGE_REPLACED 대신 ACTION_MY_PACKAGE_REPLACED 를 사용하면 수신이 가능하나 ACTION_POWER_CONNECTED 등은 수신이 불가능하고, jobscheduler의 제약조건으로 구동되도록 변경하여야 한다.

아울러 target을 상향하면 특정 broadcast를 호출하려면 action만 지정하는 것이 아닌 호출대상이될 receiver class도 지정하여야 한다.

지속적으로 Manifest 등록만으로 활용이 가능한 목록은 다음의 페이지에서 확인이 가능(사실상 남은건 ACTION_BOOT_COMPLETED 정도.ㅠㅠ)

NotificationChannel

Android는 버전이 변경될 때 마다 상당히 많이 변경되는 부분이 Notifcation이다. targetSdkVersion을 26이상으로 올리지 않더라도 notificationChannel은 적절한 단위로나누어 생성하는 것이 유리하다. 왜냐하면 notificationChannel단위로 8.0이상의 기기에서는 notification을 제어하기 때문. 혹시라도 사용자가 해당채널을 차단하는 등의 행위를 하더라도 매우 중요도가 높은 notification은 별도의 channel을 통해 전송이 가능하다.

한번 등록된 notificationChannel의 경우 configuration(진동,중요도 등)을 변경할 수 있는 기능을 제공해 주지 않기 때문에 priority를 변경하려면 priority가 다른 channel을 생성해 주어야 한다.

Targetsdkversion 26과 27의 차이?

얼마전 서비스를 단계별 배포를 통해 업데이트를 진행하였는데, 8.1.0기기(27)에서 다음과 같은 크래시가 몇건 발생하였다.

Fatal Exception: android.app.RemoteServiceException: Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x40 color=0x00000000 vis=PRIVATE)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1790)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6606)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:518)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)

stacktrace내용에서 보여지듯, startForeground 수행시 NotificationChannel이 없어서 crash가 발생하였다.

문제는 notificationchannel을 create하고, notification을 notify하도록 하면 별도의 ongoing notification을 유지할 수 밖에 없다는 문제가 생긴다.

이 문제를 해결하기 위한 방법은 생각보다 단순했다. targetSdkVersion을 27에서 26으로 변경하면 해결. 다만 임시적인 방편이므로 이후 target 상향을 검토할때에는 사용자에게 어떤이유로 service가 구동되고 있는지를 안내해 주는 notification을 제공해주면된다. os 가 update될 수록 사용자가 인지하지 못하는 background process는 구동이 불가능한 방향으로 가는듯 하다. 당연히 맞는 방향이라고 생각이 들지만 열려있던 것들이 점점 닫혀가는듯한 불편함은 어쩔 수 없는 느낌.

정리하며..

대부분의 메이저 서비스들은 이미 target상향에 대한 작업을 하였겠으나, 현재 회사에서 운영중인 서비스는 기존 하위타겟으로만 동작하는 feature로 인해 10월 정도까지 모든 타겟변경을 완료할 계획이다. ongoing notification을 다루는 부분이 다수 존재하다보니 version변경에 많은 영향을 받게되는데, alarmmanager나 jobscheduler등으로 보완처리하는 코드들이 늘어나다보니, 오히려 기기성능에 영향을 주지 않을까 항상 고민하며 구현하게 되는 부분이 늘어나게 된다.

android의 파편화는 숙명과도 같은 부분이지만 battery절감을 위한 지속적인 제약사항은 자연의 섭리 처럼 받아들여야 할지도 모르겠다.


'Development > Android' 카테고리의 다른 글

Firebase ML Kit 검토  (0) 2018.09.13
MultiDex와 Play Service SDK에 관한 고찰.  (0) 2015.07.10