• QQ
  • nahooten@sina.com
  • 常州市九洲新世界花苑15-2

Android

Android 8.0 启动service error IllegalStateException: Not al

原创内容,转载请注明原文网址:http://homeqin.cn/a/wenzhangboke/jishutiandi/Android/2019/0615/541.html

 
 
 
安卓8.0手机线上报错:
 
 
 
java.lang.IllegalStateException:Fatal Exception thrown on Scheduler.
 
 
 
2io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.void run()(HandlerScheduler.java:111)
 
 
 
3......
 
 
 
4java.lang.IllegalStateException:Not allowed to start service Intent { cmp=com.xianglin.app/.biz.gold.service.StepService }: app is in background uid UidRecord{be88278 u0a36 SVC bg:+1m4s717ms idle procs:4 seq(0,0,0)}
 
 
 
5android.app.ContextImpl.startServiceCo妹妹on(ContextImpl.java:1701)
 
 
 
6android.app.ContextImpl.startService(ContextImpl.java:1657)
 
 
 
7android.content.ContextWrapper.startService(ContextWrapper.java:644)
 
 
 
8com.xianglin.app.utils.AppUtils.void setupService(android.content.Context)(AppUtils.java:479)
 
 
 
9com.xianglin.app.utils.net.NetStateChangeReceiver$1.void onSuccess(com.xianglin.appserv.co妹妹on.service.facade.model.vo.LoginVo)(NetStateChangeReceiver.java:195)
 
 
 
10com.xianglin.app.utils.net.NetStateChangeReceiver$1.void onSuccess(java.lang.Object)(NetStateChangeReceiver.java:191)
 
 
 
错误缘故:
 
Android 8.0 不再容许背景service干脆通过startService体例去启动, 具体举动变化如下:
 
 
 
要是针对 Android 8.0 的运用测试在不容许其建立背景服无的环境下应用 startService() 函数,则该函数将激励一个 IllegalStateException。 新的 Context.startForegroundService() 函数将启动一个前台服无。当今,即便运用在背景运转, 体系也容许其挪用 Context.startForegroundService()。不过,运用必需在建立服无后的五秒内挪用该服无的 startForeground() 函数。
 
 
 
办理要领:
 
1. 点窜启动体例
 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 
 
 
context.startForegroundService(intent);
 
 
 
} else {
 
 
 
context.startService(intent);
 
 
 
}
 
 
 
2. 而且在service里再挪用startForeground要领,不然就会出现ANR
 
 
 
?
 
1
 
context.startForeground(SERVICE_ID, builder.getNotification());
 
校验下版本,startForeground(1, new Notification())放在oncreate()里就行。
 
 
 
好了,题目办理。
 
 
 
最近发现P也出了,就起了个P的虚拟机,另有版本27 8.1体系,后果提醒
 
 
 
\
 
 
 
android O 以后每个Notification都必要倚赖一个channel,要不然就报错。那就加一个简单的channel
 
 
 
\
 
 
 
\
 
 
 
这里即是简单应用,并不做过量细化的操纵,具体可查阅NotificationChannel的用法,属性良多。
 
 
 
参考
 
https://stackoverflow.com/questions/46445265/android-8-0-java-lang-illegalstateexception-not-allowed-to-start-service-inten
 
 
 
https://developer.android.com/about/versions/oreo/background
 
 
 
Android O对运用在背景运转时可以执行的操纵施加了限制,称为背景执行限制(Background Execution Limits),这可以大大削减运用的内存应用和耗电量,进步用户体验。背景执行限制分为两个片面:背景服无限制(Background Service Limitations)、播送限制(BroadcastLimitations)。
 
背景服无限制
 
 
 
若何才算是背景运用?除了下面环境外都是背景运用
 
 
 
1.具备可见的Activity
 
 
 
2.具备前台服无
 
 
 
3.另一个前台运用已相关到该运用(通过bindService大概应用该运用的ContentProvider)。
 
 
 
当运用处于背景时:
 
 
 
1.在背景运转的服无在几分钟内会被stop掉(模拟器测试在1分钟左右后被kill掉)。在这段光阴内,运用仍可以建立和应用服无。
 
 
 
2.在运用处于背景几分钟后(模拟器测试1分钟左右),运用将不行再通过startService建立背景服无,要是建立则抛出以下最
 
 
 
?
 
1
 
Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.example.samsung.test/.TestService }: app is in background
 
运用处于背景时,固然不行通过startService建立背景服无,但仍可以通过下面的体例建立前台服无。
 
 
 
?
 
