Android 前台服务崩溃RemoteServiceException

发布于:2022-12-19 ⋅ 阅读:(1078) ⋅ 点赞:(0)

RemoteServiceException

查询分析Bugly上面的异常崩溃,发现这个bug导致的崩溃率占所有崩溃中的77%,影响次数率0.2%,是个崩溃率相当高的bug。

一、分析

1、根据服务的特性可以知道,在8.0以后,启动服务需要启动前台服务

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(intent);
            Log.i("ForgroundService","startForegroundService!!");
        } else {
            startService(intent);
        }

在service中需要启动

 startForeground(1, mBuilder.build());  //id不为0

2、初步判断可能是有些地方启动服务时,没有针对8.0以上版本做适配,全局搜索后发现所有启动服务的地方都做了适配,因此排除这个可能

3、再次到bugly找日志信息,发现除了Context.startForegroundService() did not then call Service.startForeground()这句有用信息外,没有其它异常信息可以帮助到。继续查看崩溃的机型,发现某些特定机型,崩溃率比较高。但在本地环境中还是无法复现

4、网上寻找答案,突然看到这句有用信息
在这里插入图片描述
看到这句“there is a delay between the startForegroundService() call and when the service actually starts” 服务启动是有延迟的,看到这里感觉看到bug有复现之法了。

5、查看bugly崩溃发生的时间,一般应用启动的8秒内,因此怀疑是在初始化的时候,发生的。查看Application。有一处启动服务的调用,看着都挺正常。只是启动服务的时候是放在各种初始化的靠前位置,因此我在所有初始化调用后,睡眠了三秒。崩溃复现!!!在这里插入图片描述
6、后续自己写了小demo,直接就是启动服务,然后等待5秒,服务的onCreate 和onStartCommand都是等待结束后才开始执行。

Intent intent = new Intent().setClass(this, ForgroundService.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(intent);
            Log.i("ForgroundService","startForegroundService!!");
        } else {
            startService(intent);
        }
        try {
            Thread.sleep(5000);
        }catch (Exception e){

        }

Service代码

	@Override
    public void onCreate() {
        super.onCreate();
        Log.i("ForgroundService","onCreate service");
    }
	@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand ..");

        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext()).setAutoCancel(true);// 点击后让通知将消失
        mBuilder.setContentText("测试");
        mBuilder.setContentTitle("测试");
        mBuilder.setSmallIcon(R.mipmap.ic_launcher);
        mBuilder.setWhen(System.currentTimeMillis());//通知产生的时间,会在通知信息里显示
        mBuilder.setPriority(Notification.PRIORITY_DEFAULT);//设置该通知优先级
        mBuilder.setOngoing(false);//ture,设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
        mBuilder.setDefaults(Notification.DEFAULT_ALL);//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置,使用defaults属性,可以组合:

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            String channelId = "channelId" + System.currentTimeMillis();
            NotificationChannel channel = new NotificationChannel(channelId, getResources().getString(R.string.app_name), NotificationManager.IMPORTANCE_HIGH);
            manager.createNotificationChannel(channel);
            mBuilder.setChannelId(channelId);
        }
        mBuilder.setContentIntent(null);
        startForeground(222, mBuilder.build());
        Log.i("ForgroundService","onStartCommand service forground is running!!!");


        return super.onStartCommand(intent, flags, startId);
    }

7、原因定位到了,就是启动服务后,后续还有耗时操作,导致前台服务无法在调用了startForegroundService后无法在5秒内调用startForground,因此导致崩溃。
8、对于服务的启动顺序和流程,可以参考
https://blog.csdn.net/itrenj/article/details/110007831

ps:测试在11系统上该bug不会复现,官方应该已经修复


网站公告

今日签到

点亮在社区的每一天
去签到