如何解决MediaSession架构中MediaPlayer和SeekBar之间的Android通信
我正在开发音频流应用程序。我已经按照android描述here的方式设计了我的应用。在我的应用程序中,我有一个活动MainActivity
,该活动根据所选功能加载片段。在其中一个片段中,我提供了一个ReplayPlayer
,供用户浏览流音频,播放/暂停流等。我找到了this,并设计了自己的应用, StreamService
控制着MediaPlayer
,因此我的应用程序的MediaPlayer
位于StreamService
。
问题是我正在尝试将SeekBar
中的ReplayPlayer
与MediaPlayer
中StreamService
中的媒体相关联。据我了解,MediabrowserService
无法绑定,与Service
不同,因此我无法访问currentPosition
中我的MediaPlayer的StreamService
。因此,我一直沉迷于如何从我的MediaPlayer
片段中访问此currentPosition
的{{1}}。
由于其他音乐播放器应用程序清楚地显示了歌曲中的当前位置,所以我觉得有一种方法可以实现我目前正在努力的目标。我该怎么办?
预先感谢您的帮助。
AndroidManifest.xml
ReplayPlayer
StreamService.java
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/TransparentTheme"
android:usesCleartextTraffic="true">
<activity android:name=".MainActivity" android:windowSoftInputMode="stateVisible|adjustResize"/>
<service android:name=".StreamService">
<intent-filter>
<action android:name="android.media.browse.MediabrowserService" />
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="android.media.browse.AUdio_BECOMING_NOISY" />
</intent-filter>
</service>
<receiver android:name="androidx.media.session.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="android.media.AUdio_BECOMING_NOISY" />
</intent-filter>
</receiver>
<activity android:name=".SplashActivity" android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
解决方法
您可以在服务端的MediaSessionCompat中发布MediaPlayer的位置更新,然后在片段中,您将在MediaControllerCompat.Callback的onPlaybackStateChanged(PlaybackStateCompat state)方法中接收播放状态更新。 使用处理程序定期发布MediaPlayer更新。像这样:
public void onPlay() {
if (!mMediaPlayer.isPlaying()) {
mMediaPlayer.start();
updateCurrentPosition();
}
}
public void onPause() {
super.onPause();
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder()
.setActions(PAUSE_ACTIONS)
.setState(PlaybackStateCompat.STATE_PAUSED,mMediaPlayer.getCurrentPosition(),0)
.build();
stopPlaybackStateUpdate();
}
}
private void updateCurrentPosition() {
if (mMediaPlayer == null) {
return;
}
handler.postDelayed(new Runnable() {
@Override
public void run() {
int currentPosition = mMediaPlayer.getCurrentPosition();
PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder()
.setActions(PLAYING_ACTIONS)
.setState(PlaybackStateCompat.STATE_PLAYING,currentPosition,1)
.build();
mMediaSession.setPlaybackState(playbackState);
updateCurrentPosition();
}
},1000);
}
private void stopPlaybackStateUpdate() {
if (handler != null) {
handler.removeCallbacksAndMessages(null);
}
}
您可以使用MediaSessionCompat.setMetadata(Metadata)设置媒体文件的总时长。
MediaMetadataCompat mediaMetadata = new MediaMetadataCompat.Builder()
.putString(MediaMetadata.METADATA_KEY_TITLE,"XYZ"))
.putLong(MediaMetadata.METADATA_KEY_DURATION,mMediaPlayer.getDuration())
.build();
然后,在您的“片段/活动”中,您可以使用MediaController.Callback中收到的“位置更新”来设置MediaPlayer当前位置的进度(即Seekbar.setProgress())。另外,请使用当前播放媒体的总时长来设置Seekbar.setMax。
private MediaControllerCompat.Callback mMediaControllerCallback =
new MediaControllerCompat.Callback() {
@Override
public void onMetadataChanged(MediaMetadataCompat metadata) {
super.onMetadataChanged(metadata);
int totalDuration = (int) metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION);
mSeekBar.setMax(totalDuration);
}
@Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {
mSeekBar.setMax(state.getPosition()); //You will receive MediaPlayer's current position every 1 second here.
}
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。