需求

有一个用户需要这样一个功能,要求是APP能在充电的时候自动进入APP的一个界面
我寻思着,这玩意用普通权限做不了呀,不过APP有root权限倒也无妨,于是便决定采用Service去做后台服务

问题

某天,在Bugly看到如下的错误报告

java.lang.IllegalStateException:Not allowed to start service Intent  app is in background uid UidRecord


提示我无法在后台启动这个服务
于是便开始着手解决这个问题

解决问题

使用startForegroundService()

根据不同的SDK版本采用不同的启动方案

  /*** 开启用户服务 需要在目标Service的 onCreate方法中加入startForeground(1, new Notication())** @param cls class* @param context 上下文*/public static void startUseService(Context context, Class cls) {Intent intent = new Intent(context, cls);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {context.startForegroundService(intent);} else {context.startService(intent);}}

解决方法:使用startForegroundService()

必须在5秒内调用该服务的 startForeground(int id, Notification notification) 方法,否则将停止服务并抛出 *android.app.RemoteServiceException:Context.startForegroundService() did not then call Service.startForeground()*异常。

Bad notification for startForeground

结果发现调用了**startForeground(int id, Notification notification)**依旧不起作用,提示

FATAL EXCEPTION: mainandroid.app.RemoteServiceException: Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x40 color=0x00000000 vis=PRIVATE)

解决方法 :自定义notification

Android 8.0 以上不能用空的通知了 , 必须自己创建通知通道

/** 启动前台服务 */private void startForeground() {Log.d(TAG, "startForeground: ");String channelId = null;// 8.0 以上需要特殊处理if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {channelId = createNotificationChannel("fuck.foreground", "ForegroundService");} else {channelId = "";}NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId);Notification notification =builder.setContentText("充电控制服务已启动!").setSmallIcon(R.mipmap.fuck).setPriority(PRIORITY_MIN).setCategory(Notification.CATEGORY_SERVICE).build();// 设置 ID 为 0 , 就不显示已通知了 , 但是 oom_adj 值会变成后台进程 11// 设置 ID 为 大于0 , 会在通知栏显示该前台服务startForeground(0, notification);}
/*** 创建通知通道** @param channelId* @param channelName* @return*/@RequiresApi(Build.VERSION_CODES.O)private String createNotificationChannel(String channelId, String channelName) {NotificationChannel chan =new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE);chan.setLightColor(Color.BLUE);chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);NotificationManager service =(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);service.createNotificationChannel(chan);return channelId;}

以为这样就可以在不弹出通知的情况下去启动前台服务

解决通知问题

由于上述的startForeground(0, notification)
会不显示通知,结果出现了新的问题

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

原来是转为了后台服务,前台服务启动了个寂寞
这个时候就必须使用startForeground(大于零, notification)
通知会影响到用户的体验,如何去避免呢

这个时候在网上看到有人在说可以删除管道的方式
本人实际测试并不能解决问题

失败方案1:

 NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);manager.cancel(1);

失败方案2

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {NotificationChannel channel = new NotificationChannel(channelId,"Channel for  notification",NotificationManager.IMPORTANCE_NONE);mNotificationManager.createNotificationChannel(channel);
}

会出现以下之类的问题,无法去操作前台服务的channel
Not allowed to delete channel fuck.foreground with a foreground service

解决方案 :stopForeground(true)

用定时线程池之类的去定一个延迟任务删除前台通知
由于通知发出是有延迟的,基本上在发出去之前删除掉,
可以实现调用了startForeground(???, notification)而又不会弹出通知消息烦恼用户的情况

 //    延迟2s删除前台通知executorService.schedule(() -> stopForeground(true), 2, TimeUnit.SECONDS);

就这样,问题愉快的解决了!

总结

  1. 使用startForegroundService(intent)并且在目标service中自己去创建notification
  2. 在自己创建的channel中去使用startForeground(大于零, notification)
  3. 如果需要没有通知,使用stopForeground(true)去停止前台服务

