连续播放,前后切歌功能
This commit is contained in:
parent
0787a71679
commit
0f59e337be
@ -57,6 +57,8 @@ dependencies {
|
|||||||
|
|
||||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
implementation("com.github.bumptech.glide:glide:4.16.0")
|
||||||
|
|
||||||
|
implementation ("androidx.palette:palette:1.0.0")
|
||||||
|
|
||||||
//----------media3
|
//----------media3
|
||||||
implementation("androidx.media3:media3-exoplayer:1.4.1")
|
implementation("androidx.media3:media3-exoplayer:1.4.1")
|
||||||
implementation("androidx.media3:media3-exoplayer-dash:1.4.1")
|
implementation("androidx.media3:media3-exoplayer-dash:1.4.1")
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||||
<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.WAKE_LOCK" />
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,22 @@
|
|||||||
package com.hi.music.player.api;
|
package com.hi.music.player.api;
|
||||||
|
|
||||||
|
import androidx.media3.common.MediaItem;
|
||||||
|
|
||||||
public interface MediaControllerListener {
|
public interface MediaControllerListener {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void onPlayStatus(int playStatus);
|
void onPlayStatus(int playStatus);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param videoId
|
||||||
|
* @param playListIndex 在播放列表中的位置索引
|
||||||
|
* @param playNow 立即播放
|
||||||
|
*/
|
||||||
|
void onRequestNextUri(String videoId,int playListIndex,boolean playNow);
|
||||||
|
|
||||||
|
|
||||||
|
void onChangeMusic(MediaItem mediaItem);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
package com.hi.music.player.api;
|
||||||
|
|
||||||
|
public interface onImageColorListener {
|
||||||
|
void onImageColor(int color);
|
||||||
|
}
|
||||||
61
app/src/main/java/com/hi/music/player/dialog/BaseDialog.java
Normal file
61
app/src/main/java/com/hi/music/player/dialog/BaseDialog.java
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package com.hi.music.player.dialog;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.viewbinding.ViewBinding;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class BaseDialog<T extends ViewBinding> extends DialogFragment {
|
||||||
|
|
||||||
|
protected T vb;
|
||||||
|
|
||||||
|
|
||||||
|
protected abstract T getViewBinding(LayoutInflater inflater, ViewGroup container);
|
||||||
|
|
||||||
|
protected abstract void initView();
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
vb = getViewBinding(inflater,container);
|
||||||
|
init();
|
||||||
|
initView();
|
||||||
|
return vb.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
|
||||||
|
Dialog dialog = getDialog();
|
||||||
|
setCancelable(true);
|
||||||
|
if (dialog != null) {
|
||||||
|
Window window = dialog.getWindow();
|
||||||
|
if (window != null) {
|
||||||
|
// window.setBackgroundDrawableResource();
|
||||||
|
window.getDecorView().setPadding(0, 0, 0, 0);
|
||||||
|
|
||||||
|
WindowManager.LayoutParams attributes = window.getAttributes();
|
||||||
|
attributes.gravity = Gravity.BOTTOM;
|
||||||
|
attributes.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||||
|
attributes.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||||
|
window.setAttributes(attributes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeDialog() {
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package com.hi.music.player.dialog;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.hi.music.player.databinding.DialogPlayListBinding;
|
||||||
|
|
||||||
|
public class DialogPlayList extends BaseDialog<DialogPlayListBinding>{
|
||||||
|
@Override
|
||||||
|
protected DialogPlayListBinding getViewBinding(LayoutInflater inflater, ViewGroup container) {
|
||||||
|
return DialogPlayListBinding.inflate(inflater,container,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initView() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,10 +1,17 @@
|
|||||||
package com.hi.music.player.helper;
|
package com.hi.music.player.helper;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.palette.graphics.Palette;
|
||||||
|
|
||||||
import com.hi.music.player.MusicApplication;
|
import com.hi.music.player.MusicApplication;
|
||||||
|
import com.hi.music.player.api.onImageColorListener;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -80,4 +87,43 @@ public class CommonUtils {
|
|||||||
long minutes = (millis / (1000 * 60)) % 60;
|
long minutes = (millis / (1000 * 60)) % 60;
|
||||||
return String.format("%d:%02d", minutes, seconds); // 格式化为 mm:ss
|
return String.format("%d:%02d", minutes, seconds); // 格式化为 mm:ss
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从图片中提取主色调
|
||||||
|
* @param imDraw
|
||||||
|
*/
|
||||||
|
public static void extractDominantColor(Drawable imDraw, onImageColorListener listener) {
|
||||||
|
BitmapDrawable drawable = (BitmapDrawable)imDraw;
|
||||||
|
if (drawable != null) {
|
||||||
|
Bitmap bitmap = drawable.getBitmap();
|
||||||
|
|
||||||
|
// 使用 Palette 提取颜色
|
||||||
|
Palette.from(bitmap).generate(palette -> {
|
||||||
|
if (palette != null) {
|
||||||
|
int dominantColor = palette.getDominantColor(0);
|
||||||
|
int suitableDarkColor = getSuitableDarkColor(dominantColor);
|
||||||
|
listener.onImageColor(suitableDarkColor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static int getSuitableDarkColor(int color) {
|
||||||
|
// 提取颜色的 R, G, B 值
|
||||||
|
int r = (color >> 16) & 0xff;
|
||||||
|
int g = (color >> 8) & 0xff;
|
||||||
|
int b = color & 0xff;
|
||||||
|
|
||||||
|
// 计算亮度
|
||||||
|
double luminance = 0.299 * r + 0.587 * g + 0.114 * b;
|
||||||
|
|
||||||
|
// 如果亮度较高,则选择更深的颜色
|
||||||
|
if (luminance > 128) {
|
||||||
|
return 0xFF000000; // 黑色
|
||||||
|
} else {
|
||||||
|
// 如果颜色较暗,选择一种深色调
|
||||||
|
return 0xFF1F1F1F; // 深灰色作为替代
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
package com.hi.music.player.javabean;
|
||||||
|
|
||||||
|
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
||||||
|
|
||||||
|
public class CustomerUrlInfo {
|
||||||
|
|
||||||
|
private ResponsePlayUrl playUrl;
|
||||||
|
private int playMusicIndex;
|
||||||
|
private boolean needPlayNow;
|
||||||
|
|
||||||
|
|
||||||
|
public ResponsePlayUrl getPlayUrl() {
|
||||||
|
return playUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlayUrl(ResponsePlayUrl playUrl) {
|
||||||
|
this.playUrl = playUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPlayMusicIndex() {
|
||||||
|
return playMusicIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlayMusicIndex(int playMusicIndex) {
|
||||||
|
this.playMusicIndex = playMusicIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNeedPlayNow() {
|
||||||
|
return needPlayNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNeedPlayNow(boolean needPlayNow) {
|
||||||
|
this.needPlayNow = needPlayNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,11 @@ public class ResponsePlayListInfo {
|
|||||||
|
|
||||||
//封面
|
//封面
|
||||||
private String covert;
|
private String covert;
|
||||||
|
|
||||||
|
|
||||||
|
//小尺寸封面
|
||||||
|
private String smallCovert;
|
||||||
|
|
||||||
//歌曲名字
|
//歌曲名字
|
||||||
private String SongTitle;
|
private String SongTitle;
|
||||||
|
|
||||||
@ -37,11 +42,13 @@ public class ResponsePlayListInfo {
|
|||||||
private String audioUrlMedium;
|
private String audioUrlMedium;
|
||||||
|
|
||||||
|
|
||||||
|
public String getSmallCovert() {
|
||||||
|
return smallCovert;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSmallCovert(String smallCovert) {
|
||||||
|
this.smallCovert = smallCovert;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public long getDurationMs() {
|
public long getDurationMs() {
|
||||||
return DurationMs;
|
return DurationMs;
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
package com.hi.music.player.media3;
|
package com.hi.music.player.media3;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.OptIn;
|
import androidx.annotation.OptIn;
|
||||||
import androidx.media3.common.MediaItem;
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.media3.common.MediaMetadata;
|
import androidx.media3.common.MediaMetadata;
|
||||||
@ -23,7 +25,9 @@ import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
|||||||
import com.hi.music.player.network.RetrofitManager;
|
import com.hi.music.player.network.RetrofitManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
public class MyMediaControllerManager {
|
public class MyMediaControllerManager {
|
||||||
@ -32,6 +36,11 @@ public class MyMediaControllerManager {
|
|||||||
|
|
||||||
private MediaController mediaController;
|
private MediaController mediaController;
|
||||||
|
|
||||||
|
private MediaControllerListener mListener;
|
||||||
|
|
||||||
|
//播放列表总数量
|
||||||
|
private List<ResponsePlayListInfo> playList;
|
||||||
|
|
||||||
public static MyMediaControllerManager getInstance() {
|
public static MyMediaControllerManager getInstance() {
|
||||||
if (myMediaControllerManagerInstance == null) {
|
if (myMediaControllerManagerInstance == null) {
|
||||||
synchronized (RetrofitManager.class) {
|
synchronized (RetrofitManager.class) {
|
||||||
@ -68,36 +77,60 @@ public class MyMediaControllerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addListener(MediaControllerListener listener) {
|
public void addListener(MediaControllerListener listener) {
|
||||||
|
mListener = listener;
|
||||||
mediaController.addListener(new Player.Listener() {
|
mediaController.addListener(new Player.Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerError(PlaybackException error) {
|
public void onPlayerError(PlaybackException error) {
|
||||||
CommonUtils.LogMsg("=-----PlaybackException+" + error.getMessage());
|
CommonUtils.LogMsg("=-----PlaybackException+" + error.getMessage());
|
||||||
listener.onPlayStatus(MyValue.PLAY_STATUS_CODE);
|
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMediaItemTransition(@Nullable MediaItem mediaItem, int reason) {
|
||||||
|
//当前媒体项发生变化,切歌
|
||||||
|
if(mediaItem == null){
|
||||||
|
//第二次进入PlayActitivity ,调用resetPlayList(),这里为null
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mListener.onChangeMusic(mediaItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onIsPlayingChanged(boolean isPlaying) {
|
public void onIsPlayingChanged(boolean isPlaying) {
|
||||||
CommonUtils.LogMsg("-----onIsPlayingChanged+" + isPlaying);
|
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
|
|
||||||
|
// TODO: 2024/9/26 自动播放完成切歌到下一首播放没有触发这里请求下一首
|
||||||
// 播放器开始播放
|
// 播放器开始播放
|
||||||
System.out.println("Playback started!");
|
MediaItem currentItem = mediaController.getCurrentMediaItem();
|
||||||
|
int currentMediaItemIndex = mediaController.getCurrentMediaItemIndex();
|
||||||
|
if (currentMediaItemIndex < playList.size() - 1) {
|
||||||
|
//代表有下一首
|
||||||
|
if (!mediaController.hasNextMediaItem()) {
|
||||||
|
//没有更新下一首的uri
|
||||||
|
CommonUtils.LogMsg("----0000000000-请求下一首的uri" + mediaController.getMediaItemCount());
|
||||||
|
int nextIndex = currentMediaItemIndex + 1;
|
||||||
|
mListener.onRequestNextUri(playList.get(nextIndex).getVideoId(), nextIndex,false);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// 播放器暂停或停止
|
// 播放器暂停或停止
|
||||||
System.out.println("Playback paused or stopped.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlaybackStateChanged(int playbackState) {
|
public void onPlaybackStateChanged(int playbackState) {
|
||||||
|
CommonUtils.LogMsg("----playbackState" + playbackState + "------------" + mediaController.getMediaItemCount());
|
||||||
listener.onPlayStatus(playbackState);
|
mListener.onPlayStatus(playbackState);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPositionDiscontinuity(Player.PositionInfo oldPosition, Player.PositionInfo newPosition, int reason) {
|
public void onPositionDiscontinuity(Player.PositionInfo oldPosition, Player.PositionInfo newPosition, int reason) {
|
||||||
// 快进、快退等操作
|
// 快进、快退等操作
|
||||||
CommonUtils.LogMsg("=-----快进、快退+" + newPosition.positionMs);
|
// CommonUtils.LogMsg("=-----快进、快退+" + newPosition.positionMs);
|
||||||
// mediaControllerListener.onPlayStatus(playbackState);
|
// mediaControllerListener.onPlayStatus(playbackState);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -119,95 +152,153 @@ public class MyMediaControllerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 更新播放列表中的音频url
|
||||||
|
// *
|
||||||
|
// * @param playUrl
|
||||||
|
// */
|
||||||
|
// public void UpdateAudioUrl(ResponsePlayUrl playUrl) {
|
||||||
|
//
|
||||||
|
// CommonUtils.LogMsg("-------------更新播放列表中的音频 mediaController.getMediaItemCount()=" + mediaController.getMediaItemCount());
|
||||||
|
// for (int i = 0; i < mediaController.getMediaItemCount(); i++) {
|
||||||
|
// MediaItem mediaItemAt = mediaController.getMediaItemAt(i);
|
||||||
|
// if (mediaItemAt.mediaId.equals(playUrl.getVideoId())) {
|
||||||
|
//
|
||||||
|
// MediaItem.Builder builder = mediaItemAt.buildUpon();
|
||||||
|
//// mediaController.removeMediaItem(i);
|
||||||
|
//// MediaItem.Builder builder = new MediaItem.Builder();
|
||||||
|
// builder.setMediaId(playUrl.getVideoId());
|
||||||
|
// if (playUrl.getAudioUrlMedium() != null) {
|
||||||
|
// builder.setUri(playUrl.getAudioUrlMedium());
|
||||||
|
// } else {
|
||||||
|
// builder.setUri(playUrl.getAudioUrlLow());
|
||||||
|
// }
|
||||||
|
// mediaController.replaceMediaItem(i, builder.build());
|
||||||
|
// CharSequence title = mediaController.getMediaItemAt(i).mediaMetadata.title;
|
||||||
|
// CommonUtils.LogMsg("-------------更新播放列表中的音频url= i=" + i + "---title=" + title + "----mediaController.size=" + mediaController.getMediaItemCount() + "---" + mediaController);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void setPlayList(List<ResponsePlayListInfo> playList) {
|
||||||
|
this.playList = playList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetPlayList(){
|
||||||
|
mediaController.clearMediaItems();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新播放列表中的音频url
|
* 添加播放列表(不带音频url)
|
||||||
|
* 注意没有更新有效uri的不会被实际添加到mediaController
|
||||||
*
|
*
|
||||||
* @param playUrl
|
* @param playUrl
|
||||||
*/
|
*/
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
public void UpdateAudioUrl(ResponsePlayUrl playUrl) {
|
public void addMusicToPlayList(ResponsePlayUrl playUrl, int playListIndex) {
|
||||||
for (int i = 0; i < mediaController.getMediaItemCount(); i++) {
|
if (playListIndex < playList.size()&& playListIndex>=mediaController.getMediaItemCount()) {
|
||||||
MediaItem mediaItemAt = mediaController.getMediaItemAt(i);
|
ResponsePlayListInfo listInfo = playList.get(playListIndex);
|
||||||
if (mediaItemAt.mediaId.equals(playUrl.getVideoId())) {
|
if (listInfo.getVideoId().equals(playUrl.getVideoId())) {
|
||||||
MediaItem.Builder builder = mediaItemAt.buildUpon();
|
MediaItem.Builder builder = new MediaItem.Builder();
|
||||||
|
|
||||||
|
//唯一标识符
|
||||||
|
builder.setMediaId(playUrl.getVideoId());
|
||||||
if (playUrl.getAudioUrlMedium() != null) {
|
if (playUrl.getAudioUrlMedium() != null) {
|
||||||
builder.setUri(playUrl.getAudioUrlMedium());
|
builder.setUri(playUrl.getAudioUrlMedium());
|
||||||
} else {
|
} else {
|
||||||
builder.setUri(playUrl.getAudioUrlLow());
|
builder.setUri(playUrl.getAudioUrlLow());
|
||||||
}
|
}
|
||||||
mediaController.setMediaItem(builder.build(), i);
|
|
||||||
CharSequence title = mediaController.getMediaItemAt(i).mediaMetadata.title;
|
MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
||||||
CommonUtils.LogMsg("-------------更新播放列表中的音频url= i=" + i + "---title=" + title);
|
|
||||||
break;
|
MediaMetadata_builder.setArtist(listInfo.getSingerName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这里使用setDescription保存歌曲时长的分秒字符串
|
||||||
|
*/
|
||||||
|
MediaMetadata_builder.setDescription(listInfo.getDuration());
|
||||||
|
MediaMetadata_builder.setDurationMs(listInfo.getDurationMs());
|
||||||
|
MediaMetadata_builder.setArtworkUri(Uri.parse(listInfo.getCovert()));
|
||||||
|
// MediaMetadata_builder.setArtworkUri(Uri.parse("https://t7.baidu.com/it/u=2604797219,1573897854&fm=193&f=GIF"));
|
||||||
|
MediaMetadata_builder.setTitle(listInfo.getSongTitle());
|
||||||
|
|
||||||
|
CommonUtils.LogMsg("----------添加到播放列表 i=" + playListIndex + "---" + listInfo.getSongTitle() + "-------VideoId=" + listInfo.getVideoId());
|
||||||
|
// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
||||||
|
builder.setMediaMetadata(MediaMetadata_builder.build());
|
||||||
|
mediaController.addMediaItem(builder.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 添加播放列表(不带音频url)
|
||||||
|
// * 注意没有更新有效uri的不会被实际添加到mediaController
|
||||||
|
// *
|
||||||
|
// * @param listInfo
|
||||||
|
// */
|
||||||
// @OptIn(markerClass = UnstableApi.class)
|
// @OptIn(markerClass = UnstableApi.class)
|
||||||
// public void addMusicPlay(ResponsePlayListInfo playInfo, ResponsePlayUrl responsePlay) {
|
// public void addMusicPlayList(List<ResponsePlayListInfo> listInfo) {
|
||||||
|
// playList = listInfo;
|
||||||
// List<MediaItem> mediaItems = new ArrayList<>();
|
// List<MediaItem> mediaItems = new ArrayList<>();
|
||||||
|
// for (int i = 0; i < listInfo.size(); i++) {
|
||||||
|
// ResponsePlayListInfo playInfo = listInfo.get(i);
|
||||||
|
//
|
||||||
// MediaItem.Builder builder = new MediaItem.Builder();
|
// MediaItem.Builder builder = new MediaItem.Builder();
|
||||||
// if (responsePlay.getAudioUrlMedium() != null) {
|
|
||||||
// builder.setUri(responsePlay.getAudioUrlMedium());
|
|
||||||
// } else {
|
|
||||||
// builder.setUri(responsePlay.getAudioUrlLow());
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// //唯一标识符
|
// //唯一标识符
|
||||||
// builder.setMediaId(responsePlay.getVideoId());
|
// builder.setMediaId(playInfo.getVideoId());
|
||||||
//
|
//
|
||||||
// MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
// MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
||||||
//
|
//
|
||||||
// MediaMetadata_builder.setArtist(playInfo.getSingerName());
|
// MediaMetadata_builder.setArtist(playInfo.getSingerName());
|
||||||
// MediaMetadata_builder.setDurationMs(playInfo.getDurationMs());
|
// MediaMetadata_builder.setDurationMs(playInfo.getDurationMs());
|
||||||
// MediaMetadata_builder.setAlbumArtist(playInfo.getCovert());
|
//// MediaMetadata_builder.setArtworkUri(Uri.parse(playInfo.getCovert()));
|
||||||
|
// MediaMetadata_builder.setArtworkUri(Uri.parse("https://t7.baidu.com/it/u=2604797219,1573897854&fm=193&f=GIF"));
|
||||||
// MediaMetadata_builder.setTitle(playInfo.getSongTitle());
|
// MediaMetadata_builder.setTitle(playInfo.getSongTitle());
|
||||||
|
//
|
||||||
|
// CommonUtils.LogMsg("----------添加播放列表 i=" + i + "---" + playInfo.getSongTitle() + "-------VideoId=" + playInfo.getVideoId());
|
||||||
//// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
//// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
||||||
// builder.setMediaMetadata(MediaMetadata_builder.build());
|
// builder.setMediaMetadata(MediaMetadata_builder.build());
|
||||||
//
|
// mediaController.addMediaItem(builder.build());
|
||||||
// mediaItems.add(builder.build());
|
//// mediaItems.add(builder.build());
|
||||||
// mediaController.addMediaItems(mediaItems);
|
// }
|
||||||
// mediaController.prepare();
|
//// mediaController.setMediaItems(mediaItems);
|
||||||
//
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加播放列表(不带音频url)
|
|
||||||
*
|
|
||||||
* @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()));
|
|
||||||
builder.setMediaMetadata(MediaMetadata_builder.build());
|
|
||||||
mediaItems.add(builder.build());
|
|
||||||
}
|
|
||||||
mediaController.addMediaItems(mediaItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void play() {
|
public void play() {
|
||||||
|
if (!mediaController.isPlaying()) {
|
||||||
mediaController.prepare();
|
mediaController.prepare();
|
||||||
if (!mediaController.isPlaying())
|
|
||||||
mediaController.play();
|
mediaController.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public void pause() {
|
public void pause() {
|
||||||
if (mediaController.isPlaying())
|
if (mediaController.isPlaying())
|
||||||
mediaController.pause();
|
mediaController.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void playNext() {
|
||||||
|
if (mediaController.hasNextMediaItem()) {
|
||||||
|
mediaController.seekToNextMediaItem();
|
||||||
|
} else {
|
||||||
|
int currentMediaItemIndex = mediaController.getCurrentMediaItemIndex();
|
||||||
|
if (currentMediaItemIndex < playList.size() - 1) {
|
||||||
|
//应该有下一首,可能是歌曲url请求失败,需要重新请求
|
||||||
|
int nextIndex = currentMediaItemIndex + 1;
|
||||||
|
mListener.onRequestNextUri(playList.get(nextIndex).getVideoId(), nextIndex,true);
|
||||||
|
CommonUtils.LogMsg("-------------应该有下一首,可能是歌曲url请求失败,需要重新请求");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void playPrevious() {
|
||||||
|
if (mediaController.hasPreviousMediaItem()) {
|
||||||
|
mediaController.seekToPreviousMediaItem();
|
||||||
|
} else {
|
||||||
|
mediaController.seekTo(0);
|
||||||
|
mediaController.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,11 +4,13 @@ import android.content.Intent;
|
|||||||
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.OptIn;
|
||||||
import androidx.media3.common.AudioAttributes;
|
import androidx.media3.common.AudioAttributes;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.MediaItem;
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.media3.common.MediaMetadata;
|
import androidx.media3.common.MediaMetadata;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.exoplayer.ExoPlayer;
|
import androidx.media3.exoplayer.ExoPlayer;
|
||||||
|
|
||||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
||||||
@ -17,6 +19,7 @@ import androidx.media3.session.MediaSession;
|
|||||||
import androidx.media3.session.MediaSessionService;
|
import androidx.media3.session.MediaSessionService;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.hi.music.player.R;
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
import com.hi.music.player.helper.CommonUtils;
|
||||||
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
||||||
|
|
||||||
@ -31,32 +34,43 @@ public class PlaybackService extends MediaSessionService {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.DEFAULT.usage)
|
player = new ExoPlayer.Builder(this).build();
|
||||||
.setContentType(AudioAttributes.DEFAULT.contentType)
|
mediaSession = new MediaSession.Builder(this, player)
|
||||||
.build();
|
.setCallback(new MediaSession.Callback() {
|
||||||
|
|
||||||
// MediaSource.Factory mediaSourceFactory =
|
|
||||||
// new DefaultMediaSourceFactory(context)
|
|
||||||
// .setDataSourceFactory(cacheDataSourceFactory)
|
|
||||||
// .setLocalAdInsertionComponents(adsLoaderProvider);
|
|
||||||
|
|
||||||
player = new ExoPlayer.Builder(this)
|
|
||||||
.setWakeMode(C.WAKE_MODE_LOCAL)
|
|
||||||
// .setMediaSourceFactory(mediaSourceFactory)
|
|
||||||
.setAudioAttributes(audioAttributes, true).build();
|
|
||||||
|
|
||||||
mediaSession = new MediaSession.Builder(this, player).setCallback(new MediaSession.Callback() {
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<List<MediaItem>> onAddMediaItems(MediaSession mediaSession, MediaSession.ControllerInfo controller, List<MediaItem> mediaItems) {
|
public ListenableFuture<List<MediaItem>> onAddMediaItems(MediaSession mediaSession, MediaSession.ControllerInfo controller, List<MediaItem> mediaItems) {
|
||||||
|
|
||||||
CommonUtils.LogMsg("--------mediaItems="+mediaItems.get(0).mediaMetadata.title);
|
CommonUtils.LogMsg("--------实际添加的媒体项="+mediaItems.size()+"----"+mediaSession.getPlayer().getMediaItemCount());
|
||||||
// player.addMediaItems(mediaItems);
|
|
||||||
|
|
||||||
return MediaSession.Callback.super.onAddMediaItems(mediaSession, controller, mediaItems);
|
return MediaSession.Callback.super.onAddMediaItems(mediaSession, controller, mediaItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
// player = new ExoPlayer.Builder(this)
|
||||||
|
// .setWakeMode(C.WAKE_MODE_LOCAL)
|
||||||
|
//// .setMediaSourceFactory(mediaSourceFactory)
|
||||||
|
// .setAudioAttributes(audioAttributes, true).build();
|
||||||
|
//
|
||||||
|
// mediaSession = new MediaSession.Builder(this, player)
|
||||||
|
// .setId(getString(R.string.app_name) + "_MusicId")
|
||||||
|
// .setCallback(new MediaSession.Callback() {
|
||||||
|
// @Override
|
||||||
|
// public ListenableFuture<List<MediaItem>> onAddMediaItems(MediaSession mediaSession, MediaSession.ControllerInfo controller, List<MediaItem> mediaItems) {
|
||||||
|
//
|
||||||
|
// CommonUtils.LogMsg("--------实际添加的媒体项="+player.getMediaItemCount());
|
||||||
|
//// player.addMediaItems(mediaItems);
|
||||||
|
//
|
||||||
|
// return MediaSession.Callback.super.onAddMediaItems(mediaSession, controller, mediaItems);
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -71,11 +85,13 @@ public class PlaybackService extends MediaSessionService {
|
|||||||
@Override
|
@Override
|
||||||
public void onTaskRemoved(@Nullable Intent rootIntent) {
|
public void onTaskRemoved(@Nullable Intent rootIntent) {
|
||||||
Player player = mediaSession.getPlayer();
|
Player player = mediaSession.getPlayer();
|
||||||
// if (player.getPlayWhenReady()) {
|
if (!player.getPlayWhenReady()
|
||||||
// // Make sure the service is not in foreground.
|
|| player.getMediaItemCount() == 0
|
||||||
// player.pause();
|
|| player.getPlaybackState() == Player.STATE_ENDED) {
|
||||||
// }
|
// Stop the service if not playing, continue playing in the background
|
||||||
// stopSelf();
|
// otherwise.
|
||||||
|
stopSelf();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -22,7 +22,7 @@ public class JsonHelper {
|
|||||||
public static ResponseHome ResolveHomeJson(JSONObject jsonObject) {
|
public static ResponseHome ResolveHomeJson(JSONObject jsonObject) {
|
||||||
ResponseHome responseHome = new ResponseHome();
|
ResponseHome responseHome = new ResponseHome();
|
||||||
try {
|
try {
|
||||||
String bgUrl = getJsonUrl(jsonObject.getJSONObject("background"));
|
String bgUrl = getJsonUrl(jsonObject.getJSONObject("background"),true);
|
||||||
|
|
||||||
JSONObject sectionListRenderer = jsonObject.getJSONObject("contents").getJSONObject("singleColumnBrowseResultsRenderer").getJSONArray("tabs").getJSONObject(0).getJSONObject("tabRenderer").getJSONObject("content").getJSONObject("sectionListRenderer");
|
JSONObject sectionListRenderer = jsonObject.getJSONObject("contents").getJSONObject("singleColumnBrowseResultsRenderer").getJSONArray("tabs").getJSONObject(0).getJSONObject("tabRenderer").getJSONObject("content").getJSONObject("sectionListRenderer");
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ public class JsonHelper {
|
|||||||
if (musicResponsiveListItemRenderer != null) {
|
if (musicResponsiveListItemRenderer != null) {
|
||||||
ResponseSingle responseSingle = new ResponseSingle();
|
ResponseSingle responseSingle = new ResponseSingle();
|
||||||
|
|
||||||
String SingerHead = getJsonUrl(musicResponsiveListItemRenderer.getJSONObject("thumbnail"));
|
String SingerHead = getJsonUrl(musicResponsiveListItemRenderer.getJSONObject("thumbnail"),true);
|
||||||
|
|
||||||
|
|
||||||
JSONArray flexColumns = musicResponsiveListItemRenderer.getJSONArray("flexColumns");
|
JSONArray flexColumns = musicResponsiveListItemRenderer.getJSONArray("flexColumns");
|
||||||
@ -145,7 +145,7 @@ public class JsonHelper {
|
|||||||
JSONObject musicTwoRowItemRenderer = jsonList.optJSONObject("musicTwoRowItemRenderer");
|
JSONObject musicTwoRowItemRenderer = jsonList.optJSONObject("musicTwoRowItemRenderer");
|
||||||
if (musicTwoRowItemRenderer != null) {
|
if (musicTwoRowItemRenderer != null) {
|
||||||
ResponseCategory responseCategory = new ResponseCategory();
|
ResponseCategory responseCategory = new ResponseCategory();
|
||||||
String covert = getJsonUrl(musicTwoRowItemRenderer.getJSONObject("thumbnailRenderer"));
|
String covert = getJsonUrl(musicTwoRowItemRenderer.getJSONObject("thumbnailRenderer"),true);
|
||||||
|
|
||||||
JSONObject title1 = musicTwoRowItemRenderer.getJSONObject("title");
|
JSONObject title1 = musicTwoRowItemRenderer.getJSONObject("title");
|
||||||
String twoTitle = getJsonTitle(title1, 0);
|
String twoTitle = getJsonTitle(title1, 0);
|
||||||
@ -185,7 +185,10 @@ public class JsonHelper {
|
|||||||
ResponsePlayListInfo responsePlayListInfo = new ResponsePlayListInfo();
|
ResponsePlayListInfo responsePlayListInfo = new ResponsePlayListInfo();
|
||||||
JSONObject playlistPanelVideoRenderer = contents.getJSONObject(i).getJSONObject("playlistPanelVideoRenderer");
|
JSONObject playlistPanelVideoRenderer = contents.getJSONObject(i).getJSONObject("playlistPanelVideoRenderer");
|
||||||
|
|
||||||
String jsonUrl = getJsonUrl(playlistPanelVideoRenderer);
|
String maxUrl = getJsonUrl(playlistPanelVideoRenderer,true);
|
||||||
|
|
||||||
|
String smallUrl = getJsonUrl(playlistPanelVideoRenderer, false);
|
||||||
|
|
||||||
String songName = getJsonTitle(playlistPanelVideoRenderer.getJSONObject("title"), 0);
|
String songName = getJsonTitle(playlistPanelVideoRenderer.getJSONObject("title"), 0);
|
||||||
|
|
||||||
JSONObject longBylineText = playlistPanelVideoRenderer.getJSONObject("longBylineText");
|
JSONObject longBylineText = playlistPanelVideoRenderer.getJSONObject("longBylineText");
|
||||||
@ -200,7 +203,8 @@ public class JsonHelper {
|
|||||||
|
|
||||||
String[] watchEndPoint = getWatchEndPoint(playlistPanelVideoRenderer);
|
String[] watchEndPoint = getWatchEndPoint(playlistPanelVideoRenderer);
|
||||||
|
|
||||||
responsePlayListInfo.setCovert(jsonUrl);
|
responsePlayListInfo.setCovert(maxUrl);
|
||||||
|
responsePlayListInfo.setSmallCovert(smallUrl);
|
||||||
responsePlayListInfo.setSongTitle(songName);
|
responsePlayListInfo.setSongTitle(songName);
|
||||||
responsePlayListInfo.setSingerName(singerName);
|
responsePlayListInfo.setSingerName(singerName);
|
||||||
responsePlayListInfo.setAlbumTitle(AlbumTitle);
|
responsePlayListInfo.setAlbumTitle(AlbumTitle);
|
||||||
@ -213,7 +217,7 @@ public class JsonHelper {
|
|||||||
responsePlayListInfo.setMusicVideoType(watchEndPoint[3]);
|
responsePlayListInfo.setMusicVideoType(watchEndPoint[3]);
|
||||||
|
|
||||||
list.add(responsePlayListInfo);
|
list.add(responsePlayListInfo);
|
||||||
CommonUtils.LogMsg("----------歌曲名字=" + songName + "---" + Arrays.toString(watchEndPoint));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -299,8 +303,15 @@ public class JsonHelper {
|
|||||||
return strings;
|
return strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
//取最大的一张图片
|
|
||||||
private static String getJsonUrl(JSONObject jsonObject) {
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* @param maxBig 是否取最大的一张图片
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getJsonUrl(JSONObject jsonObject,boolean maxBig) {
|
||||||
try {
|
try {
|
||||||
boolean b = jsonObject.has("musicThumbnailRenderer");
|
boolean b = jsonObject.has("musicThumbnailRenderer");
|
||||||
if (b) {
|
if (b) {
|
||||||
@ -308,8 +319,11 @@ public class JsonHelper {
|
|||||||
}
|
}
|
||||||
JSONArray jsonArray = jsonObject.getJSONObject("thumbnail").getJSONArray("thumbnails");
|
JSONArray jsonArray = jsonObject.getJSONObject("thumbnail").getJSONArray("thumbnails");
|
||||||
int length = jsonArray.length();
|
int length = jsonArray.length();
|
||||||
CommonUtils.LogMsg("----------length=" + (length - 1));
|
int index = 0;
|
||||||
String pngUrl = jsonArray.getJSONObject(length - 1).getString("url");
|
if(maxBig){
|
||||||
|
index = length - 1;
|
||||||
|
}
|
||||||
|
String pngUrl = jsonArray.getJSONObject(index).getString("url");
|
||||||
|
|
||||||
return pngUrl;
|
return pngUrl;
|
||||||
} catch (JSONException exception) {
|
} catch (JSONException exception) {
|
||||||
|
|||||||
@ -12,6 +12,8 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.annotation.OptIn;
|
import androidx.annotation.OptIn;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
|
import androidx.media3.common.MediaItem;
|
||||||
|
import androidx.media3.common.MediaMetadata;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
|
||||||
@ -25,9 +27,11 @@ import com.bumptech.glide.request.target.Target;
|
|||||||
import com.hi.music.player.MusicApplication;
|
import com.hi.music.player.MusicApplication;
|
||||||
import com.hi.music.player.R;
|
import com.hi.music.player.R;
|
||||||
import com.hi.music.player.api.MediaControllerListener;
|
import com.hi.music.player.api.MediaControllerListener;
|
||||||
|
import com.hi.music.player.api.onImageColorListener;
|
||||||
import com.hi.music.player.databinding.ActivityPlayBinding;
|
import com.hi.music.player.databinding.ActivityPlayBinding;
|
||||||
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.helper.MyValue;
|
||||||
|
import com.hi.music.player.javabean.CustomerUrlInfo;
|
||||||
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;
|
||||||
@ -71,34 +75,41 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
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);
|
||||||
|
initMediaController();
|
||||||
vmPlay.getPlayMusicList(responseSingle);
|
vmPlay.getPlayMusicList(responseSingle);
|
||||||
initPlayerView();
|
initPlayerView();
|
||||||
initMediaController();
|
|
||||||
initProgressHandler();
|
initProgressHandler();
|
||||||
|
|
||||||
vmPlay.playList.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 == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (playList.size() > 0) {
|
if (playList.size() > 0) {
|
||||||
requestPlayList = true;
|
requestPlayList = true;
|
||||||
mPlayList = playList;
|
mPlayList = playList;
|
||||||
musicInfo = playList.get(0);
|
musicInfo = playList.get(0);
|
||||||
loadCovert(musicInfo.getCovert());
|
|
||||||
loadInfo(musicInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
vmPlay.playUrlLiveData.observe(this, new Observer<Pair<ResponsePlayUrl, Integer>>() {
|
vmPlay.playUrlLiveData.observe(this, new Observer<CustomerUrlInfo>() {
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(Pair<ResponsePlayUrl, Integer> responsePlayUrlIntegerPair) {
|
public void onChanged(CustomerUrlInfo customerUrlInfo) {
|
||||||
|
if (customerUrlInfo.isNeedPlayNow() && customerUrlInfo.getPlayUrl() == null) {
|
||||||
|
// TODO: 2024/9/26 需要马上播放这首歌曲,但是此次网络请求失败
|
||||||
|
CommonUtils.LogMsg("-------------需要马上播放这首歌曲,但是此次网络请求失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
requestPlayUrl = true;
|
requestPlayUrl = true;
|
||||||
mCurPlayInfo = responsePlayUrlIntegerPair.first;
|
mCurPlayInfo = customerUrlInfo.getPlayUrl();
|
||||||
Integer second = responsePlayUrlIntegerPair.second;
|
int second = customerUrlInfo.getPlayMusicIndex();
|
||||||
CommonUtils.LogMsg("---------mCurPlayInfo=" + mCurPlayInfo.getAudioUrlLow());
|
boolean needPlayNow = customerUrlInfo.isNeedPlayNow();
|
||||||
updateAudioUrl(responsePlayUrlIntegerPair.first);
|
if (needPlayNow) {
|
||||||
if (second == 0) {
|
|
||||||
mediaControllerManager.play();
|
mediaControllerManager.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,40 +126,65 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
|
|
||||||
private void initMediaController() {
|
private void initMediaController() {
|
||||||
mediaControllerManager = MyMediaControllerManager.getInstance();
|
mediaControllerManager = MyMediaControllerManager.getInstance();
|
||||||
|
mediaControllerManager.resetPlayList();
|
||||||
mediaControllerManager.addListener(new MediaControllerListener() {
|
mediaControllerManager.addListener(new MediaControllerListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onPlayStatus(int playStatus) {
|
public void onPlayStatus(int playStatus) {
|
||||||
CommonUtils.LogMsg("-------------playStatus=" + playStatus);
|
|
||||||
switch (playStatus) {
|
switch (playStatus) {
|
||||||
case Player.STATE_IDLE:
|
case Player.STATE_IDLE:
|
||||||
|
CommonUtils.LogMsg("-------------playStatus=STATE_IDLE");
|
||||||
break;
|
break;
|
||||||
case Player.STATE_BUFFERING:
|
case Player.STATE_BUFFERING:
|
||||||
//快进没有缓冲的时候触发
|
//快进没有缓冲的时候触发
|
||||||
|
vb.btnPlay.setSelected(false);
|
||||||
vb.progressBarLoading.setVisibility(View.VISIBLE);
|
vb.progressBarLoading.setVisibility(View.VISIBLE);
|
||||||
CommonUtils.LogMsg("-------------duration STATE_BUFFERING=");
|
CommonUtils.LogMsg("-------------playStatus=STATE_BUFFERING");
|
||||||
break;
|
break;
|
||||||
case Player.STATE_READY:
|
case Player.STATE_READY:
|
||||||
|
vb.btnPlay.setSelected(true);
|
||||||
mHandler.post(mRunnable);
|
mHandler.post(mRunnable);
|
||||||
vb.progressBarLoading.setVisibility(View.GONE);
|
vb.progressBarLoading.setVisibility(View.GONE);
|
||||||
|
CommonUtils.LogMsg("-------------playStatus=STATE_READY");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Player.STATE_ENDED:
|
case Player.STATE_ENDED:
|
||||||
|
vb.btnPlay.setSelected(false);
|
||||||
|
CommonUtils.LogMsg("-------------playStatus=STATE_ENDED 播放完成");
|
||||||
mHandler.removeCallbacks(mRunnable); // 停止更新
|
mHandler.removeCallbacks(mRunnable); // 停止更新
|
||||||
updatePlayComplete();
|
updatePlayComplete();
|
||||||
|
mediaControllerManager.playNext();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestNextUri(String videoId, int playListIndex, boolean playNow) {
|
||||||
|
CommonUtils.LogMsg("------------onRequestNextUri= videoId=" + videoId);
|
||||||
|
if (playNow) {
|
||||||
|
vb.progressBarLoading.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
vmPlay.getPlayUrl(videoId, playListIndex, playNow);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChangeMusic(MediaItem mediaItem) {
|
||||||
|
loadInfo(mediaItem);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onInitClick() {
|
protected void onInitClick() {
|
||||||
vb.btnPlay.setOnClickListener(this::onClick);
|
vb.btnPlay.setOnClickListener(this);
|
||||||
vb.playProgress.setOnSeekBarChangeListener(this);
|
vb.playProgress.setOnSeekBarChangeListener(this);
|
||||||
|
vb.btnNext.setOnClickListener(this);
|
||||||
|
vb.btnPrevious.setOnClickListener(this);
|
||||||
|
vb.imBack.setOnClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -163,7 +199,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
|
|
||||||
String s = CommonUtils.convertMillisToTime(contentPos);
|
String s = CommonUtils.convertMillisToTime(contentPos);
|
||||||
|
|
||||||
CommonUtils.LogMsg("---------播放进度-----contentPos=" + contentPos + "-----缓冲进度=" + bufferPos);
|
// CommonUtils.LogMsg("---------播放进度-----contentPos=" + contentPos + "-----缓冲进度=" + bufferPos);
|
||||||
vb.tvCurrent.setText(s);
|
vb.tvCurrent.setText(s);
|
||||||
vb.playProgress.setProgress((int) contentPos);
|
vb.playProgress.setProgress((int) contentPos);
|
||||||
vb.progressBarBuffer.setProgress((int) bufferPos);
|
vb.progressBarBuffer.setProgress((int) bufferPos);
|
||||||
@ -179,34 +215,38 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化当前播放歌曲信息
|
* 加载当前播放歌曲信息
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
*/
|
*/
|
||||||
private void loadInfo(ResponsePlayListInfo data) {
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
vb.tvSongName.setText(data.getSongTitle());
|
private void loadInfo(MediaItem mediaItem) {
|
||||||
vb.tvSingerName.setText(data.getSingerName());
|
|
||||||
vb.tvDuration.setText(data.getDuration());
|
|
||||||
|
|
||||||
|
MediaMetadata mediaMetadata = mediaItem.mediaMetadata;
|
||||||
|
CommonUtils.LogMsg("--------------加载当前播放歌曲信息 "+mediaMetadata.description);
|
||||||
|
if (mediaMetadata.artworkUri != null) {
|
||||||
|
loadCovert(mediaMetadata.artworkUri.toString());
|
||||||
|
}
|
||||||
|
vb.tvSongName.setText(mediaMetadata.title);
|
||||||
|
vb.tvSingerName.setText(mediaMetadata.artist);
|
||||||
|
vb.tvDuration.setText(mediaMetadata.description);
|
||||||
|
|
||||||
long durationMs = data.getDurationMs();
|
if (mediaMetadata.durationMs != null) {
|
||||||
|
long durationMs = mediaMetadata.durationMs;
|
||||||
vb.playProgress.setMax((int) durationMs);
|
vb.playProgress.setMax((int) durationMs);
|
||||||
vb.progressBarBuffer.setMax((int) data.getDurationMs());
|
vb.progressBarBuffer.setMax((int) durationMs);
|
||||||
|
|
||||||
CommonUtils.LogMsg("--------------data.getDurationMs() 22222222222=" + durationMs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新音频url到播放列表
|
* 更新音频url到播放列表
|
||||||
*/
|
*/
|
||||||
private void updateAudioUrl(ResponsePlayUrl playUrl) {
|
private void updateAudioUrl(ResponsePlayUrl playUrl) {
|
||||||
mediaControllerManager.UpdateAudioUrl(playUrl);
|
// mediaControllerManager.UpdateAudioUrl(playUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void loadCovert(String url) {
|
private void loadCovert(String url) {
|
||||||
Glide.with(MusicApplication.myApplication)
|
Glide.with(MusicApplication.myApplication)
|
||||||
.asDrawable()
|
.asDrawable()
|
||||||
@ -223,12 +263,20 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
@OptIn(markerClass = UnstableApi.class)
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
@Override
|
@Override
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||||
vb.playerView.setDefaultArtwork(resource);
|
CommonUtils.extractDominantColor(resource, new onImageColorListener() {
|
||||||
|
@Override
|
||||||
|
public void onImageColor(int color) {
|
||||||
|
vb.rootLayout.setBackgroundColor(color);
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.into(vb.imCovert);
|
.into(vb.imCovert);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -245,7 +293,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFullScreen() {
|
public boolean isFullScreen() {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -262,6 +310,13 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
} else {
|
} else {
|
||||||
mediaControllerManager.pause();
|
mediaControllerManager.pause();
|
||||||
}
|
}
|
||||||
|
} else if (v.equals(vb.btnNext)) {
|
||||||
|
mediaControllerManager.playNext();
|
||||||
|
|
||||||
|
} else if (v.equals(vb.btnPrevious)) {
|
||||||
|
mediaControllerManager.playPrevious();
|
||||||
|
} else if (v.equals(vb.imBack)) {
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -277,7 +332,6 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
if (fromUser) {
|
if (fromUser) {
|
||||||
CommonUtils.LogMsg("---------onProgressChanged----progress=" + progress);
|
|
||||||
mediaControllerManager.getMediaController().seekTo(progress);
|
mediaControllerManager.getMediaController().seekTo(progress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import androidx.lifecycle.ViewModel;
|
|||||||
|
|
||||||
import com.hi.music.player.api.RequestListener;
|
import com.hi.music.player.api.RequestListener;
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
import com.hi.music.player.helper.CommonUtils;
|
||||||
|
import com.hi.music.player.javabean.CustomerUrlInfo;
|
||||||
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;
|
||||||
@ -28,10 +29,10 @@ public class VMPlay extends ViewModel {
|
|||||||
public LiveData<List<ResponsePlayListInfo>> playList = _playList;
|
public LiveData<List<ResponsePlayListInfo>> playList = _playList;
|
||||||
|
|
||||||
|
|
||||||
private MutableLiveData<Pair<ResponsePlayUrl, Integer>> _playUrlMutableLiveData = new MutableLiveData<Pair<ResponsePlayUrl, Integer>>();
|
private MutableLiveData<CustomerUrlInfo> _playUrlMutableLiveData = new MutableLiveData<CustomerUrlInfo>();
|
||||||
public LiveData<Pair<ResponsePlayUrl, Integer>> playUrlLiveData = _playUrlMutableLiveData;
|
public LiveData<CustomerUrlInfo> playUrlLiveData = _playUrlMutableLiveData;
|
||||||
|
|
||||||
|
|
||||||
private String continuation, clickTrackingParams, visitorData;
|
|
||||||
|
|
||||||
public void getPlayMusicList(ResponseSingle responseSingle) {
|
public void getPlayMusicList(ResponseSingle responseSingle) {
|
||||||
String playlistId = responseSingle.getPlaylistId();
|
String playlistId = responseSingle.getPlaylistId();
|
||||||
@ -51,9 +52,9 @@ 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);
|
||||||
MyMediaControllerManager.getInstance().addMusicPlayList(responsePlayListInfos);
|
MyMediaControllerManager.getInstance().setPlayList(responsePlayListInfos);
|
||||||
_playList.setValue(responsePlayListInfos);
|
_playList.setValue(responsePlayListInfos);
|
||||||
getPlayUrl(responseSingle,0);
|
getPlayUrl(responseSingle.getVideoId(),0,true);
|
||||||
} else {
|
} else {
|
||||||
_playList.setValue(null);
|
_playList.setValue(null);
|
||||||
}
|
}
|
||||||
@ -62,13 +63,14 @@ public class VMPlay extends ViewModel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getPlayUrl(ResponseSingle responseSingle, int playListIndex) {
|
public void getPlayUrl(String videoId, int playListIndex,boolean playNow) {
|
||||||
String videoId = responseSingle.getVideoId();
|
CustomerUrlInfo customerUrlInfo = new CustomerUrlInfo();
|
||||||
|
customerUrlInfo.setNeedPlayNow(playNow);
|
||||||
RetrofitManager.getInstance().getPlayUrl(videoId, new RequestListener<ResponseBody>() {
|
RetrofitManager.getInstance().getPlayUrl(videoId, new RequestListener<ResponseBody>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFail(String errorMsg) {
|
public void onFail(String errorMsg) {
|
||||||
_playUrlMutableLiveData.setValue(null);
|
_playUrlMutableLiveData.setValue(customerUrlInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -76,10 +78,12 @@ 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(new Pair<>(responsePlayUrl, playListIndex));
|
MyMediaControllerManager.getInstance().addMusicToPlayList(responsePlayUrl,playListIndex);
|
||||||
} else {
|
customerUrlInfo.setPlayUrl(responsePlayUrl);
|
||||||
_playUrlMutableLiveData.setValue(null);
|
customerUrlInfo.setPlayMusicIndex(playListIndex);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
_playUrlMutableLiveData.setValue(customerUrlInfo);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/black"
|
android:id="@+id/root_layout"
|
||||||
tools:context=".ui.activity.PlayActivity">
|
tools:context=".ui.activity.PlayActivity">
|
||||||
|
|
||||||
|
|
||||||
@ -189,10 +189,11 @@
|
|||||||
android:id="@+id/btn_music_list"
|
android:id="@+id/btn_music_list"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_marginBottom="40dp"
|
|
||||||
android:src="@mipmap/icon_list"
|
android:src="@mipmap/icon_list"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintTop_toTopOf="@id/btn_play"
|
||||||
app:layout_constraintLeft_toLeftOf="@id/im_covert" />
|
app:layout_constraintBottom_toBottomOf="@id/btn_play"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/btn_next" />
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
9
app/src/main/res/layout/dialog_play_list.xml
Normal file
9
app/src/main/res/layout/dialog_play_list.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Loading…
Reference in New Issue
Block a user