解决Android8.0之后开启service

2023-05-16

背景:

项目测试时发现的,在双击返回键关闭应用后(并未杀死后台)重新打开APP,其他手机都OK,但是8.0的手机会出现较频繁的crash。检查代码,问题锁定在重新开启应用时的startService()上。

查找资料说是Android 8.0 不再允许后台service直接通过startService方式去启动,否则就会引起IllegalStateException

原因

Android 8.0 有一项复杂功能;系统不允许后台应用创建后台服务。 因此,Android 8.0 引入了一种全新的方法,即 Context.startForegroundService(),以在前台启动新服务。 在系统创建服务后,应用有5秒的时间来调用该服务的 startForeground() 方法以显示新服务的用户可见通知。如果应用在此时间限制内未调用 startForeground(),则系统将停止服务并声明此应用为 ANR。

遇到的问题

但是目前在调用:context.startForegroundService(intent)时报如下ANR,startForegroundService()文档说明在service启动后要调用startForeground()。

android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()

完整解决步骤:

1. 添加权限

<!--android 9.0上使用前台服务,需要添加权限,此权限为级别为nomarl-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

2. 启动server(引用启动5秒内要启动server)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(new Intent(context, MyService.class));
    } else {
        context.startService(new Intent(context, MyService.class));
    }

然后必须在Myservice中调用startForeground():

3. Server中onCreate方法中调用startForeground()

public static final String CHANNEL_ID_STRING = "service_01";
private Notification notification;
    @Override
    public void onCreate() {
        super.onCreate();
        //适配8.0service
        NotificationManager notificationManager = (NotificationManager) MyApp.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
        NotificationChannel mChannel = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            mChannel = new NotificationChannel(CHANNEL_ID_STRING, getString(R.string.app_name),
                    NotificationManager.IMPORTANCE_LOW);
            notificationManager.createNotificationChannel(mChannel);
            notification = new Notification.Builder(getApplicationContext(), CHANNEL_ID_STRING).build();
            startForeground(1, notification);
        }
}

4. 在onStart里再次调用startForeground()

@Override
public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        startForeground(1, notification);
    }

}

注解:

  • Android 8.0 系统不允许后台应用创建后台服务,故只能使用Context.startForegroundService()启动服务
  • 创建服务后,应用必须在5秒内调用该服务的 startForeground() 显示一条可见通知,声明有服务在挂着,不然系统会停止服务 + ANR 套餐送上。
  • Notification 要加 Channel,系统的要求
  • 为什么要在onStart里再次调用startForeground()?答:这一条主要是针对后台保活的服务,如果在服务A运行期间,保活机制又startForegroundService启动了一次服务A,那么这样不会调用服务A的onCreate方法,只会调用onStart方法。如果不在onStart方法里再挂个通知的话,系统会认为你使用了 startForegroundService 却不在 5 秒内给通知,很傻地就停止服务 + ANR 套餐送上了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解决Android8.0之后开启service 的相关文章

