我在Android O操作系统上使用服务类。
我计划在后台使用服务。
Android文档指出
如果你的应用程序的API级别为26或更高,系统会对使用或创建后台服务施加限制,除非应用程序本身在前台。如果应用程序需要创建前台服务,应用程序应该调用startForegroundService()。
如果使用startForegroundService(),服务抛出以下错误。
Context.startForegroundService() did not then call
Service.startForeground()
这有什么问题?
即使在Service中调用start前台之后,如果我们在onCreate调用之前调用stopService,它也会在某些设备上崩溃。
所以,我通过启动附加标志的服务来修复这个问题:
Intent intent = new Intent(context, YourService.class);
intent.putExtra("request_stop", true);
context.startService(intent);
并在onStartCommand中添加了一个检查,看看它是否已经开始停止:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//call startForeground first
if (intent != null) {
boolean stopService = intent.getBooleanExtra("request_stop", false);
if (stopService) {
stopSelf();
}
}
//Continue with the background task
return START_STICKY;
}
附注:如果服务没有运行,它将首先启动服务,这是一种开销。
即使在Service中调用start前台之后,如果我们在onCreate调用之前调用stopService,它也会在某些设备上崩溃。
所以,我通过启动附加标志的服务来修复这个问题:
Intent intent = new Intent(context, YourService.class);
intent.putExtra("request_stop", true);
context.startService(intent);
并在onStartCommand中添加了一个检查,看看它是否已经开始停止:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//call startForeground first
if (intent != null) {
boolean stopService = intent.getBooleanExtra("request_stop", false);
if (stopService) {
stopSelf();
}
}
//Continue with the background task
return START_STICKY;
}
附注:如果服务没有运行,它将首先启动服务,这是一种开销。
https://developer.android.com/reference/android/content/Context.html startForegroundService (android.content.Intent)
类似于startService(Intent),但是有一个隐含的承诺
Service将调用start前台(int, android.app.Notification)一次
它开始运行。该服务被赋予了相当的时间
到ANR区间做这个,否则系统会
自动停止服务并声明应用程序ANR。
与普通的startService(Intent)不同,这个方法可以在
任何时候,不管托管服务的应用程序是否在
前景的国家。
一定要打电话给服务处。在onCreate()上的start前台(int, android.app.Notification),所以你确保它将被调用..如果你有任何条件,可能会阻止你这样做,那么你最好使用正常的Context.startService(意图)并调用服务。start前台(int, android.app.Notification)你自己。
似乎Context.startForegroundService()添加了一个看门狗来确保你调用了服务。start前台(int, android.app.Notification)在它被销毁之前…
我有一个小部件,当设备处于清醒状态时,它会相对频繁地进行更新,我在短短几天内就看到了数千次崩溃。
问题触发
我甚至在我的Pixel 3 XL上也注意到了这个问题,而我本以为这款设备负载并不大。所有代码路径都被startForeground()覆盖。但后来我意识到,在很多情况下,我的服务可以很快地完成工作。我认为触发我的应用程序的原因是,在系统真正抽出时间显示通知之前,服务已经结束。
解决方案/解决方案
我摆脱了所有的崩溃。我所做的就是删除对stopSelf()的调用。(我正在考虑延迟停止,直到我非常确定通知被显示,但我不希望用户看到通知,如果它不是必要的。)当服务空闲一分钟或系统正常销毁它而不抛出任何异常时。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopForeground(true);
} else {
stopSelf();
}