It's because of Android O bg services restrictions.
So now you need to call startForeground()
only for services that were started with startForegroundService()
and call it in first 5 seconds after service has been started.
Here is the guide - https://developer.android.com/about/versions/oreo/background#services
Like this:
//Start service:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(new Intent(this, YourService.class));
} else {
startService(new Intent(this, YourService.class));
}
Then create and show notification (with channel as supposed earlier):
private void createAndShowForegroundNotification(Service yourService, int notificationId) {
final NotificationCompat.Builder builder = getNotificationBuilder(yourService,
"com.example.your_app.notification.CHANNEL_ID_FOREGROUND", // Channel id
NotificationManagerCompat.IMPORTANCE_LOW); //Low importance prevent visual appearance for this notification channel on top
builder.setOngoing(true)
.setSmallIcon(R.drawable.small_icon)
.setContentTitle(yourService.getString(R.string.title))
.setContentText(yourService.getString(R.string.content));
Notification notification = builder.build();
yourService.startForeground(notificationId, notification);
if (notificationId != lastShownNotificationId) {
// Cancel previous notification
final NotificationManager nm = (NotificationManager) yourService.getSystemService(Activity.NOTIFICATION_SERVICE);
nm.cancel(lastShownNotificationId);
}
lastShownNotificationId = notificationId;
}
public static NotificationCompat.Builder getNotificationBuilder(Context context, String channelId, int importance) {
NotificationCompat.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
prepareChannel(context, channelId, importance);
builder = new NotificationCompat.Builder(context, channelId);
} else {
builder = new NotificationCompat.Builder(context);
}
return builder;
}
@TargetApi(26)
private static void prepareChannel(Context context, String id, int importance) {
final String appName = context.getString(R.string.app_name);
String description = context.getString(R.string.notifications_channel_description);
final NotificationManager nm = (NotificationManager) context.getSystemService(Activity.NOTIFICATION_SERVICE);
if(nm != null) {
NotificationChannel nChannel = nm.getNotificationChannel(id);
if (nChannel == null) {
nChannel = new NotificationChannel(id, appName, importance);
nChannel.setDescription(description);
nm.createNotificationChannel(nChannel);
}
}
}
Remember that your foreground notification will have the same state as your other notifications even if you'll use different channel ids, so it might be hidden as a group with others. Use different groups to avoid it.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…