添加播放列表数据

This commit is contained in:
litingting 2024-09-25 19:00:03 +08:00
parent 96eecd07e7
commit 0f54dc33fb
16 changed files with 407 additions and 152 deletions

View File

@ -38,7 +38,7 @@ android {
dependencies { dependencies {
implementation("androidx.appcompat:appcompat:1.7.0") implementation("androidx.appcompat:appcompat:1.7.0")
implementation("com.google.android.material:material:1.12.0") implementation("com.google.android.material:material:1.11.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4") implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.activity:activity:1.9.1") implementation("androidx.activity:activity:1.9.1")
testImplementation("junit:junit:4.13.2") testImplementation("junit:junit:4.13.2")

View File

@ -4,6 +4,9 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" /> android:maxSdkVersion="32" />
@ -28,12 +31,11 @@
android:exported="false" /> android:exported="false" />
<activity <activity
android:name=".ui.activity.PlayActivity" android:name=".ui.activity.PlayActivity"
android:screenOrientation="portrait"
android:exported="false" /> android:exported="false" />
<activity <activity
android:name=".ui.activity.HomeActivity" android:name=".ui.activity.HomeActivity"
android:exported="false" /> android:screenOrientation="portrait"
<activity
android:name=".ui.activity.A_HomeActivity"
android:exported="true" > android:exported="true" >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -41,6 +43,11 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".ui.activity.A_HomeActivity"
android:exported="false" >
</activity>
<activity <activity
android:name=".ui.activity.MainActivity" android:name=".ui.activity.MainActivity"
android:exported="false" /> android:exported="false" />

View File

@ -3,6 +3,10 @@ package com.hi.music.player;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import com.hi.music.player.api.MediaControllerStatusListener;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.media3.MyMediaControllerManager;
public class MusicApplication extends Application { public class MusicApplication extends Application {
// private final static MusicApplication sInstance = new MusicApplication(); // private final static MusicApplication sInstance = new MusicApplication();
@ -19,5 +23,11 @@ public class MusicApplication extends Application {
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
myApplication = this; myApplication = this;
MyMediaControllerManager.getInstance().init(new MediaControllerStatusListener() {
@Override
public void onMediaControllerComplete(boolean isOk) {
CommonUtils.LogMsg("=-----mediaController+" + isOk);
}
});
} }
} }

View File

@ -3,7 +3,6 @@ package com.hi.music.player.api;
public interface MediaControllerListener { public interface MediaControllerListener {
void onMediaControllerComplete(boolean isOk);
void onPlayStatus(int playStatus); void onPlayStatus(int playStatus);
} }

View File

@ -0,0 +1,9 @@
package com.hi.music.player.api;
public interface MediaControllerStatusListener {
void onMediaControllerComplete(boolean isOk);
}

View File

@ -3,5 +3,8 @@ package com.hi.music.player.helper;
public class MyValue { public class MyValue {
//-----------------------------PlayActivity //-----------------------------PlayActivity
public static String KEY_PLAY_ACTIVITY_SINGER = "click_singer"; public static String KEY_PLAY_ACTIVITY_SINGER = "click_singer";
//播放错误
public static int PLAY_STATUS_CODE = -1;
//-----------------------------PlayActivity //-----------------------------PlayActivity
} }

View File

@ -29,6 +29,20 @@ public class ResponsePlayListInfo {
private String params; private String params;
private String musicVideoType; private String musicVideoType;
//------------自定义属性由另外接口请求返回的数据流组装
private String audioUrlLow;
private String audioUrlMedium;
public long getDurationMs() { public long getDurationMs() {
return DurationMs; return DurationMs;
} }
@ -116,4 +130,21 @@ public class ResponsePlayListInfo {
public void setMusicVideoType(String musicVideoType) { public void setMusicVideoType(String musicVideoType) {
this.musicVideoType = musicVideoType; this.musicVideoType = musicVideoType;
} }
public String getAudioUrlLow() {
return audioUrlLow;
}
public void setAudioUrlLow(String audioUrlLow) {
this.audioUrlLow = audioUrlLow;
}
public String getAudioUrlMedium() {
return audioUrlMedium;
}
public void setAudioUrlMedium(String audioUrlMedium) {
this.audioUrlMedium = audioUrlMedium;
}
} }

View File

@ -15,7 +15,9 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
import com.hi.music.player.MusicApplication; import com.hi.music.player.MusicApplication;
import com.hi.music.player.api.MediaControllerListener; import com.hi.music.player.api.MediaControllerListener;
import com.hi.music.player.api.MediaControllerStatusListener;
import com.hi.music.player.helper.CommonUtils; import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.helper.MyValue;
import com.hi.music.player.javabean.response.ResponsePlayListInfo; import com.hi.music.player.javabean.response.ResponsePlayListInfo;
import com.hi.music.player.javabean.response.ResponsePlayUrl; import com.hi.music.player.javabean.response.ResponsePlayUrl;
import com.hi.music.player.network.RetrofitManager; import com.hi.music.player.network.RetrofitManager;
@ -29,6 +31,7 @@ public class MyMediaControllerManager {
private static volatile MyMediaControllerManager myMediaControllerManagerInstance; private static volatile MyMediaControllerManager myMediaControllerManagerInstance;
private MediaController mediaController; private MediaController mediaController;
public static MyMediaControllerManager getInstance() { public static MyMediaControllerManager getInstance() {
if (myMediaControllerManagerInstance == null) { if (myMediaControllerManagerInstance == null) {
synchronized (RetrofitManager.class) { synchronized (RetrofitManager.class) {
@ -40,7 +43,7 @@ public class MyMediaControllerManager {
return myMediaControllerManagerInstance; return myMediaControllerManagerInstance;
} }
public void init(MediaControllerListener mediaControllerListener){ public void init(MediaControllerStatusListener statusListener) {
SessionToken sessionToken = SessionToken sessionToken =
new SessionToken(MusicApplication.myApplication, new ComponentName(MusicApplication.myApplication, PlaybackService.class)); new SessionToken(MusicApplication.myApplication, new ComponentName(MusicApplication.myApplication, PlaybackService.class));
ListenableFuture<MediaController> controllerFuture = ListenableFuture<MediaController> controllerFuture =
@ -52,35 +55,52 @@ public class MyMediaControllerManager {
// playerView.setPlayer(controllerFuture.get()); // playerView.setPlayer(controllerFuture.get());
try { try {
mediaController = controllerFuture.get(); mediaController = controllerFuture.get();
mediaController.addListener(new Player.Listener() {
@Override
public void onPlayerError(PlaybackException error) {
CommonUtils.LogMsg("=-----PlaybackException+"+error.getMessage());
}
@Override statusListener.onMediaControllerComplete(true);
public void onPlaybackStateChanged(int playbackState) { CommonUtils.LogMsg("=-----mediaController+" + mediaController);
CommonUtils.LogMsg("=-----playbackState+"+playbackState);
mediaControllerListener.onPlayStatus(playbackState);
}
@Override
public void onPositionDiscontinuity(Player.PositionInfo oldPosition, Player.PositionInfo newPosition, int reason) {
// 快进快退等操作
CommonUtils.LogMsg("=-----newPosition+"+newPosition.positionMs);
// mediaControllerListener.onPlayStatus(playbackState);
}
});
mediaControllerListener.onMediaControllerComplete(true);
CommonUtils.LogMsg("=-----mediaController+"+mediaController);
} catch (ExecutionException | InterruptedException e) { } catch (ExecutionException | InterruptedException e) {
CommonUtils.LogErrorMsg(e.getMessage()); CommonUtils.LogErrorMsg(e.getMessage());
mediaControllerListener.onMediaControllerComplete(false); statusListener.onMediaControllerComplete(false);
} }
}, MoreExecutors.directExecutor()); }, MoreExecutors.directExecutor());
}
public void addListener(MediaControllerListener listener) {
mediaController.addListener(new Player.Listener() {
@Override
public void onPlayerError(PlaybackException error) {
CommonUtils.LogMsg("=-----PlaybackException+" + error.getMessage());
listener.onPlayStatus(MyValue.PLAY_STATUS_CODE);
}
@Override
public void onIsPlayingChanged(boolean isPlaying) {
CommonUtils.LogMsg("-----onIsPlayingChanged+" + isPlaying);
if (isPlaying) {
// 播放器开始播放
System.out.println("Playback started!");
} else {
// 播放器暂停或停止
System.out.println("Playback paused or stopped.");
}
}
@Override
public void onPlaybackStateChanged(int playbackState) {
listener.onPlayStatus(playbackState);
}
@Override
public void onPositionDiscontinuity(Player.PositionInfo oldPosition, Player.PositionInfo newPosition, int reason) {
// 快进快退等操作
CommonUtils.LogMsg("=-----快进、快退+" + newPosition.positionMs);
// mediaControllerListener.onPlayStatus(playbackState);
}
});
} }
public MediaController getMediaController() { public MediaController getMediaController() {
@ -89,37 +109,105 @@ public class MyMediaControllerManager {
public long getContentPos() { public long getContentPos() {
if (mediaController == null) return 0;
return mediaController.getContentPosition(); return mediaController.getContentPosition();
} }
public long getBufferPos() {
if (mediaController == null) return 0;
return mediaController.getBufferedPosition();
}
/**
* 更新播放列表中的音频url
*
* @param playUrl
*/
@OptIn(markerClass = UnstableApi.class) @OptIn(markerClass = UnstableApi.class)
public void addMusicPlay(ResponsePlayListInfo playInfo, ResponsePlayUrl responsePlay){ public void UpdateAudioUrl(ResponsePlayUrl playUrl) {
List<MediaItem> mediaItems = new ArrayList<>(); for (int i = 0; i < mediaController.getMediaItemCount(); i++) {
MediaItem.Builder builder = new MediaItem.Builder(); MediaItem mediaItemAt = mediaController.getMediaItemAt(i);
if(responsePlay.getAudioUrlMedium()!= null){ if (mediaItemAt.mediaId.equals(playUrl.getVideoId())) {
builder.setUri(responsePlay.getAudioUrlMedium()); MediaItem.Builder builder = mediaItemAt.buildUpon();
}else { if (playUrl.getAudioUrlMedium() != null) {
builder.setUri(responsePlay.getAudioUrlLow()); builder.setUri(playUrl.getAudioUrlMedium());
} else {
builder.setUri(playUrl.getAudioUrlLow());
}
mediaController.setMediaItem(builder.build(), i);
CharSequence title = mediaController.getMediaItemAt(i).mediaMetadata.title;
CommonUtils.LogMsg("-------------更新播放列表中的音频url= i=" + i + "---title=" + title);
break;
}
} }
}
// @OptIn(markerClass = UnstableApi.class)
// public void addMusicPlay(ResponsePlayListInfo playInfo, ResponsePlayUrl responsePlay) {
// List<MediaItem> mediaItems = new ArrayList<>();
// MediaItem.Builder builder = new MediaItem.Builder();
// if (responsePlay.getAudioUrlMedium() != null) {
// builder.setUri(responsePlay.getAudioUrlMedium());
// } else {
// builder.setUri(responsePlay.getAudioUrlLow());
// }
//
// //唯一标识符
// builder.setMediaId(responsePlay.getVideoId());
//
// MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
//
// MediaMetadata_builder.setArtist(playInfo.getSingerName());
// MediaMetadata_builder.setDurationMs(playInfo.getDurationMs());
// MediaMetadata_builder.setAlbumArtist(playInfo.getCovert());
// MediaMetadata_builder.setTitle(playInfo.getSongTitle());
//// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
// builder.setMediaMetadata(MediaMetadata_builder.build());
//
// mediaItems.add(builder.build());
// mediaController.addMediaItems(mediaItems);
// mediaController.prepare();
//
// }
builder.setMediaId(responsePlay.getVideoId());
MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
MediaMetadata_builder.setArtist(playInfo.getSingerName()); /**
// MediaMetadata_builder.setDurationMs( ); * 添加播放列表不带音频url
MediaMetadata_builder.setAlbumArtist(playInfo.getCovert()); *
MediaMetadata_builder.setTitle(playInfo.getSongTitle()); * @param listInfo
*/
@OptIn(markerClass = UnstableApi.class)
public void addMusicPlayList(List<ResponsePlayListInfo> listInfo) {
List<MediaItem> mediaItems = new ArrayList<>();
for (int i = 0; i < listInfo.size(); i++) {
ResponsePlayListInfo playInfo = listInfo.get(i);
MediaItem.Builder builder = new MediaItem.Builder();
//唯一标识符
builder.setMediaId(playInfo.getVideoId());
MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
MediaMetadata_builder.setArtist(playInfo.getSingerName());
MediaMetadata_builder.setDurationMs(playInfo.getDurationMs());
MediaMetadata_builder.setAlbumArtist(playInfo.getCovert());
MediaMetadata_builder.setTitle(playInfo.getSongTitle());
// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear())); // MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
builder.setMediaMetadata(MediaMetadata_builder.build()); builder.setMediaMetadata(MediaMetadata_builder.build());
mediaItems.add(builder.build());
mediaItems.add(builder.build()); }
mediaController.addMediaItems(mediaItems); mediaController.addMediaItems(mediaItems);
}
public void play() {
mediaController.prepare(); mediaController.prepare();
if (!mediaController.isPlaying())
mediaController.play();
} }
public void play(){ public void pause() {
mediaController.play(); if (mediaController.isPlaying())
mediaController.pause();
} }
} }

View File

@ -3,7 +3,9 @@ package com.hi.music.player.ui.activity;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Handler; import android.os.Handler;
import android.util.Pair;
import android.view.View; import android.view.View;
import android.widget.SeekBar;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -12,7 +14,6 @@ import androidx.core.content.ContextCompat;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.session.MediaController;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource; import com.bumptech.glide.load.DataSource;
@ -35,19 +36,31 @@ import com.hi.music.player.ui.activity.viewmodel.VMPlay;
import java.util.List; import java.util.List;
public class PlayActivity extends BaseActivity<ActivityPlayBinding> { public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements SeekBar.OnSeekBarChangeListener {
private ResponseSingle responseSingle; private ResponseSingle responseSingle;
private VMPlay vmPlay; private VMPlay vmPlay;
//接口返回的播放列表(没有音频数据)
private List<ResponsePlayListInfo> mPlayList; private List<ResponsePlayListInfo> mPlayList;
//播放列对应的音频数据
private List<ResponsePlayUrl> mPlayUrls;
private ResponsePlayUrl mCurPlayInfo; private ResponsePlayUrl mCurPlayInfo;
private ResponsePlayListInfo musicInfo; private ResponsePlayListInfo musicInfo;
private Handler mHandler; private Handler mHandler;
private Runnable mRunnable; private Runnable mRunnable;
private MyMediaControllerManager mediaControllerManager; private MyMediaControllerManager mediaControllerManager;
//请求播放列表是否成功
private boolean requestPlayList = false;
//请求第一首歌曲url是否成功
private boolean requestPlayUrl = false;
@Override @Override
protected ActivityPlayBinding getViewBinding() { protected ActivityPlayBinding getViewBinding() {
return ActivityPlayBinding.inflate(getLayoutInflater()); return ActivityPlayBinding.inflate(getLayoutInflater());
@ -58,35 +71,38 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> {
Intent intent = getIntent(); Intent intent = getIntent();
responseSingle = (ResponseSingle) intent.getSerializableExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER); responseSingle = (ResponseSingle) intent.getSerializableExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER);
vmPlay = getActivityScopeViewModel(VMPlay.class); vmPlay = getActivityScopeViewModel(VMPlay.class);
vmPlay.getPlayUrl(responseSingle);
vmPlay.getPlayMusicList(responseSingle); vmPlay.getPlayMusicList(responseSingle);
initPlayerView(); initPlayerView();
initMediaController(); initMediaController();
initProgressHandler();
vmPlay.data.observe(this, new Observer<List<ResponsePlayListInfo>>() { vmPlay.playList.observe(this, new Observer<List<ResponsePlayListInfo>>() {
@Override @Override
public void onChanged(List<ResponsePlayListInfo> playList) { public void onChanged(List<ResponsePlayListInfo> playList) {
if (playList.size() > 0) { if (playList.size() > 0) {
requestPlayList = true;
mPlayList = playList; mPlayList = playList;
musicInfo = playList.get(0); musicInfo = playList.get(0);
loadCovert(musicInfo.getCovert()); loadCovert(musicInfo.getCovert());
loadInfo(musicInfo); loadInfo(musicInfo);
startPlayMusic();
} }
} }
}); });
vmPlay.playUrlLiveData.observe(this, new Observer<ResponsePlayUrl>() { vmPlay.playUrlLiveData.observe(this, new Observer<Pair<ResponsePlayUrl, Integer>>() {
@Override @Override
public void onChanged(ResponsePlayUrl responsePlayUrl) { public void onChanged(Pair<ResponsePlayUrl, Integer> responsePlayUrlIntegerPair) {
mCurPlayInfo = responsePlayUrl; requestPlayUrl = true;
mCurPlayInfo = responsePlayUrlIntegerPair.first;
Integer second = responsePlayUrlIntegerPair.second;
CommonUtils.LogMsg("---------mCurPlayInfo=" + mCurPlayInfo.getAudioUrlLow()); CommonUtils.LogMsg("---------mCurPlayInfo=" + mCurPlayInfo.getAudioUrlLow());
startPlayMusic(); updateAudioUrl(responsePlayUrlIntegerPair.first);
if (second == 0) {
mediaControllerManager.play();
}
} }
}); });
} }
@ -99,35 +115,32 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> {
private void initMediaController() { private void initMediaController() {
mediaControllerManager = MyMediaControllerManager.getInstance(); mediaControllerManager = MyMediaControllerManager.getInstance();
mediaControllerManager.init(new MediaControllerListener() { mediaControllerManager.addListener(new MediaControllerListener() {
@Override
public void onMediaControllerComplete(boolean isOk) {
MediaController mediaController1 = mediaControllerManager.getMediaController();
vb.playerView.setPlayer(mediaController1);
startPlayMusic();
}
@Override @Override
public void onPlayStatus(int playStatus) { public void onPlayStatus(int playStatus) {
CommonUtils.LogMsg("-------------playStatus=" + playStatus);
switch (playStatus) { switch (playStatus) {
case Player.STATE_IDLE:
break;
case Player.STATE_BUFFERING:
//快进没有缓冲的时候触发
vb.progressBarLoading.setVisibility(View.VISIBLE);
CommonUtils.LogMsg("-------------duration STATE_BUFFERING=");
break;
case Player.STATE_READY: case Player.STATE_READY:
mHandler.post(mRunnable); mHandler.post(mRunnable);
vb.progressBar.setVisibility(View.GONE); vb.progressBarLoading.setVisibility(View.GONE);
break; break;
case Player.STATE_ENDED: case Player.STATE_ENDED:
mHandler.removeCallbacks(mRunnable); // 停止更新 mHandler.removeCallbacks(mRunnable); // 停止更新
break; updatePlayComplete();
case Player.STATE_BUFFERING:
break; break;
} }
} }
}); });
} }
@ -135,53 +148,65 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> {
@Override @Override
protected void onInitClick() { protected void onInitClick() {
vb.btnPlay.setOnClickListener(this::onClick); vb.btnPlay.setOnClickListener(this::onClick);
vb.playProgress.setOnSeekBarChangeListener(this);
} }
/** /**
* 更新播放进度Ui * 更新播放进度Ui缓冲进度
*/ */
private void updatePlaybackProgress() { private void updatePlaybackProgress() {
// 获取当前播放位置 // 获取当前播放位置
long contentPos = mediaControllerManager.getContentPos(); long contentPos = mediaControllerManager.getContentPos();
long currentPosition = mediaControllerManager.getMediaController().getCurrentPosition(); long bufferPos = mediaControllerManager.getBufferPos();
long duration = mediaControllerManager.getMediaController().getContentDuration();
long durationMs = musicInfo.getDurationMs();
String s = CommonUtils.convertMillisToTime(contentPos); String s = CommonUtils.convertMillisToTime(contentPos);
CommonUtils.LogMsg("---------播放进度-----contentPos=" + contentPos + "-----缓冲进度=" + bufferPos);
CommonUtils.LogMsg("---------播放进度-----contentPos=" + contentPos+"----currentPosition="+currentPosition+"------duration="+duration);
vb.tvCurrent.setText(s); vb.tvCurrent.setText(s);
vb.seekbar.setValue(contentPos); vb.playProgress.setProgress((int) contentPos);
vb.progressBarBuffer.setProgress((int) bufferPos);
}
/**
* 播放完成 更新播放进度Ui
*/
private void updatePlayComplete() {
vb.tvCurrent.setText(vb.tvDuration.getText().toString());
} }
/** /**
* 初始化当前播放歌曲信息 * 初始化当前播放歌曲信息
*
* @param data * @param data
*/ */
private void loadInfo(ResponsePlayListInfo data) { private void loadInfo(ResponsePlayListInfo data) {
vb.tvSongName.setText(data.getSongTitle()); vb.tvSongName.setText(data.getSongTitle());
vb.tvSingerName.setText(data.getSingerName()); vb.tvSingerName.setText(data.getSingerName());
vb.tvDuration.setText(data.getDuration()); vb.tvDuration.setText(data.getDuration());
vb.seekbar.setValueTo(data.getDurationMs());
long durationMs = data.getDurationMs();
vb.playProgress.setMax((int) durationMs);
vb.progressBarBuffer.setMax((int) data.getDurationMs());
CommonUtils.LogMsg("--------------data.getDurationMs() 22222222222=" + durationMs);
} }
private void startPlayMusic() {
initProgressHandler();
CommonUtils.LogMsg("00000");
MediaController mediaController = mediaControllerManager.getMediaController();
if (mCurPlayInfo != null && mediaController != null && mPlayList != null) {
mediaControllerManager.addMusicPlay(mPlayList.get(0), mCurPlayInfo);
mediaControllerManager.play();
CommonUtils.LogMsg("111");
}
/**
* 更新音频url到播放列表
*/
private void updateAudioUrl(ResponsePlayUrl playUrl) {
mediaControllerManager.UpdateAudioUrl(playUrl);
} }
private void loadCovert(String url) { private void loadCovert(String url) {
Glide.with(MusicApplication.myApplication) Glide.with(MusicApplication.myApplication)
.asDrawable() .asDrawable()
@ -213,8 +238,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> {
@Override @Override
public void run() { public void run() {
updatePlaybackProgress(); updatePlaybackProgress();
// 继续定时更新 mHandler.postDelayed(this, 1000);
mHandler.postDelayed(this, 1000); // 每秒更新一次
} }
}; };
} }
@ -233,6 +257,11 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> {
public void onClick(View v) { public void onClick(View v) {
if (v.equals(vb.btnPlay)) { if (v.equals(vb.btnPlay)) {
vb.btnPlay.setSelected(!vb.btnPlay.isSelected()); vb.btnPlay.setSelected(!vb.btnPlay.isSelected());
if (vb.btnPlay.isSelected()) {
mediaControllerManager.play();
} else {
mediaControllerManager.pause();
}
} }
} }
@ -243,4 +272,23 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> {
if (mHandler != null && mRunnable != null) if (mHandler != null && mRunnable != null)
mHandler.removeCallbacks(mRunnable); mHandler.removeCallbacks(mRunnable);
} }
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
CommonUtils.LogMsg("---------onProgressChanged----progress=" + progress);
mediaControllerManager.getMediaController().seekTo(progress);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
} }

View File

@ -1,5 +1,7 @@
package com.hi.music.player.ui.activity.viewmodel; package com.hi.music.player.ui.activity.viewmodel;
import android.util.Pair;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
@ -9,6 +11,7 @@ import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.response.ResponsePlayListInfo; import com.hi.music.player.javabean.response.ResponsePlayListInfo;
import com.hi.music.player.javabean.response.ResponsePlayUrl; import com.hi.music.player.javabean.response.ResponsePlayUrl;
import com.hi.music.player.javabean.response.child.ResponseSingle; import com.hi.music.player.javabean.response.child.ResponseSingle;
import com.hi.music.player.media3.MyMediaControllerManager;
import com.hi.music.player.network.JsonHelper; import com.hi.music.player.network.JsonHelper;
import com.hi.music.player.network.RetrofitManager; import com.hi.music.player.network.RetrofitManager;
@ -21,12 +24,12 @@ import okhttp3.ResponseBody;
public class VMPlay extends ViewModel { public class VMPlay extends ViewModel {
private MutableLiveData<List<ResponsePlayListInfo>> _data = new MutableLiveData<List<ResponsePlayListInfo>>(); private MutableLiveData<List<ResponsePlayListInfo>> _playList = new MutableLiveData<List<ResponsePlayListInfo>>();
public LiveData<List<ResponsePlayListInfo>> data = _data; public LiveData<List<ResponsePlayListInfo>> playList = _playList;
private MutableLiveData<ResponsePlayUrl> _playUrlMutableLiveData = new MutableLiveData<ResponsePlayUrl>(); private MutableLiveData<Pair<ResponsePlayUrl, Integer>> _playUrlMutableLiveData = new MutableLiveData<Pair<ResponsePlayUrl, Integer>>();
public LiveData<ResponsePlayUrl> playUrlLiveData = _playUrlMutableLiveData; public LiveData<Pair<ResponsePlayUrl, Integer>> playUrlLiveData = _playUrlMutableLiveData;
private String continuation, clickTrackingParams, visitorData; private String continuation, clickTrackingParams, visitorData;
@ -40,7 +43,7 @@ public class VMPlay extends ViewModel {
@Override @Override
public void onFail(String errorMsg) { public void onFail(String errorMsg) {
_data.setValue(null); _playList.setValue(null);
} }
@Override @Override
@ -48,16 +51,18 @@ public class VMPlay extends ViewModel {
JSONObject jsonObject = CommonUtils.toJsonObject(data); JSONObject jsonObject = CommonUtils.toJsonObject(data);
if (jsonObject != null) { if (jsonObject != null) {
List<ResponsePlayListInfo> responsePlayListInfos = JsonHelper.ResolvePlayListJson(jsonObject); List<ResponsePlayListInfo> responsePlayListInfos = JsonHelper.ResolvePlayListJson(jsonObject);
_data.setValue(responsePlayListInfos); MyMediaControllerManager.getInstance().addMusicPlayList(responsePlayListInfos);
_playList.setValue(responsePlayListInfos);
getPlayUrl(responseSingle,0);
} else { } else {
_data.setValue(null); _playList.setValue(null);
} }
} }
}); });
} }
public void getPlayUrl(ResponseSingle responseSingle) { public void getPlayUrl(ResponseSingle responseSingle, int playListIndex) {
String videoId = responseSingle.getVideoId(); String videoId = responseSingle.getVideoId();
RetrofitManager.getInstance().getPlayUrl(videoId, new RequestListener<ResponseBody>() { RetrofitManager.getInstance().getPlayUrl(videoId, new RequestListener<ResponseBody>() {
@ -71,7 +76,7 @@ public class VMPlay extends ViewModel {
JSONObject jsonObject = CommonUtils.toJsonObject(data); JSONObject jsonObject = CommonUtils.toJsonObject(data);
if (jsonObject != null) { if (jsonObject != null) {
ResponsePlayUrl responsePlayUrl = JsonHelper.ResolvePlayUrlJson(jsonObject); ResponsePlayUrl responsePlayUrl = JsonHelper.ResolvePlayUrlJson(jsonObject);
_playUrlMutableLiveData.setValue(responsePlayUrl); _playUrlMutableLiveData.setValue(new Pair<>(responsePlayUrl, playListIndex));
} else { } else {
_playUrlMutableLiveData.setValue(null); _playUrlMutableLiveData.setValue(null);
} }

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="10dp" />
<solid android:color="@color/color_transparent" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="10dp" />
<solid android:color="@color/progress_buffer_color"/>
</shape>
</clip>
</item>
</layer-list>

View File

@ -4,7 +4,7 @@
<solid android:color="@color/white" /> <solid android:color="@color/white" />
<size <size
android:width="13dp" android:width="9dp"
android:height="13dp" /> android:height="9dp" />
</shape> </shape>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="false" android:drawable="@mipmap/icon_pause"/> <item android:state_selected="false" android:drawable="@mipmap/icon_play"/>
<item android:state_selected="true" android:drawable="@mipmap/icon_play"/> <item android:state_selected="true" android:drawable="@mipmap/icon_pause"/>
</selector> </selector>

View File

@ -27,33 +27,32 @@
android:layout_marginTop="30dp" android:layout_marginTop="30dp"
android:layout_marginEnd="40dp" android:layout_marginEnd="40dp"
android:scaleType="fitXY" android:scaleType="fitXY"
android:src="@mipmap/ic_launcher"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/im_back" /> app:layout_constraintTop_toBottomOf="@id/im_back" />
<androidx.media3.ui.PlayerView <androidx.media3.ui.PlayerView
android:id="@+id/player_view" android:id="@+id/player_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
app:show_buffering="when_playing"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/im_back" app:layout_constraintTop_toBottomOf="@id/im_back"
app:show_shuffle_button="true"/> app:show_buffering="when_playing"
app:show_shuffle_button="true" />
<ProgressBar <ProgressBar
android:id="@+id/progressBarLoading"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:indeterminateTint="@color/white"
app:layout_constraintBottom_toBottomOf="@id/im_covert" app:layout_constraintBottom_toBottomOf="@id/im_covert"
app:layout_constraintLeft_toLeftOf="@id/im_covert" app:layout_constraintLeft_toLeftOf="@id/im_covert"
android:indeterminateTint="@color/white"
android:id="@+id/progressBar"
android:visibility="invisible"
app:layout_constraintRight_toRightOf="@id/im_covert" app:layout_constraintRight_toRightOf="@id/im_covert"
app:layout_constraintTop_toTopOf="@id/im_covert" /> app:layout_constraintTop_toTopOf="@id/im_covert" />
@ -79,57 +78,81 @@
app:layout_constraintLeft_toLeftOf="@id/tv_song_name" app:layout_constraintLeft_toLeftOf="@id/tv_song_name"
app:layout_constraintTop_toBottomOf="@id/tv_song_name" /> app:layout_constraintTop_toBottomOf="@id/tv_song_name" />
<com.google.android.material.slider.Slider
android:id="@+id/seekbar" <!-- <com.google.android.material.slider.Slider-->
<!-- android:id="@+id/play_progress"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:value="0"-->
<!-- android:valueFrom="0"-->
<!-- android:valueTo="100"-->
<!-- app:labelBehavior="gone"-->
<!-- app:layout_constraintLeft_toLeftOf="parent"-->
<!-- app:layout_constraintRight_toRightOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tv_singer_name"-->
<!-- app:thumbColor="@color/white"-->
<!-- app:thumbElevation="0dp"-->
<!-- android:paddingStart="0dp"-->
<!-- android:paddingEnd="0dp"-->
<!-- app:thumbRadius="4dp"-->
<!-- app:trackColorActive="@color/white"-->
<!-- app:trackColorInactive="@color/seek_bg_color"-->
<!-- app:trackHeight="3dp" />-->
<SeekBar
android:id="@+id/play_progress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="35dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="35dp"
android:maxHeight="3dp"
android:paddingLeft="0dp"
android:paddingEnd="5dp"
android:paddingRight="0dp"
android:paddingStart="5dp"
android:progress="30"
android:progressDrawable="@drawable/seekbar_progress_drawable"
android:thumb="@drawable/seekbar_thumb"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_singer_name" />
<ProgressBar
android:id="@+id/progressBar_buffer"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="3dp"
android:valueFrom="0" android:paddingStart="5dp"
app:layout_constraintLeft_toLeftOf="@id/im_covert" android:paddingEnd="5dp"
app:layout_constraintRight_toRightOf="@id/im_covert" android:progress="100"
app:layout_constraintTop_toBottomOf="@id/tv_singer_name" android:progressDrawable="@drawable/horizontal_progressbar"
app:labelBehavior="gone" app:layout_constraintBottom_toBottomOf="@id/play_progress"
app:thumbColor="@color/white" app:layout_constraintLeft_toLeftOf="@id/play_progress"
app:thumbRadius="6dp" app:layout_constraintRight_toRightOf="@id/play_progress"
app:trackColorActive="@color/white" app:layout_constraintTop_toTopOf="@id/play_progress" />
app:trackColorInactive="#00000000"
app:trackHeight="3dp" />
<SeekBar
android:id="@+id/seekbar1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:maxHeight="3dp"
android:paddingStart="0dp"
android:paddingLeft="0dp"
android:paddingEnd="0dp"
android:paddingRight="0dp"
android:progress="10"
android:visibility="gone"
android:progressDrawable="@drawable/seekbar_progress_drawable"
android:thumb="@drawable/seekbar_thumb"
app:layout_constraintLeft_toLeftOf="@id/im_covert"
app:layout_constraintRight_toRightOf="@id/im_covert"
app:layout_constraintTop_toBottomOf="@id/tv_singer_name" />
<TextView <TextView
android:id="@+id/tv_current" android:id="@+id/tv_current"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:text="1:23" android:paddingStart="5dp"
android:text="0:00"
android:textColor="@color/white_60_color" android:textColor="@color/white_60_color"
app:layout_constraintStart_toStartOf="@id/seekbar" app:layout_constraintStart_toStartOf="@id/play_progress"
app:layout_constraintTop_toBottomOf="@id/seekbar" /> app:layout_constraintTop_toBottomOf="@id/play_progress" />
<TextView <TextView
android:id="@+id/tv_duration" android:id="@+id/tv_duration"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:text="1:23" android:paddingEnd="5dp"
android:text="0:00"
android:textColor="@color/white_60_color" android:textColor="@color/white_60_color"
app:layout_constraintEnd_toEndOf="@id/seekbar" app:layout_constraintEnd_toEndOf="@id/play_progress"
app:layout_constraintTop_toBottomOf="@id/seekbar" /> app:layout_constraintTop_toBottomOf="@id/play_progress" />
<ImageView <ImageView
android:id="@+id/btn_play" android:id="@+id/btn_play"
@ -172,6 +195,4 @@
app:layout_constraintLeft_toLeftOf="@id/im_covert" /> app:layout_constraintLeft_toLeftOf="@id/im_covert" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -8,4 +8,7 @@
<color name="seek_bg_color">#4DFFFFFF</color> <color name="seek_bg_color">#4DFFFFFF</color>
<color name="white_60_color">#99FFFFFF</color> <color name="white_60_color">#99FFFFFF</color>
<color name="progress_buffer_color">#59FFFFFF</color>
<color name="test">#2D9C31</color>
</resources> </resources>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- <style name="Slider.NoMargin" parent="Widget.Material3.Slider">-->
<!-- <item name="trackMarginStart">0dp</item>-->
<!-- <item name="trackMarginEnd">0dp</item>-->
<!-- </style>-->
</resources>