我在Android O操作系统上使用服务类。

我计划在后台使用服务。

Android文档指出

如果你的应用程序的API级别为26或更高,系统会对使用或创建后台服务施加限制,除非应用程序本身在前台。如果应用程序需要创建前台服务,应用程序应该调用startForegroundService()。

如果使用startForegroundService(),服务抛出以下错误。

Context.startForegroundService() did not then call
Service.startForeground() 

这有什么问题?


当前回答

以下是谷歌在Android 12上的行为变化:

To provide a streamlined experience for short-running foreground services on Android 12, the system can delay the display of foreground service notifications by 10 seconds for certain foreground services. This change gives short-lived tasks a chance to complete before their notifications appear.

解决方案:在onCreate()中为你使用的服务调用start前台()

其他回答

Android O API 26的问题

如果你立即停止服务(所以你的服务实际上并没有真正运行(措辞/理解),并且你在ANR间隔之下,你仍然需要在stopSelf之前调用start前台

https://plus.google.com/116630648530850689477/posts/L2rn4T6SAJ5

尝试了这种方法,但它仍然创建一个错误:-

if (Util.SDK_INT > 26) {
    mContext.startForegroundService(playIntent);
} else {
    mContext.startService(playIntent);
}

我正在使用这个,直到错误被解决

mContext.startService(playIntent);

如果你在调用service . start前台(…)之前调用Context.startForegroundService(…),然后再调用Context.stopService(…),你的应用程序会崩溃。

我这里有清晰的复制品前景服务api26

我在谷歌问题跟踪器上打开了一个bug

这方面的几个bug已经被打开和关闭不会修复。

希望我的与明确的复制步骤将使削减。

谷歌团队提供的信息

谷歌问题跟踪器评论36

这不是一个框架错误;这是故意的。如果应用程序使用startForegroundService()启动一个服务实例,它必须将该服务实例转换到前台状态并显示通知。如果服务实例在start前台()被调用之前就停止了,那么这个承诺就没有实现:这是应用程序中的一个bug。

re# 31,发布一个其他应用程序可以直接启动的服务从根本上来说是不安全的。您可以通过将该服务的所有启动操作都视为需要startForeground()来减轻这一点,尽管这显然不是您想要的。

谷歌问题跟踪器评论56

这里有几种不同的情况会导致相同的结果。

完全的语义问题是,用startForegroundService()启动一些东西,但忽略了通过startForeground()实际将其转换到前台,这只是一个语义问题。这被故意视为应用程序漏洞。在将服务转移到前台之前停止服务是应用程序错误。这是OP的关键,也是为什么这个问题被标记为“按预期工作”。

然而,也有关于这个问题的虚假检测的问题。这是一个真正的问题,尽管它是分开跟踪这个特殊的bug跟踪器问题。我们对抱怨不是充耳不闻。

我只是检查PendingIntent null或或不是之前调用 context.startForegroundService (service_intent)功能。

这对我很有用

PendingIntent pendingIntent=PendingIntent.getBroadcast(context,0,intent,PendingIntent.FLAG_NO_CREATE);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && pendingIntent==null){
            context.startForegroundService(service_intent);
        }
        else
        {
            context.startService(service_intent);
        }
}

我也面临着同样的问题,花时间找到了一个解决方案,你可以尝试下面的代码。如果你使用服务,然后把这段代码放在onCreate,否则你使用意图服务,然后把这段代码放在onHandleIntent。

if (Build.VERSION.SDK_INT >= 26) {
        String CHANNEL_ID = "my_app";
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                "MyApp", NotificationManager.IMPORTANCE_DEFAULT);
        ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("")
                .setContentText("").build();
        startForeground(1, notification);
    }

即使在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;
}

附注:如果服务没有运行,它将首先启动服务,这是一种开销。