Android

[포그라운드서비스 오류 Android 12] android.app.ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground()

갤럭시 S20 휴대폰에서 발생한 오류이다. 앱을 실행 후 백그라운드 서비스를 시작했지만 포그라운드 서비스로 올라오지 못해서 발생하는 오류이다. 갤럭시S20은 안드로이드12 운영체제를 사용하는 휴대전화이다.

Android 12 포그라운드서비스 오류

2022-09-18 14:20:31.179 13864-13864/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: smart.app.battery.mobile.charger, PID: 13864
    android.app.ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{db20abe u0 smart.app.test/.StatusService}
        at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:2147)
        at android.app.ActivityThread.access$2900(ActivityThread.java:310)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2376)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:226)
        at android.os.Looper.loop(Looper.java:313)
        at android.app.ActivityThread.main(ActivityThread.java:8669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)

안드로이드 12를 타켓팅하는 경우 포그라운서비스  실행 제한이 시작된다.!! 아 정말 힘들게하는 구글!! 백그라운드 서비스 제한에 이어 이제는 포그라운 서비스도 제한을 시작하였다. 자세한 내용은 아래 글을 참고하면 되고……

안드로이드 12 부터 포그라운드 서비스 시작 제한이 시작됩니다. 대비하세요!! 실시간 처리가 필

포그라운드 서비스 시작 제한 Android 12를 타겟팅하는 앱은 몇 가지 특수한 사례를 제외하고 백그라운드에서 실행되는 동안 더 이상 포그라운드 서비스를 시작할 수 없습니다. 앱이 백그라운드

playground.naragara.com

포그라운드 서비스 실행 제한  |  Android 12  |  Android Developers

이제 Android 13 개발자 프리뷰를 사용할 수 있습니다. 지금 사용해 보시고 의견을 알려 주세요. 포그라운드 서비스 실행 제한 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하

developer.android.com

Foreground services  |  Android Developers

Foreground services Stay organized with collections Save and categorize content based on your preferences. Foreground services perform operations that are noticeable to the user. Foreground services show a status bar notification, so that users are activel

developer.android.com

그래서 해결책은? 포그라운드 서비스 권장 대안: WorkManager를 사용하라고 하지만

정확한 시간에 알림을 해야하는 경우에는 사용할 수 없다.

포그라운드 서비스 실행이 허용되게 하는 방법은 다음과 같은 케이스들이 있다.

백그라운드에서 포그라운드 서비스 실행이 허용되는 경우

다음 상황에서는 앱이 백그라운드에서 실행되는 동안에도 포그라운드 서비스를 시작할 수 있습니다.

위 허용 대상 중에 방법을 찾아야한다.

나의 경우 밑에서 2번째 혹은 마지막 방법으로 적용해야하는데

다음 방법은 적용해도 동일한 오류가 계속 발생되었다.

시스템에서 '고정' 포그라운드 서비스를 다시 시작합니다. 
포그라운드 서비스를 고정하려면 onStartCommand()에서 
START_STICKY나 START_REDELIVER_INTENT를 반환합니다.

onStartCommand는 서비스가 시스템에 의해서 종료되었을 때 재시작 할지 결정하는 flag이며 종류는 다음과 같다.

START_NOT_STICKY
서비스가 시스템에 의해 종료되어도 재시작 하지 않습니다.

START_STICKY
서비스가 시스템에 의해 종료되면 재시작합니다. 
그러나 종료 전에 사용된 마지막 Intent는 Null로 초기화하여 재시작 합니다.

START_REDELIVER_INTENT
서비스가 시스템에 의해 종료되면 재시작하며 종료 전에 보류된 Intent를 모두 순차적으로 전달합니다. 
서비스가 지속되어야 하는 파일다운로드에 적합합니다.

마지막 방법인 ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS 인텐트 작업을 이미 사용중인데 오류가 발생한다.

안드로이드 12 테스트폰이 없어서 테스트를 못했는데

이번에 폰 바꾸면서 확인하게 된 계기가 되었다.

나의 경우 사용자에게 알림 다이얼로그를 노출 후 사용자가 확인 버튼을 누르면

배터리 사용량 최적화 리스트로 바로 보내서 사용자가 예외시키도록 해주고 있는데

가이드의 내용은 시스템 설정에서 앱 정보 페이지사용자를 보내 사용자가 이 옵션을 찾도록 하라는 것이다.

그렇게 하든 이렇게 하든 찾아가는 방법만 다를뿐

사용자가 설정하는 옵션은 배터리 최적화에서 제외시키는 동작은 동일한다.

그런데 왜 오류는 여전히 발생중인가??

앱 정보 페이지에 가면 기존에 없던 옵션이 보인다. 안드로이드 12부터 추가된 것같다.

앱 정보(애플리케이션 정보) 화면은 다음과 같다.

사용량 > 배터리 메뉴를 클릭하면 다음과 같이 아주 쉽게 사용자가 변경할 수 있는 UI가 나타난다.

