奥利奥系统 - 前台服务未显示前台通知

27

到目前为止,我已经调整了我的代码以使用ContextCompat.startForegroundService(context, intentService);来启动我的服务。这种方法可以在Android < 26和Android 26(Oreo)上运行。

然而,在Android Oreo中,我仍然可以看到差异:我没有看到我的自定义前台通知(我只看到“应用正在后台运行”的通知)。我还需要进行任何调整吗?

我的服务看起来像这样:

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);
}

编辑

我的通知是这样创建的,在 API < 26 的成千上万个 Android 设备上都可以正常工作:

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();
}
3个回答

21

你可能需要为你的应用程序定义通知通道。检查日志,应该会有警告。请查看这里进行介绍。

我将给你一些示例,它们将使用 Kotlin 编写。首先,创建一个类像这样。你需要在应用程序启动时调用 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)
    }
}

那么你可以像这样使用实用工具

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)
    }
}

你添加的链接非常好,谢谢。不过我有一个问题:这个更改是否意味着在Android Oreo中我不必再为前台服务显示通知了?因为有人告诉我即使没有通知,我的应用程序也可以在Android Oreo上运行... - prom85
1
嗯...没有通知,它实际上不能工作。在Android O中,后台任务不允许没有可见的组件,例如活动或通知进行。如果您在没有可见组件的情况下运行服务,系统将在一段时间后终止它。因此,如果要执行后台作业,则需要使用通知来服务。 如果您需要定期在后台运行某些内容-您应该检查firebase job dispatcher。它允许您运行预定服务。 - A. Shevchuk
我有一个带有UI元素的侧边栏应用程序,它似乎也可以使用我现在使用的不可见通知(即没有通道的通知)正常工作。几天来没有收到任何投诉。模拟器也不会在5秒内终止我的服务。 - prom85
@prom85 你的目标 API 设置为26了吗? - A. Shevchuk
是的,没错。可见组件无论如何都在那里,甚至有两个:一个用于我绘制的覆盖层,另一个用于在后台运行的服务... - prom85
那是因为你的覆盖层起了作用。但是以后要注意背景工作的限制。 - A. Shevchuk

1

在 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)

不回答问题。 - Benjamin

0
  // 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);


            }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接