如何使用MediaSession.setMediaButtonReceiver(PendingIntent)恢复播放 [英] How to use MediaSession.setMediaButtonReceiver(PendingIntent) to resume playback

本文介绍了如何使用MediaSession.setMediaButtonReceiver(PendingIntent)恢复播放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在停止应用程序时单击耳机按钮从我的应用程序开始播放音乐。

I'm trying to be able to start music playback from my app when the headset buttons are clicked while my app is stopped.

我可以使用MediaSession.Callback onMediaButtonEvent()或现在不推荐使用的 registerMediaButtonEventReceiver()来监听媒体按钮,请单击我的应用程序正在播放音乐,但是如果我暂停音乐一分钟,同时我的活动和播放服务仍在运行,然后按耳机按钮,我将失去接收媒体按钮广播的功能。而是会打开Goog​​le即时。

I can use MediaSession.Callback onMediaButtonEvent() or the now deprecated registerMediaButtonEventReceiver() to listen for media button click WHILE my app is playing music, but if I pause the music for a minute, with my Activity and playback Service still running, and then I press the headset button, I see that I have lost the ability to receive the media button broadcast. Instead, Google Now opens.

我要尝试的是类似Google Play音乐之类的东西。即使应用程序完全停止运行,它也可以开始音乐播放...在后台没有任何服务。

What I'm trying to do is something like Google Play Music. It is able to start music playback even if the app is completely stopped...no services in the background.

我觉得 setMediaButtonReceiver()是用于此目的的一个,但我没有

I feel that setMediaButtonReceiver() is the one to use for this, but I've not been able to get it to work.


setMediaButtonReceiver(PendingIntent mbr)

Set媒体按钮接收器的待定意图,以允许在会话停止后重新开始播放。如果您的应用程序以此方式启动,那么ACTION_MEDIA_BUTTON意图将通过挂起的意图发送。

Set a pending intent for your media button receiver to allow restarting playback after the session has been stopped. If your app is started in this way an ACTION_MEDIA_BUTTON intent will be sent via the pending intent.

我的服务中包含以下代码段。

I have the following snippet in my Service.

PendingIntent pi = PendingIntent.getBroadcast(HeadsetService.this, 0, new Intent(HeadsetService.this, RemoteControlReceiver.class), 0);
mMediaSession.setMediaButtonReceiver(pi);

我的RemoteControlReceiver BroadcastReceiver已在清单中注册,但是当我按下按钮时没有收到广播。

My RemoteControlReceiver BroadcastReceiver is registered in the Manifest but I receive no broadcast when I press the button.

我还看到其他音乐播放器应用一旦停止播放大约一分钟,便失去了接收媒体按钮广播的能力。

I've also seen that other music player apps lose the ability to receive media button broadcasts once they've stopped playback for about minute.

任何想法我都可以拥有

预先感谢!

推荐答案

首先,对于区分 MediaSessionCompat 与任何服务(例如 MediaBrowserServiceCompat )非常重要。

First, it is important to distinct MediaSessionCompat from any service such as MediaBrowserServiceCompat.

MediaSessionCompat 正在与外部 MediaSessionStack 进行通信,该命令指示哪个应用将从外部 MediaSessionService获取媒体键命令。在API 26+上,密钥将发送到最后播放的应用程序。具有API<的设备26将首先查找活动的播放/缓冲会话,然后查找活动的会话,然后查找最后的播放会话。后者允许应用程序通过在不需要的时候保持 mMediaSesssion.isActive 标记来窃取焦点。有关优先级的更多详细信息,请参见官方指南

MediaSessionCompat is communicating with the external MediaSessionStack that dictates which app will get media key commands from external MediaSessionService. On API 26+ the key will be sent to the last playing app. Devices with API < 26 will first look for active playing/buffering session, then for active session and then for last playing session. The latter allows apps to 'steal' the focus by keeping the mMediaSesssion.isActive tag on when they shouldn't. More details about priority can be found in the official guide.

只要您的应用在某个时候设置 mMediaSesssion.isActive = true 并且最后一次播放,它将获得媒体密钥,除非 mMediaSession.release()被调用。后者将从 MediaSessionStack 中删除​​您的会话,因此您的会话将不再接收媒体密钥。这就是为什么一旦您不再希望用户继续播放视频或音乐时,调用 release()的重要性。还有一个警告:如果系统认为您的应用被杀死而不是正常结束,则该应用也将从 MediaSessionStack 中删除​​,这是有道理的,因为在服务中<在这种情况下不一定会调用code> onDestroy(),因此系统会为您释放会话。轻扫应用程序时可能会发生这种情况。我使用的解决方法是在使用主应用程序时将服务保持在前台,然后在接到服务中的 onTaskRemoved()调用后短暂延迟后结束服务

