Oreo - 前台服务不显示前台通知
Oreo - Foreground service does not show foreground notification
到目前为止,我已将我的代码调整为使用 ContextCompat.startForegroundService(context, intentService);
来启动我的服务。这样,它也适用于 android < 26 和 android 26 (Oreo)。
我仍然看到差异,在 android oreo 中我没有看到我的自定义前台通知(我只看到 "app is running in the background" 通知)。我还需要在那里进行任何调整吗?
我的服务是这样的:
public class BaseOverlayService extends Service {
@Override
public void onCreate() {
super.onCreate();
moveToForeground();
}
private void moveToForeground() {
Notification notification = ...;
super.startForeground(NOTIFICATION_ID, notification);
}
}
官方示例
此示例 (https://github.com/googlesamples/android-play-location/blob/master/LocationUpdatesForegroundService/app/src/main/java/com/google/android/gms/location/sample/locationupdatesforegroundservice/LocationUpdatesService.java#L200) 显示为注释,我应该使用以下内容,但 startServiceInForeground
不存在...
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
NotificationManager mNotificationManager = ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));
mNotificationManager.startServiceInForeground(new Intent(this, BaseOverlayService.class), NOTIFICATION_ID, notification);
} else {
startForeground(NOTIFICATION_ID, notification);
}
编辑
我的通知是这样创建的,到目前为止,它正在 android API < 26 的设备上工作:
protected Notification foregroundNotification(int notificationId)
{
boolean paused = MainApp.getPrefs().sidebarServicePaused();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.icon_not);
builder.setContentIntent(notificationIntent());
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon));
builder.setContentTitle(getString(R.string.derived_app_name));
builder.setContentText(getString(checkStatus() ? (paused ? R.string.service_notification_text_paused : R.string.service_notification_text_running) : R.string.service_notification_text_preparing));
builder.setColor(Color.parseColor("#25baa2"));
if (MainApp.getPrefs().hideNotificationIcon())
builder.setPriority(NotificationCompat.PRIORITY_MIN);
else
builder.setPriority(NotificationCompat.PRIORITY_MAX);
if (paused)
builder.addAction(R.drawable.ic_play_arrow_black_24dp, getString(R.string.resume), resumeIntent(this));
else
builder.addAction(R.drawable.ic_pause_black_24dp, getString(R.string.pause), pauseIntent(this));
return builder.build();
}
您可能需要为您的应用定义通知渠道。查看日志,应该有warning。
检查this以获取介绍
我给你举个例子,它会在 kotin 中。
首先,像这样制作一个 class 。您需要在应用程序开始时调用 createMainNotificationChannel() 一次。
class NotificationManager(private val context: Context) {
companion object {
private val CHANNEL_ID = "YOUR_CHANNEL_ID"
private val CHANNEL_NAME = "Your human readable notification channel name"
private val CHANNEL_DESCRIPTION = "description"
}
@RequiresApi(Build.VERSION_CODES.O)
fun getMainNotificationId(): String {
return CHANNEL_ID
}
@RequiresApi(Build.VERSION_CODES.O)
fun createMainNotificationChannel() {
val id = CHANNEL_ID
val name = CHANNEL_NAME
val description = CHANNEL_DESCRIPTION
val importance = android.app.NotificationManager.IMPORTANCE_LOW
val mChannel = NotificationChannel(id, name, importance)
mChannel.description = description
mChannel.enableLights(true)
mChannel.lightColor = Color.RED
mChannel.enableVibration(true)
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager
mNotificationManager.createNotificationChannel(mChannel)
}
}
然后你就可以像这样使用util
fun createNotificationCompatBuilder(context: Context): NotificationCompat.Builder {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return NotificationCompat.Builder(context, NotificationManager(context).mainNotificationId)
} else {
return NotificationCompat.Builder(context)
}
}
kotlin 中的代码
private fun customNotification(title: String,notificationID: Int) {
val intent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0 /* request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val builder = NotificationCompat.Builder(this, title)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentText("Notification description")
.setSmallIcon(R.drawable.ic_mark_map)
.setContentIntent(pendingIntent)
.setOnlyAlertOnce(true)
val mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(title,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT)
mNotificationManager.createNotificationChannel(channel)
}
val notification = builder.build()
startForeground(notificationID, notification)
}
使用:
customNotification("Title",101)
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
getString(R.string.app_name),
NotificationManager.IMPORTANCE_HIGH);
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
channel.setDescription(data.get("body"));
channel.enableLights(true);
channel.enableVibration(true);
channel.setSound(SoundUri, attributes); // This is IMPORTANT
notificationManager.createNotificationChannel(channel);
}
到目前为止,我已将我的代码调整为使用 ContextCompat.startForegroundService(context, intentService);
来启动我的服务。这样,它也适用于 android < 26 和 android 26 (Oreo)。
我仍然看到差异,在 android oreo 中我没有看到我的自定义前台通知(我只看到 "app is running in the background" 通知)。我还需要在那里进行任何调整吗?
我的服务是这样的:
public class BaseOverlayService extends Service {
@Override
public void onCreate() {
super.onCreate();
moveToForeground();
}
private void moveToForeground() {
Notification notification = ...;
super.startForeground(NOTIFICATION_ID, notification);
}
}
官方示例
此示例 (https://github.com/googlesamples/android-play-location/blob/master/LocationUpdatesForegroundService/app/src/main/java/com/google/android/gms/location/sample/locationupdatesforegroundservice/LocationUpdatesService.java#L200) 显示为注释,我应该使用以下内容,但 startServiceInForeground
不存在...
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
NotificationManager mNotificationManager = ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));
mNotificationManager.startServiceInForeground(new Intent(this, BaseOverlayService.class), NOTIFICATION_ID, notification);
} else {
startForeground(NOTIFICATION_ID, notification);
}
编辑
我的通知是这样创建的,到目前为止,它正在 android API < 26 的设备上工作:
protected Notification foregroundNotification(int notificationId)
{
boolean paused = MainApp.getPrefs().sidebarServicePaused();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.icon_not);
builder.setContentIntent(notificationIntent());
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon));
builder.setContentTitle(getString(R.string.derived_app_name));
builder.setContentText(getString(checkStatus() ? (paused ? R.string.service_notification_text_paused : R.string.service_notification_text_running) : R.string.service_notification_text_preparing));
builder.setColor(Color.parseColor("#25baa2"));
if (MainApp.getPrefs().hideNotificationIcon())
builder.setPriority(NotificationCompat.PRIORITY_MIN);
else
builder.setPriority(NotificationCompat.PRIORITY_MAX);
if (paused)
builder.addAction(R.drawable.ic_play_arrow_black_24dp, getString(R.string.resume), resumeIntent(this));
else
builder.addAction(R.drawable.ic_pause_black_24dp, getString(R.string.pause), pauseIntent(this));
return builder.build();
}
您可能需要为您的应用定义通知渠道。查看日志,应该有warning。 检查this以获取介绍
我给你举个例子,它会在 kotin 中。 首先,像这样制作一个 class 。您需要在应用程序开始时调用 createMainNotificationChannel() 一次。
class NotificationManager(private val context: Context) {
companion object {
private val CHANNEL_ID = "YOUR_CHANNEL_ID"
private val CHANNEL_NAME = "Your human readable notification channel name"
private val CHANNEL_DESCRIPTION = "description"
}
@RequiresApi(Build.VERSION_CODES.O)
fun getMainNotificationId(): String {
return CHANNEL_ID
}
@RequiresApi(Build.VERSION_CODES.O)
fun createMainNotificationChannel() {
val id = CHANNEL_ID
val name = CHANNEL_NAME
val description = CHANNEL_DESCRIPTION
val importance = android.app.NotificationManager.IMPORTANCE_LOW
val mChannel = NotificationChannel(id, name, importance)
mChannel.description = description
mChannel.enableLights(true)
mChannel.lightColor = Color.RED
mChannel.enableVibration(true)
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager
mNotificationManager.createNotificationChannel(mChannel)
}
}
然后你就可以像这样使用util
fun createNotificationCompatBuilder(context: Context): NotificationCompat.Builder {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return NotificationCompat.Builder(context, NotificationManager(context).mainNotificationId)
} else {
return NotificationCompat.Builder(context)
}
}
kotlin 中的代码
private fun customNotification(title: String,notificationID: Int) {
val intent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0 /* request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val builder = NotificationCompat.Builder(this, title)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentText("Notification description")
.setSmallIcon(R.drawable.ic_mark_map)
.setContentIntent(pendingIntent)
.setOnlyAlertOnce(true)
val mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(title,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT)
mNotificationManager.createNotificationChannel(channel)
}
val notification = builder.build()
startForeground(notificationID, notification)
}
使用:
customNotification("Title",101)
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
getString(R.string.app_name),
NotificationManager.IMPORTANCE_HIGH);
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
channel.setDescription(data.get("body"));
channel.enableLights(true);
channel.enableVibration(true);
channel.setSound(SoundUri, attributes); // This is IMPORTANT
notificationManager.createNotificationChannel(channel);
}