Android 后台启动startService()相关问题的解决相关推荐

  1. 如何在Android 10中从后台启动活动

    如何在Android 10中从后台启动活动? https://www.it1352.com/1922748.html 小米手机"后台弹出界面(允许应用在后台弹出界面)"权限问题解决 ...

  2. 一篇文章看明白 Android Service 启动过程

    Android - Service 启动过程 相关系列 一篇文章看明白 Android 系统启动时都干了什么 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制 一篇文章看明白 An ...

  3. android系统知识(8.0)---Android O 启动优化

    Android O 启动优化的一些思路 启动优化其实是一个比较大的命题,在一些特地的场景下,快速启动有比较强烈的需求,这篇博客主要简单的介绍一些在android O平台上的进行启动优化的思路与想法. ...

  4. Android 系统(215)---Android O_GO后台启动服务改动

    Android O_GO后台启动服务改动 Android O_GO后台启动服务改动 1. 问题现象 应用在适配Android O/GO的系统时,会发现后台启动不了服务,会报出如下异常,并强退: jav ...

  5. android启动画面白屏,Android app启动时黑屏或者白屏的原因及解决办法

    1.产生原因 其实显示黑屏或者白屏实属正常,这是因为还没加载到布局文件,就已经显示了window窗口背景,黑屏白屏就是window窗口背景. 示例: 2.解决办法 通过设置设置Style (1)设置背 ...

  6. Linux 启动jar项目相关命令(解决关闭Linux终端,程序自动停止问题)

    Linux 启动jar项目相关命令 序言 启动jar包命令相关问题及解决办法 问题描述 解决办法 结语 序言 开发中在服务器上部署项目避免不了的,无论是测试还是开发都会遇到要重启项目及部署项目,所以部 ...

  7. Android Q 限制后台启动Activity

    描述 Android Q限制在没有用户交互的情况下加载Activity.这一变化可以最大限度的减少对用户的打扰,保持用户对屏幕上所显示内容的可控性. 运行在Android Q上的APP仅在以下一种或多 ...

  8. android 10+从后台启动 Activity 的限制

    限制后台启动activity 如果未满足相关条件,则后台不允许启动activity,并会打印如下相关的log: // anything that has fallen through would cu ...

  9. Android 9.0 延时开机动画解决首次开机黑屏和去掉android正在启动的提示框

    1.概述 在9.0的系统产品rom定制化开发中,在一些产品中会出现在首次开机的时候,由于在开机动画播放完以后会出现几秒短暂的黑屏情况,然后进入默认Launcher,这在产品体验上 也是感觉到有点差,所 ...

最新文章

  1. ITOO4.1之缓存—分布式缓存Memcached学习(理论篇)
  2. 浅谈 JavaScriptCore
  3. Barracuda VS antelope
  4. 基于Azure Blob冷存储的数据压缩备份总结
  5. 分布式系统面试 - 常见问题
  6. tiptop 编译运行_putty终于让我的TIPTOP脱离虚拟机在64位上运行了。
  7. 女生学的计算机专业有前途吗,计算机专业好不好 女生学计算机有前途吗
  8. php inputcsv,php实现CSV文件导入和导出
  9. slf4j log4j logback关系详解和相关用法
  10. 《你不知道的JavaScript》整理(二)——this
  11. C盘总是满了,不想重装系统,不想扩充,C盘瘦身彻底解决
  12. python网络爬虫从入门到精通吕云翔pdf_Python 网络爬虫从入门到精通
  13. php环境安装教程,PHP运行环境配置与开发环境的配置(图文教程)
  14. 操作系统4————进程同步
  15. 设计模式--代理模式--深入理解动态代理
  16. 炬芯平台SPP私有协议调试
  17. 技术探讨之请教方舟编译器的十个问题
  18. 写一些生活的琐事(纯属发泄)
  19. 在pycharm中使用pyqt5
  20. 精选上万个(cc协议)游戏素材,一键下载

热门文章

  1. 判断一张图片是否是空白图
  2. java分子分母的加减乘除_加减乘除四则运算
  3. PHP5.3.5如何连接MSSql Server
  4. nRF24L01无线通信模块使用简介(接收端)
  5. Python识别身份证号码并检查是否合法(pysseract,dlib,opencv)
  6. 智能经济大局下,云智一体的“形胜”
  7. 双系统安装deepin20_记录一次Windows+Deepin双系统安装及简单优化
  8. 应用PCA算法提取特征脸,重构人脸图像,并利用SVM算法进行人脸识别
  9. js中国标准时间转换为yyyy-MM-dd
  10. eagle PCB软件使用心得