1
 
 
 
NotificationManager noti = (NotificationManager)getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
 
 
 
noti.startServiceInForeground();
 
 
 
背景服无会被kill掉,官方保举可应用AlarmManager、SyncAdapter、JobScheduler取代背景服无。
 
 
 
播送限制
 
 
 
要是运用监听少许体系播送,当体系发出播送时,良多运用都邑被唤醒,这会招致所有运用疾速地连续花消资源,从而低落用户体验。其实,大片面运用都不会处分这个播送,运用只是唤醒一下看看和本人是否相关,为了缓和这一题目,Android N对少许播送做出了限制:
 
 
 
1.targetSdkVersion为Android N(API level 24)及以上的运用,要是运用在AndroidManifest.xml中静态注册CONNECTIVITY_ACTION这个receiver,运用将不行收到此播送。要是运用应用Context.registerReceiver()动静注册receiver,运用仍可以收到这个播送。
 
 
 
2.运转在Android N及以上建筑的运用,无论是targetSdkVersion是否是Android N,运用都不行发送大概汲取ACTION_NEW_PICTURE和ACTION_NEW_VIDEO这两个播送。
 
 
 
在大无数环境下,运用都可以应用JobScheduler功课降服这些限制。 这种体例让运用放置为在未活跃运转时执行事情,不过仍能够使体系可以在不影响用户体验的环境下放置这些功课。
 
 
 
Android 8.0 提供针对JobScheduler的多个改进,让您可以更放松地应用决策功课取代服无和播送汲取器;如需打听细致信息,请参阅JobScheduler 改进。
 
 
 
而Android O执行了更为严格的限制。
 
 
 
1.动静注册的receiver,可汲取任何显式和隐式播送。
 
 
 
2.targetSdkVersion为Android O(API level 26)及以上的运用,静态注册的receiver将不行收到隐式播送,但可以收到显式播送。下面例子申明
 
 
 
清单文件的receiver申明
 
 
 
?
 
1
 
 
 
 
 
android:name=".TestReceiver"
 
 
 
android:enabled="true">
 
 
 
 
 
 
 
Receiver类定义
 
 
 
?
 
1
 
 
 
public class TestReceiver extends BroadcastReceiver {
 
 
 
@Override
 
 
 
public void onReceive(Context context, Intent intent) {
 
 
 
Toast.makeText(context, "onReceive", Toast.LENGTH_SHORT).show();
 
 
 
}
 
 
 
}
 
 
 
①要是如许发送隐式播送,receiver将汲取不到播送。
 
 
 
?
 
1
 
 
 
Intent intent = new Intent();
 
 
 
intent.setAction("com.test.example.testreceiver.action");
 
 
 
sendBroadcast(intent);
 
 
 
②要是如许发送显式播送,receiver仍可以汲取到播送
 
 
 
?
 
1
 
 
 
Intent intent = new Intent();
 
 
 
intent.setClassName("com.test.example.testreceiver", "com.test.example.testreceiver.TestReceiver");
 
 
 
sendBroadcast(intent);
 
 
 
固然静态注册的receiver不行汲取隐式播送,但Google考虑到少许播送也不频繁产生,也有少许例外,对这些例外的静态注册的receiver,仍可汲取隐式和显式播送。
 
 
 
ACTION_LOCKED_BOOT_COMPLETED、ACTION_BOOT_COMPLETED
 
 
 
ACTION_USER_INITIALIZE
 
 
 
ACTION_TIMEZONE_CHANGED
 
 
 
ACTION_LOCALE_CHANGED
 
 
 
ACTION_USB_ACCESSORY_ATTACHED
 
 
 
ACTION_USB_ACCESSORY_DETACHED
 
 
 
ACTION_USB_DEVICE_ATTACHED
 
 
 
ACTION_USB_DEVICE_DETACHED
 
 
 
ACTION_HEADSET_PLUG
 
 
 
……
 
 
 
细目请参考
 
 
 
https://developer.android.com/preview/features/background-broadcasts.html
 
 
 
据Google工程师吐露,Google的目标是填塞一次电,手机可用2~3天,这也可看到Google在手机续航方面的起劲。
 
 
 
当前惟有Android Studio2.4可以下载Android O 预览版SDK,下载地点
 
 
 
https://dl.谷歌.com/dl/android/studio/ide-zips/2.4.0.6/android-studio-ide-171.3934896-windows.zip
 
 
 
Android 8.0新特性-作废大片面静态注册播送
 
