Android 9.0:不允许启动服务:应用程序处于后台。。在onResume()之后
我有一个音乐播放器,它试图在Android 9.0:不允许启动服务:应用程序处于后台。。在onResume()之后,android,android-service,android-9.0-pie,Android,Android Service,Android 9.0 Pie,我有一个音乐播放器,它试图在活动的的onResume()中启动服务。为了清晰起见,我删除了几行,但代码实际上是: @Override protected void onResume() { super.onResume(); startService(new Intent(this, MusicService.class)); } 根据崩溃日志,这在一些运行Android p的设备上引发了一个异常: Caused by java.lang.IllegalStateExcept
活动的的onResume()
中启动服务。为了清晰起见,我删除了几行,但代码实际上是:
@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上。Android.arch.lifecycle是否可以用作此Android 9错误的解决方案
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);
}
}
更新:这在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)
}
}
class ResumingServiceManager(val生命周期:lifecycle):LifecycleObserver{
初始化{
lifecycle.addObserver(此)
}
val disposable:CompositeDisposable=CompositeDisposable()
趣味startService(上下文:上下文,意图:意图){
if(Build.VERSION.SDK\u INT
在onCreate()
中初始化它,然后只要在onResume中调用resumingServiceManager.startService(此,intent)
它具有生命周期意识,因此当它暂停取消onSuccess触发时,它会清除一次性的,而onSuccess可能会立即打开/关闭到后台。这已在Android问题跟踪程序中标记为“修复”:
大概这个补丁将在安卓Q的一个版本中发布
据结束这一事件的谷歌人说
有一种解决方法可以避免应用程序崩溃。应用程序可以通过调用ActivityManager.GetRunningAppProcesss()
在Activity.onResume()
中获取进程状态,如果重要性级别低于ActivityManager.RunningAppProcessInfo.importance\u前台
,则避免启动服务。如果设备尚未完全唤醒,活动将立即暂停,并最终在完全唤醒后再次恢复
谷歌有一个变通办法:
这个问题已经在未来的Android版本中得到了解决
有一种解决方法可以避免应用程序崩溃。应用程序可以获得
通过调用
如果出现以下情况,请避免启动服务
重要性级别低于
ActivityManager.RunningAppProcessInfo.IMPORTANCE\u前台。如果
设备尚未完全唤醒,活动将立即暂停并停止
在它完全清醒后,最终会再次恢复
所以我认为应该是这样的:
// 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);
}
我们队也面临同样的问题。我的日历显示2019年4月5日,但问题仍然在我的三星Galaxy S9+、android 9.0(一个用户界面)上重现
我们在onResume中启动服务,并在Pause中解除绑定
如何复制
当屏幕上显示具有此逻辑的活动时,只需锁定设备,不要触摸10-15分钟。解锁屏幕后,应用程序将崩溃
如何修复
我们找到了实际可行的解决方案。从android 8+开始,在android.os.Handler.post(…)中启动您的服务
示例(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)
}
}
祝你好运 错误消息似乎模棱两可,我发现消息的最后一部分指的是服务所在的应用程序,而不是试图启动服务并绑定到服务的应用程序
如果服务的应用程序不是前景化的(即使服务本身是后台服务),则会出现错误:
现在,如果我在启动尝试启动服务的“客户端”应用程序之前,运行具有该服务的应用程序,使其位于前台,那么服务启动的一切工作正常
如果该服务是“后台服务”,且该服务的应用程序不在前台,则该服务可能会被终止——因此,如果您需要继续使用该服务,启动该服务实际上是不够的
这似乎是从安卓7到安卓8的变化的结果,在奥利奥,他们开始限制一些东西
上面的Android文档中对此进行了解释
文档中的建议是将您的逻辑迁移到计划的作业中,或者将该服务设置为前台服务,这样可以直观地显示该服务正在运行。我找到了重现该问题的方法
使用Android 10、11、12 DP2在Android Emulator上测试:
- 在
Activity.onResume()中启动启动服务的应用程序
- 按Home(主页)按钮将活动状态更改为stopped(停止)
- 等到
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)
}
}
W/System.err: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.mycompany.myserviceapp/.MyService }: app is in background uid null
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1505)
at android.app.ContextImpl.startService(ContextImpl.java:1461)
at android.content.ContextWrapper.startService(ContextWrapper.java:644)