随机推荐

  • java.lang.NoSuchMethodError: java.lang.reflect.Field.trySetAccessible()Z

    把jdk 设置成11 就可以了
  • ES6 模块

    概述 在 ES6 前 xff0c 实现模块化使用的是 RequireJS 或者 seaJS xff08 分别是基于 AMD 规范的模块化库 xff0c 和基于 CMD 规范的模块化库 xff09 ES6 引入了模块化 xff0c 其设计思想
  • jdk 8 、9 10 11 12 13 14和 jdk 1.8 什么关系?

    jdk 8 就是 jdk 1 8 jdk9 就是 jdk 1 9
  • android studio设置jdk版本项目设置和全局设置

    android studio设置jdk版本项目设置和全局设置 方法1 xff1a 修改项目的gradle构建jdk xff08 建议在使用别人的单个项目时使用 xff09 打开项目设置 打开jdk设置 选择jdk11 注意要apply保存然
  • Gradle:执行命令时指定 JDK 版本

    应用场景 在命令行执行 Gradle 时使用的 Gradle 版本为系统环境变量中指定的 Gradle 版本 xff0c 使用的 JDK 为系统环境变量 JAVA HOME 指定的 JDK 来自 Gradle 官网的说明 xff1a JAV
  • Java基础-方法区以及static的内存分配图

    什么是方法区 xff1a 方法区是系统分配的一个内存逻辑区域 xff0c 是JVM在装载类文件时 xff0c 用于存储类型信息的 类的描述信息 方法区存放的信息包括 xff1a 类的基本信息 xff1a 1 每个类的全限定名 2 每个类的直
  • AudioManager 蓝牙sco连接相关接口

    蓝牙耳机连接之后 xff0c 发现音频发声的还是终端 xff0c 并没有转换到蓝牙耳机发声 网上搜索相关资料 xff0c 发现是蓝牙耳机需要建立链路来播放音频 简单介绍下蓝牙耳机的两种链路 xff1a A2DP xff08 异步链路 xff
  • Android 音频源码分析——AudioTrack设备选择

    基于Andorid9 0源码 以AudioTrack为例 xff0c 梳理下输出设备选择流程 音频设备选择的影响因素 xff1a AudioAttributes 声音流类型 setForceUse 设置 setPreferredDevice
  • 音频输出设备的选择

    场景 xff1a 使用AudioTrack播放一段音频 xff0c streamtype是AUDIO STREAM MUSIC xff1b 跟踪音频输出设备选择的流程 xff0c 代码会走到这里 xff1a 1 frameworks av
  • Engine::getDeviceForStrategyInt()解析

    audio devices t是int类型 audio devices t Engine getDeviceForStrategyInt routing strategy strategy DeviceVector availableOut
  • AudioService之音频输出通道切换

    前言 xff1a 音频输出的方式有很多种 xff0c 外放即扬声器 xff08 Speaker xff09 听筒 xff08 Telephone Receiver xff09 有线耳机 xff08 WiredHeadset xff09 蓝牙
  • UML 用例图以及UML的八种关系

    首先 xff0c 一张总体的知识脉络导图献上 xff1a 一 什么是用例图 xff1f 用例图描述了一组用例 参与者以及它们之间的关系 使用阶段 xff1a 软件需求分析 使用者 xff1a 软件分析人员 软件开发人员 用例模型 xff1a
  • 清除浏览器缓存后,发现页面样式不能加载了

    清除浏览器缓存后 xff0c 发现页面样式不能加载了 这里需要注意一个springboot版本问题 xff1a Spring Boot 1 x和2 x版本拦截器对于静态资源访问的区别 xff01 Spring Boot 1 x版本已经做好了
  • UML时序图(Sequence Diagram)

    什么是时序图 时序图 Sequence Diagram xff0c 又名序列图 循序图 xff0c 是一种UML交互图 它通过描述对象之间发送消息的时间顺序显示多个对象之间的动态协作 让我们来看一看visio2016对时序图的的解释 时序图
  • UML流程图

    流程图介绍 流程图 xff08 FlowChart xff09 是描述我们进行某一项活动所遵循顺序的一种图示方法 它能通过图形符号形象的表示解决问题的步骤和程序 好的流程图 xff0c 不仅能对我们的程序设计起到作用 xff1b 在帮助理解
  • Android: 如何切换 SCO 链路

    最近在做蓝牙音箱开发 xff0c 在 A2DP 和 HFP 来回切换的时候 xff0c 遇到了手机兼容性的问题 最终发现设备收声和手机收声 xff0c 是因为 soc 切换有问题 原先在网上找了一些资料发现其实还蛮简单的 就两句话 xff0
  • Java 枚举(enum) 详解6种常见的用法

    用法一 xff1a 常量 在JDK1 5 之前 xff0c 我们定义常量都是 xff1a public static final 现在好了 xff0c 有了枚举 xff0c 可以把相关的常量分组到一个枚举类型里 xff0c 而且枚举提供了比
  • Android注解快速入门和实用解析

    首先什么是注解 xff1f 64 Override就是注解 xff0c 它的作用是 xff1a 1 检查是否正确的重写了父类中的方法 2 标明代码 xff0c 这是一个重写的方法 1 体现在于 xff1a 检查子类重写的方法名与参数类型是否
  • Android高版本Service在后台一分钟被杀死

    最近公司出现了一个Bug xff0c Service在后台写log时候一分钟左右被杀死 xff0c 或者运行一会就被杀死了 xff0c 上网搜了一下原来是Android高版本为了保护电量 xff0c 流量什么的 xff0c 会在后台杀死这些
  • 解决Android8.0之后开启service

    背景 项目测试时发现的 xff0c 在双击返回键关闭应用后 xff08 并未杀死后台 xff09 重新打开APP xff0c 其他手机都OK xff0c 但是8 0的手机会出现较频繁的crash 检查代码 xff0c 问题锁定在重新开启应用