本日楼主在写一个播送的demo,功效最的简单,即是一个运用发送一个自定义的播送,同时在这个运用内部定义了一个播送接受者,而且在AndroidManifest文件中进行静态的注册。Demo看上去最的简单,不过在Android 8.0的建筑运转这个运用,永远不行汲取到这个发送出去的播送,感受最的蒙蔽。环节是,在Android 7.0的建筑是能够汲取到的!
 
 
 
1.缘故
 
 
 
看到这个环境,我就觉得不是我的代码题目,应该是Android 8.0相较于Android 8.0以前的建筑有所变更,因而Google了一把,公然被我找到了题目所在。在Google爸爸的Android官网找到了Android 8.0举动变化的先容,此中有一句说的是:
 
 
 
\
 
 
 
这句话的意思即是说,在Android 8.0的平台上,运用不行对大片面的播送进行静态注册,也即是说,不行在AndroidManifest文件对有些播送进行静态注册,这里必需夸大是有些播送,由于有些播送照旧能够注册的。好比,经过楼主测试,对汲取Android 开机的播送通过静态注册照旧能够平常汲取的。
 
 
 
Android 8.0举动变化的先容链接:https://developer.android.com/about/versions/oreo/android-8.0-changes.htmlhl=zh-cn,前面那个链接必需通过FQ,固然我们首倡科学上网,以是国内镜像网站链接:https://developer.android.谷歌.cn/about/versions/oreo/android-8.0.html。
 
 
 
2.办理办法
 
 
 
前面我们晓得了是甚么缘故招致的,只要晓得了缘故,办理办法就最轻易的想出来的。
 
 
 
我们晓得播送的注册体例分为两种:
 
 
 
A.静态注册,也即是说在AndroidManifest文件中对BroadcastReceiver进行注册,平时还会加上action用来过滤。
 
 
 
B.动静注册,挪用Context中的registerReceiver对播送进行动静注册,应用unRegisterReceiver要领对播送进行作废注册的操纵。
 
 
 
静态注册不行的话,那我们就动静注册啊!
 
 
 
3.代码
 
 
 
MainActivity文件的代码
 
 
 
 
 
 
 
?
 
1
 
2
 
3
 
4
 
5
 
6
 
7
 
8
 
9
 
10
 
11
 
12
 
13
 
14
 
15
 
16
 
17
 
18
 
19
 
20
 
21
 
22
 
23
 
24
 
25
 
26
 
27
 
28
 
29
 
30
 
31
 
32
 
33
 
34
 
35
 
36
 
37
 
38
 
1 public class MainActivity extends AppCompatActivity {
 
 2
 
 3  private Button mButton = null;
 
 4
 
 5  private IntentFilter mIntentFilter = null;
 
 6
 
 7  private MyBroadcastReceiver mMyBroadcastRecvier = null;
 
 8
 
 9
 
10  @Override
 
11  protected void onCreate(Bundle savedInstanceState) {
 
12super.onCreate(savedInstanceState);
 
13setContentView(R.layout.activity_main);
 
14
 
15//过滤器
 
16mIntentFilter = new IntentFilter("pby");
 
17//建立播送汲取者的工具
 
18mMyBroadcastRecvier =  new MyBroadcastReceiver();
 
19//注册播送汲取者的工具
 
20registerReceiver(mMyBroadcastRecvier, mIntentFilter);
 
21mButton = (Button) findViewById(R.id.id_button);
 
22mButton.setOnClickListener(new View.OnClickListener(){
 
23 @Override
 
24 public void onClick(View v) {
 
25  Intent intent = new Intent("pby");
 
26  //发送一个播送
 
27  sendBroadcast(intent);
 
28 }
 
29});
 
30  }
 
31
 
32  @Override
 
33  protected void onDestroy() {
 
34super.onDestroy();
 
35//作废播送汲取者的注册
 
36unregisterReceiver(mMyBroadcastRecvier);
 
37  }
 
38 }
 
 
 
 
 
MyBroadcastReceiver文件的代码
 
 
 
 
 
 
 
?
 
1
 
2
 
3
 
4
 
5
 
6
 
1 public class MyBroadcastReceiver extends BroadcastReceiver {
 
2  @Override
 
3  public void onReceive(Context context, Intent intent) {
 
4Toast.makeText(context, "收到了自定义的播送", Toast.LENGTH_LONG).show();
 
5  }
 
6 }
 
 
 
 
 
惟有上头的简单配置,没有点窜AndroidManifest文件中任何的代码
 

上篇:上一篇:修改ro属性的小工具新版本-170119
下篇:下一篇:Android 获取唯一机械码的代码