IT Share you

Android 9.0 : 서비스 시작이 허용되지 않음 : 앱이 백그라운드에 있습니다. onResume () 이후

shareyou 2020. 12. 5. 10:57
반응형

Android 9.0 : 서비스 시작이 허용되지 않음 : 앱이 백그라운드에 있습니다. onResume () 이후


나는 시도는 시작하는 음악 플레이어있어 Service에서 onResume()의를 Activity. 명확성을 위해 몇 줄을 제거했지만 코드는 효과적으로 다음과 같습니다.

@Override
protected void onResume() {
    super.onResume();

    startService(new Intent(this, MusicService.class));
}

충돌 로그에 따르면 Android P를 실행하는 일부 기기에서 예외가 발생합니다.

Caused by java.lang.IllegalStateException: Not allowed to start service Intent { cmp=another.music.player/com.simplecity.amp_library.playback.MusicService }: app is in background uid UidRecord{6a4a9c6 u0a143 TPSL bg:+3m25s199ms idle change:cached procs:1 seq(1283,1283,1283)}
       at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1577)
       at android.app.ContextImpl.startService(ContextImpl.java:1532)
       at android.content.ContextWrapper.startService(ContextWrapper.java:664)
       at android.content.ContextWrapper.startService(ContextWrapper.java:664)
       at com.simplecity.amp_library.utils.MusicServiceConnectionUtils.bindToService(SourceFile:36)
       at com.simplecity.amp_library.ui.activities.BaseActivity.bindService(SourceFile:129)
       at com.simplecity.amp_library.ui.activities.BaseActivity.onResume(SourceFile:96)

onResume()(및 super.onResume())이 호출 된 직후 내 앱이 백그라운드에있을 수있는 방법은 무엇입니까?

이것은 나에게 의미가 없습니다. 이것이 플랫폼 버그일까요? 이 충돌의 영향을받는 3500 명 이상의 사용자는 모두 Android P에 있습니다.


Google의 해결 방법이 있습니다.

이 문제는 향후 Android 릴리스에서 해결되었습니다.

응용 프로그램 충돌을 방지하는 해결 방법이 있습니다. 애플리케이션은 ActivityManager.getRunningAppProcesses ()를 호출하여 Activity.onResume ()에서 프로세스 상태를 가져올 수 있으며 중요도가 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND보다 낮은 경우 서비스 시작을 피할 수 있습니다. 장치가 완전히 깨어 있지 않으면 활동이 즉시 일시 중지되고 결국 완전히 깨어 난 후 다시 재개됩니다.

그래서 다음과 같이해야한다고 생각합니다.

// hack for https://issuetracker.google.com/issues/113122354
    List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
    if (runningAppProcesses != null) {
        int importance = runningAppProcesses.get(0).importance;
        // higher importance has lower number (?)
        if (importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)
            URLPlayerService.startActionBroadcastServiceData(PlayerActivity.this);
    }

핸들러를 해결 방법으로 사용했으며 꽤 잘 작동하지만 100 %는 아닙니다.

// hack for https://issuetracker.google.com/issues/113122354
   handler.postDelayed(() -> URLPlayerService.startService(PlayerActivity.this),200);

업데이트 : 이것은 Prod에서 우리에게 효과적이지만 100 %는 아닙니다. 나는 지난 한 달 동안 한 번의 충돌 보고서를 받았는데 그렇지 않으면 백 개가 훨씬 넘었을 것입니다. 이 문제가 제대로 해결되기 전까지는 이것이 현재로서는 최선의 선택 인 것 같습니다. 만약 내가 시간을 300 이상으로 늘렸다면 한번도 충돌이 일어나지 않았을까요?

우리는 지금까지 작동하는 것처럼 보이는 이것을 지금 테스트하고 있습니다. 더 많은 결과가 표시되면 업데이트됩니다.

class ResumingServiceManager(val lifecycle: Lifecycle) : LifecycleObserver {

    init {
        lifecycle.addObserver(this)
    }

    val disposable: CompositeDisposable = CompositeDisposable()

    fun startService(context: Context, intent: Intent) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            context.startService(intent)
        } else {
            Single.just(true)
                    .delaySubscription(300, TimeUnit.MILLISECONDS)
                    .subscribeOn(AndroidSchedulers.mainThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribeBy(
                            onSuccess = {
                                context.startService(intent)
                            }

                    ).addTo(disposable)
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun stopped() {
        disposable.clear()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun destroy() {
        lifecycle.removeObserver(this)
    }
}

에서 onCreate()그것을 초기화 한 후 언제든지 당신은 onResume 단지 통화 서비스를 시작하려면resumingServiceManager.startService(this, intent)

수명주기를 인식하므로 즉시 열기 / 닫기를 사용하여 백그라운드로 이동할 때 onSuccess가 트리거되지 않도록 일시 중지하면 일회용 항목을 지 웁니다.


우리 팀도 같은 문제에 직면했습니다. 내 캘린더에 2019 년 4 월 5 일이 표시되지만 삼성 Galaxy S9 +, Android 9.0 (One UI)에서 여전히 문제가 재현됩니다.

onResume에서 서비스를 시작하고 onPause의 바인딩을 해제합니다.

재생산 방법

이 로직을 사용하는 활동이 화면에 표시되면 기기를 잠그고 10 ~ 15 분 동안 터치하지 마세요. 화면 잠금 해제 후 앱이 충돌합니다.

어떻게 고치는 지

We found solution that actually work. Since android 8+, start your service in android.os.Handler.post(...)

Example (Kotlin):

override fun onResume() {
    super.onResume()
    Handler().post {
        val serviceIntent = Intent(activity, SomeService::class.java)
        activity?.startService(serviceIntent)
        activity?.bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE)
    }
}

Good luck!


This has been marked as 'fixed' in the Android Issue Tracker:

Presumably the fix will be released in one of the Android Q releases.

According to the Googler who closed the issue,

There is a workaround to avoid application crash. Applications can get the process state in Activity.onResume() by calling ActivityManager.getRunningAppProcesses() and avoid starting Service if the importance level is lower than ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND. If the device hasn’t fully awake, activities would be paused immediately and eventually be resumed again after its fully awake.


They fixed the crash (in some future release, not sure which exactly) and provided a workaround for now: https://issuetracker.google.com/issues/110237673#comment9


Maybe android.arch.lifecycle could be used as a workaround for this Android 9 bug?

public class MyActivity extends Activity implements LifecycleObserver {

    protected void onResume() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
                startService(intent);
            } else {
                ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
            }
        } else {
            startService(intent);
        }
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    void onEnterForeground() {
        startService(intent);
        ProcessLifecycleOwner.get().getLifecycle().removeObserver(this);
    }
}

I've found it here.

참고URL : https://stackoverflow.com/questions/52013545/android-9-0-not-allowed-to-start-service-app-is-in-background-after-onresume

반응형