배터리 사용량 최적화 리스트 화면으로 보내서 앱을 찾아서 해제 하는 방식은 일반 사용자들이 어려워 할 수 있는데

이건 너무 쉽게 설정할 수 있게 해주고 있다.

위 캡쳐 화면의 내용과 같이  제한없음에 이미 설정되어 있는데

여전히 오류가 발생하는 것이다.

삼성전자서비스 사이트에는 다음과 같이 안내하고 있다

참고로 Android 8.0에 추가된 백그라운드 실행 제한과는 관련이 없다.

이 제한 및 예외는 Android 12/SDK 31 버전에서 새롭게  추가되었다 .

포그라운드 서비스 타입을 지정해보려했으나 해당사항이 없었다.

<service android:description="string resource"
         android:directBootAware=["true" | "false"]
         android:enabled=["true" | "false"]
         android:exported=["true" | "false"]
         android:foregroundServiceType=["camera" | "connectedDevice" |
                                        "dataSync" | "location" | "mediaPlayback" |
                                        "mediaProjection" | "microphone" | "phoneCall"]
         android:icon="drawable resource"
         android:isolatedProcess=["true" | "false"]
         android:label="string resource"
         android:name="string"
         android:permission="string"
         android:process="string" >
    . . .
</service>

[안드로이드 오류 처리] 배터리 최적화 ActivityNotFoundException: No Activity found to handle Intent { act=android.

안드로이드 운영체제 버전이 상향될수록 백그라운드 서비스에 대한 제약이 심해지고 있어요. 휴대폰 제조사마다 다르게 개발하여 운영되고 있기 때문에 모든 휴대폰에 대한 1:1 대응이 힘든 상

playground.naragara.com

참고로 카카오톡 앱은 안드로이드 12에서

아래 퍼미션을 사용중이고 “권한이 필요합니다” 다이얼로그 창을 띄운 후 확인을 누르면

배터리 최적화 리스트로 가지 않고 안내문구와 함께 “거부”, “허용” 버튼이 있는 시스템 대화 상자가  뜨도록 구현되어있다.

시스템 다이얼로그창 구현 방법은 아래 샘플 코드를 보면된다.

<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
public class CustomDialog extends DialogFragment
{
    public static CustomDialog newInstance() {
        return new CustomDialog();
    }
 
    @Override
    public Dialog onCreateDialog(Bundle a_savedInstanceState) {
    	String title = "권한이 필요합니다.";
        String message = "정상적인 앱 사용을 위해 해당 어플을 "배터리 사용량 최적화" 목록에서 "제외"하는 권한이 필요합니다. nn[확인] 버튼을 누른 후 시스템 알림 대화 상자가 뜨면 [허용] 을 선택해 주세요";
        OnClickListener clickListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent();
                intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                intent.setData(Uri.parse("package:" + getContext().getPackageName()));
                startActivity(intent);
            }
        };
 
        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(message)
                .setPositiveButton("확인", clickListener);
        return builder.create();
    }
}

그러나 이 역시 권한을 부여하는 방법의 하나일뿐 지금 발생하는 오류와는 무관하다고 생각된다.

이 권한을 사용하여 마켓에 올리면 심사과정에서 거부될 수 있다고 알고 있다.

배터리 최적화 관련 코드들은 아래 링크에서 참고할 수 있다.

android.os.PowerManager.isIgnoringBatteryOptimizations java code examples | Tabnine

public boolean isAppWhitelisted() { return powerManager.isIgnoringBatteryOptimizations(packageName);

www.tabnine.com

내가 원하는 나에게 맞는 해결책이 없는 것인가??

설마 모든 안드로이드 12 운영체제를 사용하는 폰에서 동일하게 발생하는 문제일까?

아니면 삼성전자 휴대전화에서만 발생하는 것일까?

아직 강제 안드로이드 12 적용 구글플레이 등록까지는

한 달 정도의 시간이 남아있다.

2022년 11월 부터는 무조건 안드로이드 12 이상을 타켓팅해야한다.

해결책을 찾아야한다.

삼성전자 개발자 사이트의 개발자 서포트를 활용하여

문의를 해둔 상태이다.

어떻게 하면 해결 가능 한지 문의를 해두었다.

그러나 몇 일이 지나도 답변이 없었다.

그래서 결국 해결책을 찾기 위해 많은 삽질과 구글링을 하였다.

그리고 우연히 오류 원인을 발견했다.

오류의 원인은 PendingIntent의 플래그값을 추가해주지 않아서였다.

포그라운드 서비스 시작시 사용하는 PendingIntent 관련 오류는 전혀 노출되지 않기 때문에 오류원인을 찾기 쉽지 않다.

안드로이드 12를 타켓팅하는 앱이라면 소스코드를 모두 뒤져서 PendingIntent 코드를 찾아 플래그값을 추가 해주면 된다.

자세한 내용은 아래 글 참고!!

Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. 오류 해결 방법

[안드로이드] Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. 오류 해결 방법

[reference]

Leave a Reply

error: Content is protected !!