Отмена уведомлений Android, когда система автоматически убивает систему - PullRequest
6 голосов
/ 16 марта 2019

У меня есть приложение, которое реализует MediaBrowserServiceCompat. При воспроизведении музыки она запускается на переднем плане с уведомлением управления мультимедиа, что система делает недопустимым. Когда пауза, это выходит из переднего плана, и уведомление сохраняется. Стандартный материал.

Когда эта служба автоматически убивается системой, уведомление не удаляется.

Вы можете смоделировать это, переведя приложение в состояние без паузы переднего плана, выйдя из приложения и выполнив следующую команду:

adb shell am kill com.myapp.package

Уведомление остается. Вы получаете это сообщение Logcat:

W/ActivityManager: Scheduling restart of crashed service com.myapp.package/com.myapp.package.playback.platform.AndroidMediaService

Ни один из очевидных хуков (например, onDestroy, onTaskRemoved и т. Д.) В сервисе, похоже, не вызывается - похоже, он полностью убит. Поскольку служба запускается с START_NOT_STICKY, мы также не получаем onCreate для нового экземпляра.

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

Другие приложения, похоже, не имеют проблем с этим.

Повторите этот сценарий (пауза, выход из приложения) и выполните команды, например, в Google Play Music:

adb shell am kill com.google.android.music

или Spotify:

adb shell am kill com.spotify.music

и вы обнаружите, что их уведомления немедленно исчезают, как если бы они были отменены при демонтаже.

Что они могут сделать, чтобы это произошло?

Ответы [ 3 ]

3 голосов
/ 18 марта 2019

Я понял ответ на этот вопрос, и это была, конечно, моя собственная вина. Нет ничего особенного в том, что делают другие приложения, - это поведение платформы, и мы оказались в стороне.

Я запоздало обнаружил, что при переходе от переднего плана к фону мы вызывали:

ServiceCompat.stopForeground(service, ServiceCompat.STOP_FOREGROUND_DETACH)

Я обнаружил это через dumpsys, например ::10000 *

adb shell dumpsys activity services com.google.android.music

и я нашел некоторые отличия.

Мое приложение:

ServiceRecord{294309d u0 com.myapp.debug/com.myapp.playback.platform.AndroidMediaService}
    intent={cmp=com.myapp.debug/com.myapp.playback.platform.AndroidMediaService}
    packageName=com.myapp.debug
    processName=com.myapp.debug:main
    baseDir=/data/app/com.myapp.debug-GM-nBaeXA_e47EmJKnM27g==/base.apk
    dataDir=/data/user/0/com.myapp.debug
    app=ProcessRecord{83fb4ffd0 23567:com.myapp.debug:main/u0a381}
    createTime=-27s211ms startingBgTimeout=--
    lastActivity=-26s911ms restartTime=-27s211ms createdFromFg=true
    startRequested=true delayedStop=false stopIfKilled=true callStart=true lastStartId=2

Воспроизведение музыки:

ServiceRecord{8693ccb u0 com.google.android.music/.playback2.MusicPlaybackService}
    intent={cmp=com.google.android.music/.playback2.MusicPlaybackService}
    packageName=com.google.android.music
    processName=com.google.android.music:main
    baseDir=/data/app/com.google.android.music-lrn1VQr_3_RDi5PMbqozdw==/base.apk
    dataDir=/data/user/0/com.google.android.music
    app=ProcessRecord{9a3c417d0 22921:com.google.android.music:main/u0a191}
    isForeground=false foregroundId=1 foregroundNoti=Notification(channel=playback_v1 pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x2 color=0xffff5722 category=transport actions=5 vis=PUBLIC semFlags=0x0 semPriority=0 semMissedCount=0)
    createTime=-9m33s792ms startingBgTimeout=--
    lastActivity=-20s825ms restartTime=-9m33s792ms createdFromFg=true
    startRequested=true delayedStop=false stopIfKilled=false callStart=true lastStartId=1

Вы можете увидеть отсутствующий атрибут foregroundNoti в журналах моего приложения. Это продукт отрыва вызова. Мы решили сделать это в какой-то момент давно, чтобы система не собирала уведомления. Поразмыслив, мы должны были позволить его убить, как и в других приложениях.

0 голосов
/ 18 марта 2019

Вы должны установить приоритет уведомления "НИЗКИЙ" , а в методе уничтожения службы вы можете вручную удалить уведомление по приведенному ниже коду,

 notificationManager.cancelAll();
0 голосов
/ 18 марта 2019

Попробуйте добавить этот флаг в манифест, чтобы остановить службу с приложением, когда оно будет убито:

<service
    ...
    android:stopWithTask="true"/>

Если оно не удаляет уведомление, установка его в false должна вызвать обратный вызов в службе, где вы сможете удалить уведомление

@Override 
public void onTaskRemoved(Intent rootIntent) {
    ...
}

Кроме того, этот ответ может быть связан.

Обновление

Поскольку вышеприведенное не сработало, я посмотрел, как в манифесте объявлено нативное приложение Music, и они не используют то, что я предложил. То, что они используют, и это может быть связано, это

<service
   ...
   android:process=":main" />

во всех сервисах, а также в приемниках, которые меняют уведомления. Стоит попробовать.

...