带有 boot_completed 的运行时异常 Android O [英] Runtime exception Android O with boot_completed
问题描述
我正在尝试在我的 BOOT_COMPLETED 接收器中启动 IntentService,但在 Android O (API 26) 中我得到:
I'm trying to start an IntentService within my BOOT_COMPLETED receiver, but in Android O (API 26) I get:
java.lang.RuntimeException:
java.lang.IllegalStateException:
Not allowed to start service Intent { act=intent.action.update cmp=packageName.services.OwnService }:
app is in background
(消息在一行中,但这样更容易阅读)
(Message is in one line, but this way it's easier readable)
我怎样才能以正确的方式做到这一点?
How can I do this the correct way?
推荐答案
以下是我在 一篇博文:
您的 BroadcastReceiver
接收 ACTION_BOOT_COMPLETED
广播在 Android 上可以调用 startForegroundService()
而不是 startService()
8.0+:
Your BroadcastReceiver
that receives the ACTION_BOOT_COMPLETED
broadcast
could call startForegroundService()
instead of startService()
when on Android
8.0+:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
public class OnBootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent i=new Intent(context, TestIntentService.class);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) {
context.startForegroundService(i);
}
else {
context.startService(i);
}
}
}
请注意,这在一定程度上有效,即使您的服务实际上没有永远调用 startForeground()
.您有时间四处走动调用 startForeground()
,与执行此操作的 ANR 间隔相当".如果您的工作时间长于一毫秒但少于几秒,您可以跳过 Notification
和 startForeground()
调用.然而,你会在 LogCat 中得到一个错误:
Note that this works, to an extent, even if your service does not actually
ever call startForeground()
. You are given a window of time to get around
to calling startForeground()
, "comparable to the ANR interval to do this".
If your work is longer than a millisecond but less than a few seconds,
you could skip the Notification
and the startForeground()
call. However,
you will get an error in LogCat:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.commonsware.myapplication, PID: 5991
android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1775)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
当然,如果你不介意简短的Notification
,欢迎你像 Android 期望的那样使用 startForeground()
,在这种情况下,您可以正常进行后台工作,尽管在用户的通知中显示了一个条目阴影.
Of course, if you do not mind having a Notification
briefly, you are welcome
to use startForeground()
as Android expects you to, in which case you can
do background work normally, albeit with an entry showing up in the user's notification
shade.
BroadcastReceiver
从 API 级别 11 开始提供 goAsync()
.这允许您接收器在主应用程序线程之外工作,这样你就可以摆脱IntentService
并将您的代码移动到 BroadcastReceiver
中.你仍然只有 ANR使用超时期限,但您不会占用主应用程序线.这比第一个解决方法要好,因为它具有相同的时间限制,但避免了令人讨厌的错误.但是,它确实需要一些数量返工.
BroadcastReceiver
has offered goAsync()
since API Level 11. This allows your
receiver to do work off the main application thread, so you could get rid of the
IntentService
entirely and move your code into the BroadcastReceiver
.
You still only have the ANR
timeout period to work with, but you will not be tying up your main application
thread. This is better than the first workaround, insofar as it has the same
time limitation but avoids the nasty error. However, it does require some amount
of rework.
如果您的工作需要超过几秒钟并且您想避免Notification
,你可以修改你的代码来实现一个 JobService
和使用 JobScheduler
.这有一个额外的好处,就是只给你控制何时满足其他标准(例如,有可用的互联网联系).然而,这不仅需要重写,而且 JobScheduler
仅适用于 Android 5.0+,因此如果您的 minSdkVersion
小于 21,您将需要在旧设备上使用其他解决方案.
If your work will take more than a few seconds and you want to avoid the
Notification
, you could modify your code to implement a JobService
and
work with JobScheduler
. This has the added advantage of only giving you
control when other criteria are met (e.g., there is a usable Internet
connection). However, not only does this require a rewrite, but JobScheduler
is only available on Android 5.0+, so if your minSdkVersion
is less than 21,
you will need some other solution on the older devices.
更新:Eugen Pechanec 指出JobIntentService
,这是一个有趣的 JobService
/IntentService
混搭.
UPDATE: Eugen Pechanec pointed out JobIntentService
,
which is an interesting JobService
/IntentService
mashup.
这篇关于带有 boot_completed 的运行时异常 Android O的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!