У меня есть служба, которая слушает мультимедийные кнопки, но я хочу слушать их только во время работы моей службы, поскольку у меня есть кнопка в пользовательском интерфейсе для запуска / остановки службы.
Как я могу выполните следующие два действия:
- При запуске 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();
}
}