So as long as your app set mMediaSesssion.isActive = true at some point and was last playing, it will get media keys unless mMediaSession.release() was called. The latter removes your session from MediaSessionStack and thus will your session no longer receives media keys. That's why it is important to call release() once you no longer expect user to continue playing video or music. There is one more caveat: If system thinks your app was killed as opposed to ended gracefully, then the app is removed from MediaSessionStack as well, which makes sense, because in service onDestroy() is not necessarily called in such scenario and thus the system releases your session for you. This might happen when you swipe away the app. A workaround I use is to keep the service in foreground while the main app is in use and then end the service after a short delay upon receiving a call to onTaskRemoved() in service.

如果将 mMediaSession.release()放在 onDestroy中,则会在某个时刻发生()您的服务。该服务在不使用时会终止,否则会占用系统资源。因此,建议在 onStop()命令中或在刷掉应用程序或通知时结束它。在您的情况下,电源管理器可能会在闲置一段时间后终止您的服务。根据实现的不同,即使服务被销毁,播放器的某些部分仍可能工作。此外,由于服务不再处于前台,因此通知可能仍然存在。这可能会让您误以为该服务正在运行。尽管没有更多细节,但我无法真正说出您的情况到底出了什么问题。

The call to mMediaSession.release() will happen at some point if you put it in onDestroy() of your service. The service is expected to end when it is not being used, as otherwise it is taking system resources. Thus, it is recommended to end it in onStop() command or when swiping away app or notification. In your case it may happen that power manager killed your service after being inactive for some time. Depending on implementation the some parts of the player might still be working even if the service is destroyed. Also the notification might still be there, as the service is no longer in foreground. That might've fool you into thinking that the service was running. Though without more details, I cannot really say what exactly went wrong in your case.

另一个可能导致您的应用无法获取媒体密钥的原因是,如果您的清单没有正确配置。确保您的 BroadcaseReceiver 条目包含 android.intent.action.MEDIA_BUTTON 意向过滤器。

One additional cause that might prevent your app from getting media keys is if your manifest is not properly configured. Make sure that your BroadcaseReceiver entry includes android.intent.action.MEDIA_BUTTON intent filter.

另一个可能的错误是在服务或任何其他生命周期组件中初始化媒体密钥回调 MediaSessionCompat.Callback()。因此,如果该组件被破坏,则会迅速导致意外行为。

Another possible mistake is initializing your media key callback MediaSessionCompat.Callback() in the service or any other lifecycle component. Thus, if that component gets destroyed, it can quickly lead to unexpected behavior.

TLDR:

过滤您的 Logcat 用于 MediaSessionStack | MediaSessionService ,以确保您的应用获取媒体密钥。如果不是,则:

Filter your Logcat for MediaSessionStack|MediaSessionService to ensure that your app gets the media keys. If it doesn't, then:


  • 确保已设置 mMusicService.isActive = true (在例如在 onPlay()

  • 确保 mMusicService.release()不被称为

  • 确保清单正确设置

  • 确保系统不认为您的服务被杀死(例如,通过清除应用程序)而不是正常结束

  • ensure that mMusicService.isActive = true is set (in e.g. in onPlay())
  • ensure that mMusicService.release() is not called
  • ensure that your manifest is properly set
  • ensure that the system doesn't think your service was killed (e.g. by swiping away the app) as opposed to being ended gracefully

然后确保您的应用程序正确处理了媒体密钥。

Then make sure your app is handling media keys properly.


  • 如果是自定义接收器,则应该在那里。

  • 如果是 androidx.media.session.MediaButtonReceiver 它们应该位于 MediaControllerCompat.Callback()中,其状态不应取决于任何服务或生命周期组件

  • In case of custom receiver, they should be there.
  • In case of androidx.media.session.MediaButtonReceiver they should be in MediaControllerCompat.Callback() whose state should not depend on any service or lifecycle component

我写的答案比较笼统,因为这是一个古老的问题,其他人可能比OP受益更多。

I wrote the answer a little bit more general, since it is an old question and others might benefit from it more than the OP.

这篇关于如何使用MediaSession.setMediaButtonReceiver(PendingIntent)恢复播放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