需求 有一个用户需要这样一个功能,要求是APP能在充电的时候自动进入APP的一个界面 我寻思着,这玩意用普通权限做不了呀,不过APP有root权限倒也无妨,于是便决定采用Service去做后台服务 问题 某天,在Bugly看到如下的错误报告
有一个用户需要这样一个功能,要求是APP能在充电的时候自动进入APP的一个界面
我寻思着,这玩意用普通权限做不了呀,不过APP有root权限倒也无妨,于是便决定采用Service去做后台服务
某天,在Bugly看到如下的错误报告
java.lang.IllegalStateException: Not allowed to start service Intent app is in background uid UidRecord
提示我无法在后台启动这个服务
于是便开始着手解决这个问题
根据不同的SDK版本采用不同的启动方案
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); } }
必须在5秒内调用该服务的 startForeground(int id, Notification notification) 方法,否则将停止服务并抛出 *Android.app.RemoteServiceException:Context.startForegroundService() did not then call Service.startForeground()*异常。
结果发现调用了**startForeground(int id, Notification notification)**依旧不起作用,提示
FATAL EXCEPTION: main android.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)
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); } @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
用定时线程池之类的去定一个延迟任务删除前台通知
由于通知发出是有延迟的,基本上在发出去之前删除掉,
可以实现调用了startForeground(???, notification)而又不会弹出通知消息烦恼用户的情况
// 延迟2s删除前台通知 executorService.schedule(() -> stopForeground(true), 2, TimeUnit.SECONDS);
就这样,问题愉快的解决了!
来源地址:https://blog.csdn.net/qq_29687271/article/details/128187571
--结束END--
本文标题: Android 后台启动startService()相关问题的解决
本文链接: https://www.lsjlt.com/news/372361.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-05-14
2024-05-14
2024-05-14
2024-05-14
2024-05-14
2024-05-14
2024-05-14
2024-05-14
2024-05-14
2024-05-14
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0