startService
能够很便利的发动一个service
服务,也能够运转在独自的进程。
但是如果在后台调用了startService
,则很可能会抛出一个崩溃。
Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.test.broadservice/.MyService }: app is in background uid UidRecord{b67c471 u0a86 RCVR idle change:uncached procs:1 seq(0,0,0)}
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 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1661)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
过错原因
Android8.0
之后,体系增加了对后台Service
的约束,如果运用处于后台,调用startService
会抛出IllegalStateException
。
意思是,在后台的运用,不允许调用startService
发动一个后台服务,否则就会抛出反常。
解决办法
1. 运用startForegroundService
运用办法比较简单,这儿就不列出代码了。
有几点需求注意:
- 用此办法发动前台服务,会在用户的告诉栏上显示
- 必须在
5s
内调用服务的startForeground
办法,否则会发生ANR
2. 运用JobScheduler
运用JobScheduler能够完成在后台运转使命。
界说一个JobService:
public class MyJobService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}
onStartJob
:
- 运转在主进程,需求避免履行耗时的操作。
- 回来true:表明使命还在继续履行
- 回来false:表明使命已履行完
- 履行完之后,能够调jobFinished办法来告诉体系使命已完结。
onStopJob
:
- 当条件不满足的时分,会回调这个办法。
- 回来true:表明条件满足时,再次履行使命
- 回来false:表明使命完全完毕
注册JobService
:
<service
android:name=".MyJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
界说一个JobInfo
:
JobInfo.Builder builder = new JobInfo.Builder(111, new ComponentName(this, MyJobService.class));
// todo 设置使命的参数
将使命发布给体系:
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(builder.build());
3. 运用WorkManager
WorkManager
是JobScheduler
的升级版本,且支撑多进程,能够将使命运转到独自的进程中。详细运用办法能够参考之前的文章:运用退出后继续运转后台使命,来试试WorkManager吧!
总结
Android 8.0
版本以上,在后台调用startService
会抛出IllegalStateException
反常,需求改用其他的方法来运用。
常用的办法有如下三种:
-
startForegroundService
: 这种方法会在用户的告诉栏显示UI。 -
JobScheduler
:能够完成后台无感知运转使命。 -
WorkManager
:Jetpack
里的库,JobScheduler
的升级版,支撑多进程。