Android 8 получение сообщений о прекращении приема событий мультимедийных кнопок - PullRequest
0 голосов
/ 03 февраля 2020

У меня есть служба, которая слушает мультимедийные кнопки, но я хочу слушать их только во время работы моей службы, поскольку у меня есть кнопка в пользовательском интерфейсе для запуска / остановки службы.

Как я могу выполните следующие два действия:

  • При запуске MyService начните получать события мультимедийных кнопок в com.myApp / MyService.
  • В конце MyService прекратите получать события мультимедийных кнопок в com .myApp / MyService.

Связаны следующие журналы:

D MediaSessionService: Sending KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_HEADSETHOOK, scanCode=226, metaState=0, flags=0x8, repeatCount=0, eventTime=13258317, downTime=13258317, deviceId=4, source=0x101 } to com.myApp/MyService (userId=0)

Примечание:

  • Я обнаружил, что могу начать получать носители события после того, как мое приложение начало воспроизводить аудио. Это, однако, не идеально, так как я не хочу воспроизводить аудио в своем приложении. (Я использую только мультимедийные события для запуска распознавания голоса)
  • После воспроизведения звука мой сервис, по-видимому, является медиа-ресивером по умолчанию. Это означает, что при нажатии кнопки мультимедиа мой сервис создается, ничего не делает и уничтожается. Это не идеальное поведение для конечного пользователя, поскольку мое приложение «крадет» эти события, которые потенциально могут быть обработаны чем-то другим.
  • Переопределение OnStartCommand() в моем сервисе не помогает
  • Вызов SetMediaButtonReceiver на MediaSession также не помогает
  • Использование BroadcastReceiver с намерением "android .intent.action.MEDIA_BUTTON", зарегистрированным в AudioManager, также не работает

Соответствующий код (в C#, я на Xamarin.Forms, но это не должно влиять на способ достижения этого)

public class MediaSessionCompatCallback : MediaSessionCompat.Callback
{
    public Func<Intent, bool> MediaButtonEvent { get; set; }
    public override bool OnMediaButtonEvent(Intent mediaButtonEvent) => MediaButtonEvent?.Invoke(mediaButtonEvent) ?? false;
}

[Service(Exported = true, Enabled = true)]
[IntentFilter(new[] { ServiceInterface })]
public class MediaBrowserService : MediaBrowserServiceCompat, AudioManager.IOnAudioFocusChangeListener
{
    private MediaSessionCompat mediaSession;
    private MediaSessionCompatCallback mediaSessionCallback;

    private void CreateMediaSessionCallback()
    {
        mediaSessionCallback = new MediaSessionCompatCallback()
        {
            MediaButtonEvent = OnMediaButtonEvent
        };
    }

    private void SetupMediaSession()
    {
        CreateMediaSessionCallback();

        var stateBuilder = new PlaybackStateCompat.Builder().SetActions(PlaybackStateCompat.ActionPlay | PlaybackStateCompat.ActionPlayPause);

        mediaSession = new MediaSessionCompat(this, nameof(MediaBrowserService));
        mediaSession.SetFlags(MediaSessionCompat.FlagHandlesMediaButtons | MediaSessionCompat.FlagHandlesTransportControls);
        mediaSession.SetPlaybackState(stateBuilder.Build());
        mediaSession.SetCallback(mediaSessionCallback);
        mediaSession.Active = true;

        SessionToken = mediaSession.SessionToken;
    }

    private void BuildNotification() { [...] }

    public override void OnCreate()
    {
        base.OnCreate();

        SetupMediaSession();
        StartForeground(135, BuildNotification());
        ContextCompat.StartForegroundService(ApplicationContext, new Intent(ApplicationContext, Java.Lang.Class.FromType(typeof(MediaBrowserService))));
    }

    public override void OnDestroy()
    {
        base.OnDestroy();

        if (mediaSession != null)
        {
            mediaSession.Active = false;
            mediaSession.SetCallback(null);
            mediaSession.Release();
            mediaSession.Dispose();
            mediaSession = null;
        }

        if (mediaSessionCallback != null)
        {
            mediaSessionCallback.Dispose();
            mediaSessionCallback = null;
        }

        StopForeground(true);
        StopSelf();
    }
}
...