- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想将我的 exoplayer 实现与媒体 session 对象连接起来。我设置了一个 SimpleExoPlayerView 来显示视频。每次单击按钮时,我都希望触发媒体 session 回调。我只能在使用耳机之类的东西时触发回调。 App中使用的代码写在下面
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void setUp(LifecycleOwner lifecycleOwner){
// Create a MediaSessionCompat
Log.i("Hoe8", "lco setup called");
mMediaSession = new MediaSessionCompat(activity, "this");
// Enable callbacks from MediaButtons and TransportControls
mMediaSession.setFlags(
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
// Do not let MediaButtons restart the player when the app is not visible
mMediaSession.setMediaButtonReceiver(null);
// Set an initial PlaybackState with ACTION_PLAY, so media buttons can start the player
mStateBuilder = new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY |
PlaybackStateCompat.ACTION_PLAY_PAUSE);
mMediaSession.setPlaybackState(mStateBuilder.build());
// MySessionCallback has methods that handle callbacks from a media controller
mMediaSession.setCallback(new MediaSessionCompat.Callback() {
@Override
public void onPlay() {
super.onPlay();
Log.i("Hoe8", "MediaSession callback play called");
mMediaSession.setActive(true);
((JokesAdapter.VideoPostViewHolder) rv).setIsPlaying(true);
((JokesAdapter.VideoPostViewHolder) rv).setHasStarted(true);
}
@Override
public void onPause() {
super.onPause();
((JokesAdapter.VideoPostViewHolder) rv).setIsPlaying(false);
}
@Override
public void onStop() {
super.onStop();
mMediaSession.setActive(false);
((JokesAdapter.VideoPostViewHolder) rv).setIsPlaying(false);
((JokesAdapter.VideoPostViewHolder) rv).setHasStarted(false);
}
});
// Create a MediaControllerCompat
MediaControllerCompat mediaController =
new MediaControllerCompat(activity, mMediaSession);
MediaControllerCompat.setMediaController(activity, mediaController);
//Handler mainHandler = new Handler();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
new DefaultTrackSelector(videoTrackSelectionFactory);
// 2. Create the player
player = ExoPlayerFactory.newSimpleInstance(activity, trackSelector);
playerView.setPlayer(player);
MediaSessionConnector mediaSessionConnector =
new MediaSessionConnector(mMediaSession);
mediaSessionConnector.setPlayer(player, null,null );
}
对代码做了一些修改
public class VideoLifeCyclerObserver implements LifecycleObserver {
MediaSessionCompat mMediaSession;
PlaybackStateCompat.Builder mStateBuilder;
AppCompatActivity activity;
SimpleExoPlayerView playerView;
SimpleExoPlayer player;
ExoPlayer.ExoPlayerComponent rv;
MediaSessionConnector mediaSessionConnector;
public VideoLifeCyclerObserver(AppCompatActivity activity, SimpleExoPlayerView playerView, ExoPlayer.ExoPlayerComponent rv){
this.activity = activity;
this.playerView = playerView;
this.activity.getLifecycle().addObserver(this);
this.rv = rv;
Log.i("Hoe8","video lco created");
}
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void setUp(LifecycleOwner lifecycleOwner){
// Create a MediaSessionCompat
Log.i("Hoe8", "lco setup called");
mMediaSession = new MediaSessionCompat(activity, "this");
// Create a MediaControllerCompat
MediaControllerCompat mediaController =
new MediaControllerCompat(activity, mMediaSession);
MediaControllerCompat.setMediaController(activity, mediaController);
mediaSessionConnector =
new MediaSessionConnector(mMediaSession, new PlayBackController());
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void startPlayer(LifecycleOwner lifecycleOwner){
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
new DefaultTrackSelector(videoTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(activity, trackSelector);
playerView.setPlayer(player);
mediaSessionConnector.setPlayer(player, null,null );
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void tearDown(LifecycleOwner lifecycleOwner){
player.stop();
player.release();
player.sendMessages(new ExoPlayer.ExoPlayerMessage(rv,1,player.getContentPosition()));
}
public class PlayBackController extends DefaultPlaybackController{
@Override
public void onPause(Player player) {
Log.i("Hoe8", "onPause called");
((JokesAdapter.VideoPostViewHolder) rv).setIsPlaying(false);
super.onPause(player);
}
@Override
public void onPlay(Player player) {
Log.i("Hoe8", "MediaSession callback play called 2");
mMediaSession.setActive(true);
((JokesAdapter.VideoPostViewHolder) rv).setIsPlaying(true);
((JokesAdapter.VideoPostViewHolder) rv).setHasStarted(true);
super.onPlay(player);
}
@Override
public void onStop(Player player) {
Log.i("Hoe8", "onStop called");
mMediaSession.setActive(false);
((JokesAdapter.VideoPostViewHolder) rv).setIsPlaying(false);
((JokesAdapter.VideoPostViewHolder) rv).setHasStarted(false);
super.onStop(player);
}
}
}
如何让 SimpleExoPlayerView 中显示的按钮触发媒体 session 回调?
最佳答案
简而言之:
从(含)开始删除 onCreate 中的所有代码
//启用来自 MediaButtons 和 TransportControls 的回调
到(不包括)
//创建一个 MediaControllerCompat
:)
更冗长:
我建议通过监听播放器的状态转换而不是通过点击按钮来触发媒体 session 回调。这使您无需为与播放器交互的每个 UI 元素执行此操作。这实际上就是 MediaSessionConnector 为您所做的。
使用 MediaSessionConnector,您无需自己操作 MediaSession。连接器在播放器实例和媒体 session 之间进行调解。这意味着连接器会监听播放器的状态转换并将播放器状态映射到媒体 session 状态。连接器还监听传输控件发送的媒体操作,并将它们委托(delegate)给播放器或您的应用程序。注意:您的应用不需要提供 MediaSessionCompat.Callback,连接器会自行注册(并覆盖您的,因为每个 session 只能有一个)。
通常:您的应用仅与 SimpleExoPlayer 实例交互,而连接器将播放器状态映射到 session 。
让我们从基本方法开始,它将播放器的状态映射到触发适当的 MediaControllerCompat.Callback 方法的 session :
// code running in a activity or service where (this instanceof Context)
mediaSession = new MediaSessionCompat(this, getPackageName());
mediaSessionConnector = new MediaSessionConnector(mediaSession)
mediaSessionConnector.setPlayer(player, null, null);
mediaSession.setActive(true);
您现在可以像以前一样准备和使用播放器,例如调用 setPlayWhenReady(true|false)、seekTo(t) 并且连接器维护广播到 session Controller 的 PlaybackStateCompat。
连接器确实在此级别接收并实现了一些媒体操作(不需要您自己的 MediaSession.Callback):
PlaybackStateCompat.ACTION_PLAY_PAUSE |
PlaybackStateCompat.ACTION_PLAY |
PlaybackStateCompat.ACTION_PAUSE |
PlaybackStateCompat.ACTION_STOP |
PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE |
PlaybackStateCompat.ACTION_SET_REPEAT_MODE;
PlayFromXYZ 操作
您可能希望支持其他媒体操作,例如 ACTION_PLAY_FROM_MEDIA_ID。您可以通过提供您的 PlaybackPreparer 来做到这一点:
playbackPreparer = new YourPlaybackPreparer();
mediaSessionConnector.setPlayer(player, playbackPreparer, null);
连接器现在将 ACTION_PLAY_FROM_MEDIA_ID 或 ACTION_PREPARE_FROM_MEDIA_ID 等操作委托(delegate)给您的播放准备器,它为给定的媒体 ID 创建一个 MediaSource 以准备播放器。
元数据和队列管理
同样有趣的是能够将播放器的时间轴直接映射到媒体 session 的队列和元数据。为此,您可以提供 QueueNavigator .有摘要TimelineQueueNavigator由扩展程序提供:
QueueNavigator queueNavigator = new TimelineQueueNavigator(mediaSession) {
@Override
public MediaDescriptionCompat getMediaDescription(int windowIndex) {
// implement this method and read from your backing data:
getMediaDescriptionAtQueuePosition(windowIndex):
return mediaDescription;
}
}
mediaSessionConnector.setQueueNavigator(queueNavigator);
有了这个媒体 Controller 现在可以读取 session 的元数据和队列。队列表示播放器的当前时间轴, session 的元数据描述当前正在播放的时间轴中的窗口。 (more about playlists)。
提供一个 TimelineQueueNavigator,连接器监听传输控件发送的 ACTION_SKIP_TO_NEXT、ACTION_SKIP_TO_PREVIOUS 和 ACTION_SKIP_TO_QUEUE_ITEM,并相应地沿着时间线导航。
生命周期集成
请注意,您必须在onStart/onResume 上创建播放器实例并在onPause/onStop 上释放它。这可确保您与其他应用程序共享的编解码器资源在您处于后台时得到释放。您的代码示例只在 onCreate 上执行一次,这不是好的公民:)。 See how the ExoPlayer demo app does it .
关于android - 将 exoplayer 与 MediaSessionCompat 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48046882/
我无法导入 MediaSessionCompat。用于导入整个 android.support.v4.media 库的导入语句不会出现在 Android Studio“IntelliSense”中,并
如何使用 MediaSessionCompat?有人可以举一个简单的工作示例吗? 我找到了一些,但他们使用: MediaSessionCompat _mediaSession = new MediaS
将支持库升级到 25.3.1 后遇到此崩溃: Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual me
mediaSessionCompat.setMetadata(new MediaMetadataCompat.Builder() .putStr
我很好奇是否有人遇到过这个问题或有任何建议。我正在编写一个使用 MediaSessionCompat API 的媒体播放器。每隔一段时间,我都会确定播放媒体的当前位置并引发更改事件。我重新设置了播放状
我在使用 Android 的 MediaSession 时遇到了一些困难。 我一直在研究应该从 url 流式传输的原型(prototype) radio 应用程序。 到目前为止,我已经将它与前台服务一
我对 MediaControllerCompat 和 MediaSessionCompat 的导入 import android.support.v4.media.session.MediaContr
社区同胞! 所以我的应用程序遇到问题,那就是使用 MediaSessionCompat。 该崩溃问题仅出现在 Android 8 版本(8.1 也有)上,但主要出现在不同设备上的 8.0.0 上。 致
对于 Lollipop ,我们被告知要更换 registerMediaButtonEventReceiver() 与 setMediaButtonReceiver(PendingIntent)。 这在
我想用一个使用 MediaSession 的新类替换我应用程序中的 android RemoteControlClient 类,但它不适用于 API 级别 < 21,MediaSessionCompa
我想将我的 exoplayer 实现与媒体 session 对象连接起来。我设置了一个 SimpleExoPlayerView 来显示视频。每次单击按钮时,我都希望触发媒体 session 回调。我只
当我尝试在运行 Android 5.0.1 的 HUAWEI P8 lite 设备上显示通知时,我的应用程序崩溃(它在 Nexus 和三星设备上运行良好)。我的大部分代码取自 Ian Lake 的视频
我有一个应用程序可以从服务中复制网络广播(使用 AACDecoder 库)并在 Activity 未恢复时在简单的持续通知中显示正在播放的内容。我想要的是通过 NotificationCompat.M
我正在尝试在 Android 中实现通知播放器。我关注了this实现这一目标的指南。但是,作为我的要求,我需要在后台通知播放器中实现“跳到下一个”和“跳到上一个”。 到目前为止,MediaSessio
我正在尝试将我的应用程序更新到 Android SDK 31,但我遇到了 MediaSessionCompat 的问题。 我有一个扩展 MediaBrowserServiceCompat() 的 Me
我是一名优秀的程序员,十分优秀!