Oreo - служба переднего плана не показывает уведомление переднего плана

Пока что я настроил свой код на использование 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);
}

Изменить

Мое уведомление создано таким образом, которое до сих пор работает на тысячах устройств 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();
}

person prom85    schedule 08.09.2017    source источник


Ответы (2)


Возможно, вам потребуется определить канал уведомлений для вашего приложения. Проверьте журнал, должно быть предупреждение. Ознакомьтесь с этим для ознакомления.

Приведу пример, это будет в котине. Сначала создайте такой класс. Вам нужно будет вызвать 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)
    }
}
person A. Shevchuk    schedule 08.09.2017
comment
Добавленная вами ссылка в любом случае неплохая, спасибо. Один вопрос: означает ли это изменение, что мне больше не нужно показывать уведомление для службы переднего плана в android oreo? Потому что люди сказали мне, что мое приложение работает на Android Oreo без уведомления ... - person prom85; 08.09.2017
comment
эхммм ... Вообще-то без уведомления работать не может. Фоновая работа не разрешена в android o без видимых компонентов, таких как активность или уведомление. Если вы запустите свою службу без видимых компонентов, система через некоторое время убьет ее. Таким образом, вам нужно уведомление для службы, если вы хотите выполнить фоновую работу. Если вам нужно запустить что-то в фоновом режиме с некоторым периодом - проверьте диспетчер заданий firebase. Это позволяет запускать запланированное обслуживание. - person A. Shevchuk; 08.09.2017
comment
У меня есть приложение боковой панели с элементами пользовательского интерфейса на WindowManager, и оно, похоже, работает с невидимым уведомлением, которое я использую до сих пор (невидимое уведомление - это уведомление без канала). Жалоб не поступало уже несколько дней. Эмулятор тоже не убивает мою службу в течении 5 секунд - person prom85; 08.09.2017
comment
@ prom85 ваш целевой api установлен на 26? - person A. Shevchuk; 08.09.2017
comment
Да, это так. Видимые компоненты в любом случае есть, даже два: один для наложения, который я рисую, и один для службы, работающей в фоновом режиме ... - person prom85; 08.09.2017
comment
Тогда это работает из-за вашего наложения. Но будьте осторожны в будущем с ограничениями фоновых работ. - person A. Shevchuk; 08.09.2017

Код на котлине

 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)
person code4rox    schedule 28.06.2018
comment
это не отвечает на вопрос - person Benjamin; 28.06.2018