[안드로이드 오류 처리] 배터리 최적화 ActivityNotFoundException: No Activity found to handle Intent { act=android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS }
안드로이드 운영체제 버전이 상향될수록 백그라운드 서비스에 대한 제약이 심해지고 있어요. 휴대폰 제조사마다 다르게 개발하여 운영되고 있기 때문에 모든 휴대폰에 대한 1:1 대응이 힘든 상황입니다. 최대한 사용자에게 앱이 제대로 동작하도록 해야할 필요가 있습니다. 그럼에도 불구하고 앱 내에서 해결될 수 없다면 블로그에 휴대폰 제조사별로 가이드를 제공하는 글을 작성해서 리뷰에 댓글로 알리기 시작했습니다. 그러나 이것 역시 한계가 오더라구요. 제조사별로 최신 운영체제가 설치된 휴대폰을 구입할 수 없기 때문이죠. 그나마 한국에 있을 때는 주변에 친구들 폰을 사용하여 설정 방법을 캡쳐하여 해결방법을 블로그에 썼지만 지금은 그런 상황이 안되기에…….최근에 앱이 동작을 멈춘다는 사용자의 리뷰들이 많이 올라와서 해결책을 찾고 있었습니다. 사용자가 설정창을 직접 찾아 들어가기 힘드니( Settings > Battery > Battery Optimization), 앱 설정에서 다이렉트로 호출해서 설정만 가능하게 하는 방법으로 구현하였습니다. 사용자가 체크만 하면 바로 앱에서 자동으로 설정하도록 구현할 수 도 있지만, 이 방법을 사용하게 되면 구글플레이 스토어 등록이 거부 될 수 있으며, 어느날 갑자기 기기 및 네트워그 악용 위반으로 앱이 마켓에서 삭제될 수도 있음으로 배제하였습니다. 배터리 최적화 설정 창을 호출하는 방법은 아래와 같은 코드 스니펫 처럼 구현하였어요. 휴대폰 운영체제 버전에 따라 배터리 최적화로 노출될 수도 있고, 절전 예외 처리로 노출 될 수 도 있습니다. 어차피 같은 의미입니다.
//배터리최적화
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
findViewById(R.id.battery_opti_layout).setVisibility(View.VISIBLE);
setStatusBatteryToggle();
}else {
findViewById(R.id.battery_opti_layout).setVisibility(View.GONE);
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Intent i = new Intent();
i.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
startActivityForResult(i, 119);
}
운영체제의 버전이 마시멜로우 부터 설정뷰가 보이도록 처리하였습니다. 그런데 파이어베이스에 오류보고가 올라오기 시작하네요.
Fatal Exception: android.content.ActivityNotFoundException:
No Activity found to handle Intent
{ act=android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1879)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1546)
at android.app.Activity.startActivityForResult(Activity.java:4298)
at android.app.Activity.startActivityForResult(Activity.java:4245)
at com.text.SettingActivity$3.onCheckedChanged(SettingActivity.java)
at android.widget.CompoundButton.setChecked(CompoundButton.java:165)
at android.widget.CompoundButton.toggle(CompoundButton.java:118)
at android.widget.CompoundButton.performClick(CompoundButton.java:123)
at android.view.View$PerformClick.run(View.java:22596)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7331)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
오류 내용은 배터리최적화 옵션 액티비티가 존재하지 않는 다는 것을 의미합니다.
오류보고가 올라오는 휴대폰의 종류는 다음과 같아요. 안드로이드 6.0, 6.01이 설치된 휴대폰에서 오류보고가 올라오고 있습니다. 삼성 갤럭시 A5 모델과 갤럭시 S5 Mini, 오포 CPH1609, CPH1701 등입니다.
오류 처리를 위해 Android 개발자 문서를 다시 살펴보았습니다. 개발자 문서에는 해당 인텐트 액티비티 지원을 안드로이드 마시멜로우 부터 지원된다고 적혀있어요. API Level 23은 Android 6.0 M 마시멜로우 버전을 의미합니다.
ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
Added in API level 23
public static final String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
Activity Action: Show screen for controlling which apps can ignore battery optimizations.
Input: Nothing.
Output: Nothing.
You can use PowerManager.isIgnoringBatteryOptimizations() to determine if an application is already ignoring optimizations. You can use ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS to ask the user to put you on this list.
Constant Value: "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS"
안드로이드 6.0이 설치된 휴대폰이 설치된 다른 폰들에서 오류보고가 올라오지 않는 것을 보면, 이부분에 대한 처리 역시 휴대폰 제조사별로 커스터마이징 처리한 것으로 보여집니다.
안드로이드 6..0이 설치된 모든 안드로이드 폰을 제외시킬 수 는 없음으로 해결책으로 try{}cacth()문을 걸어서 지원되지 않음을 알리는 토스트 메세지를 호출해 주었습니다.
try {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Intent i = new Intent();
startActivityForResult(i, 119);
}
}catch (ActivityNotFoundException e){
//cont_24 : 죄송합니다. 지원되지 않는 휴대 전화입니다.
Toast.makeText(SettingActivity.this
, getResources().getString(R.string.cont_24)
, Toast.LENGTH_LONG).show();
}
안드로이드 개발자 문서 가이드
developer.android.com/training/monitoring-device-state/doze-standby.html#whitelisting-cases
developer.android.com/training/monitoring-device-state/doze-standby.html#support_for_other_use_cases
타 사용 사례 지원
거의 모든 앱은 네트워크 연결, 알람, 작업 및 동기화를 제대로 관리하고 FCM 높은 우선순위 메시지를 사용하여 잠자기 모드를 지원할 수 있습니다. 하지만 일부 사용 사례에서는 이것만으로는 부족합니다. 부족한 경우 시스템은 잠자기 및 앱 대기 모드 최적화에서 부분적으로 제외할 앱에 관한 허용 목록을 구성할 수 있도록 지원합니다.
허용 목록에 추가된 앱은 잠자기 및 앱 대기 모드 중 네트워크를 사용하고 부분 wake lock을 보유할 수 있습니다. 하지만 허용 목록에 추가된 앱에도 다른 앱과 마찬가지로 다른 제한사항은 여전히 적용됩니다. 예를 들어 API 수준 23 이하에서는 허용 목록에 추가된 앱의 작업 및 동기화가 지연되며 일반 AlarmManager 알람은 실행되지 않습니다. isIgnoringBatteryOptimizations()를 호출하면 앱이 현재 예외 허용 목록에 포함되어 있는지 여부를 확인할 수 있습니다.
사용자는 설정 > 배터리 > 배터리 최적화에서 허용 목록을 수동으로 구성할 수 있습니다. 또는 시스템이 앱에서 사용자에게 허용 목록 추가를 요청하는 방법을 제공할 수도 있습니다.
- 앱은 ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS 인텐트를 실행하여 사용자가 앱을 추가할 수 있는 배터리 최적화로 바로 이동하게 할 수 있습니다.
- REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 권한이 있는 앱은 시스템 대화상자를 트리거하여 사용자가 설정으로 이동하지 않고도 직접 허용 목록에 앱을 추가하도록 할 수 있습니다. 앱은 ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 인텐트를 실행하여 대화상자를 트리거합니다.
- 사용자는 필요에 따라 허용 목록에서 앱을 수동으로 삭제할 수 있습니다.
허용 목록에 앱을 추가하도록 사용자에게 요청하기 전에 앱이 허용 목록에 추가할 수 있는 사용 사례와 일치하는지 확인하세요.
참고: Google Play 정책에서는 앱의 핵심 기능에 악영향을 미치는 경우가 아니면 앱이 Android 6.0 이상의 전원 관리 기능(잠자기 및 앱 대기 모드)에서 직접 제외 요청을 하는 것을 금지하고 있습니다.
기기 및 네트워크 악용
사용자의 기기, 기타 기기 또는 컴퓨터, 서버, 네트워크, 애플리케이션 프로그래밍 인터페이스(API), 서비스(기기에 설치된 기타 앱, Google 서비스, 승인된 이동통신사 네트워크를 포함하나 이에 국한되지 않음)를 방해하거나, 작동에 지장을 주거나, 손상하거나, 무단으로 액세스하는 앱은 허용되지 않습니다.
Google Play의 앱은 Google Play의 핵심 앱 품질 가이드라인에 명시된 기본 Android 시스템 최적화 요구사항을 준수해야 합니다.
Google Play를 통해 배포된 앱은 Google Play의 업데이트 메커니즘 이외의 방법을 사용하여 자체적으로 수정, 대체 또는 업데이트할 수 없습니다. 또한 Google Play 이외의 출처에서 dex, JAR, .so 파일 등의 실행 코드를 다운로드해서는 안 됩니다. 이러한 제한사항은 가상 머신에서 실행되며 Android API에 제한적으로 액세스할 수 있는 코드(예: WebView 또는 브라우저에서 실행되는 자바스크립트)에는 적용되지 않습니다.
보안 취약점을 야기하거나 악용하는 코드는 허용되지 않습니다. 개발자에게 신고된 최근 보안 문제에 관해 알아보려면 앱 보안 개선 프로그램을 확인하세요.
- 광고를 표시하는 다른 앱을 차단하거나 방해하는 앱입니다.
- 다른 앱의 게임플레이에 영향을 미치는 게임 속임수 앱입니다.
- 서비스, 소프트웨어 또는 하드웨어를 해킹하거나 보안 기능을 우회하는 방법을 조장하거나 안내하는 앱입니다.
- 서비스 약관을 위반하는 방식으로 서비스 또는 API에 액세스하거나 이를 사용하는 앱
- 허용 목록에 포함할 수 없고 시스템 전원 관리를 우회하려고 시도하는 앱
- 제3자에게 프록시 서비스를 제공하는 앱은 이러한 기능이 사용자가 앱을 사용하는 주된 목적인 경우에만 서비스를 제공할 수 있습니다.
- Google Play가 아닌 다른 출처에서 dex 파일이나 네이티브 코드와 같은 실행 코드를 다운로드하는 앱 또는 타사 코드(예: SDK)
- 사용자의 사전 동의 없이 기기에 다른 앱을 설치하는 앱
- 악성 소프트웨어 배포 또는 설치로 연결하거나 이러한 활동을 조장하는 앱