原创内容,转载请注明原文网址: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 获取唯一机械码的代码