Tim*_*eed 64 android android-service android-9.0-pie
我有一个音乐播放器,试图启动Service
中onResume()
的一个Activity
.为清晰起见,我删除了几行,但代码有效:
@Override
protected void onResume() {
super.onResume();
startService(new Intent(this, MusicService.class));
}
Run Code Online (Sandbox Code Playgroud)
根据崩溃日志,这在运行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)
Run Code Online (Sandbox Code Playgroud)
在调用onResume()
(和super.onResume()
)之后,我的应用程序是如何处于后台的?
这对我没有任何意义.这可能是一个平台错误吗?受此次崩溃影响的所有3500多名用户都在Android P.
Google提供了一种解决方法:
此问题已在未来的Android版本中解决。
有一种解决方法可以避免应用程序崩溃。如果重要性级别低于ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,应用程序可以通过调用ActivityManager.getRunningAppProcesses()来获取Activity.onResume()中的进程状态,并避免启动Service。如果设备尚未完全唤醒,则活动将立即暂停,并最终在完全唤醒后再次恢复。
所以我认为应该这样:
// 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);
}
Run Code Online (Sandbox Code Playgroud)
我已经使用处理程序作为解决方法,它的效果很好,但不是100%:
// hack for https://issuetracker.google.com/issues/113122354
handler.postDelayed(() -> URLPlayerService.startService(PlayerActivity.this),200);
Run Code Online (Sandbox Code Playgroud)
更新:这对我们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)
}
}
Run Code Online (Sandbox Code Playgroud)
在onCreate()
初始化它然后随时想要在onResume中启动服务只需调用resumingServiceManager.startService(this, intent)
这是生命周期意识所以它会清除一次性如果它暂停取消onSuccess触发时它可能在前往后台的途中立即打开/关闭.
这已在 Android 问题跟踪器中标记为“已修复”:
据推测,该修复程序将在 Android Q 版本之一中发布。
据关闭问题的谷歌员工说,
有一种解决方法可以避免应用程序崩溃。如果重要性级别低于 ,应用程序可以
Activity.onResume()
通过调用获取进程状态ActivityManager.getRunningAppProcesses()
并避免启动服务ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
。如果设备尚未完全唤醒,活动将立即暂停,并最终在完全唤醒后再次恢复。
小智 5
我们的团队面临着同样的问题。我的日历显示 2019 年 4 月 5 日,但问题仍然在我的 Samsung Galaxy S9+、android 9.0(一个 UI)上重现
我们在onResume中启动服务并在onPause中解除绑定。
如何重现
当屏幕上出现具有此逻辑的活动时,只需锁定您的设备,并且 10-15 分钟内不要触摸。解锁屏幕后,应用程序将崩溃。
怎么修
我们找到了实际有效的解决方案。从 android 8+ 开始,在 android.os.Handler.post(...) 中启动你的服务
示例(科特林):
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)
}
}
Run Code Online (Sandbox Code Playgroud)
祝你好运!
小智 -3
也许 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);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
15826 次 |
最近记录: |