package com.weishitechsub.quanminchangKmianfei.fragment.home;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.hfd.common.base.BaseFragment;
import com.hfd.common.net.HttpBuiler;
import com.hfd.common.net.JsonGenericsSerializator;
import com.hfd.common.net.Url;
import com.hfd.common.util.DensityUtil;
import com.hfd.common.util.ToastUtil;
import com.hw.lrcviewlib.LrcRow;
import com.hw.lrcviewlib.LrcView;
import com.weishitechsub.quanminchangKmianfei.bean.MusicBean;
import com.weishitechsub.quanminchangKmianfei.dialog.PermissionDialog;
import com.weishitechsub.quanminchangKmianfei.utils.MusicCache;
import com.weishitechsub.quanminchangKmianfei.utils.MusicPlayerManager;
import com.weishitechsub.quanminchangKmianfei.utils.PermissionUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import pub.devrel.easypermissions.EasyPermissions;
import com.hfd.common.net.GenericsCallback;
import com.weishitechsub.quanminchangKmianfei.R;
import com.weishitechsub.quanminchangKmianfei.utils.OnMultiClickListener;
import okhttp3.Call;
/**
* 高端语音导航首页
*/
public class HomeFragment extends BaseFragment implements EasyPermissions.PermissionCallbacks{
ImageView iv_song,iv_xh,iv_sys,iv_bf,iv_xys,iv_xz;
TextView tv_start_time,tv_end_time,tv_no_lyric;
LrcView lyricView;
SeekBar seekbar;
private List<MusicBean.DataBean> restList = new ArrayList<>();
private List<MusicBean.DataBean> musicList; // 存储获取到的歌曲列表
private static final String[] PERMS_CAMERA = new String[] {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}; // 需要请求的权限数组
private static final int RC_CAMERA_PERM = 123; // 请求码,唯一标识
private static final int REQUEST_CODE_WRITE_SETTINGS = 101;
private AlertDialog progressDialog;
private Handler handler;
private Runnable updateProgressRunnable;
@Override
protected int setLayout() {
return R.layout.fragment_home;
}
@Override
protected void initView() {
iv_song = fvbi(R.id.iv_song);
lyricView = fvbi(R.id.lyricView);
tv_start_time = fvbi(R.id.tv_start_time);
seekbar = fvbi(R.id.seekbar);
tv_end_time = fvbi(R.id.tv_end_time);
iv_xh = fvbi(R.id.iv_xh);
iv_sys = fvbi(R.id.iv_sys);
iv_bf = fvbi(R.id.iv_bf);
iv_xys = fvbi(R.id.iv_xys);
iv_xz = fvbi(R.id.iv_xz);
tv_no_lyric = fvbi(R.id.tv_no_lyric);
// 设置最大值为100
seekbar.setMax(100);
initLyricStyle();
}
@Override
protected void initClick() {
iv_xz.setOnClickListener(new OnMultiClickListener() {
@Override
public void onMultiClick(View v) {
getSavePermissions();
}
});
iv_sys.setOnClickListener(v -> playPrevious()); // 上一首
iv_xys.setOnClickListener(v -> playNext()); // 下一首
iv_bf.setOnClickListener(v -> togglePlayPause()); // 播放/暂停
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
int duration = MusicPlayerManager.getInstance().getDuration();
int newPosition = (int) ((progress / 100.0) * duration);
MusicPlayerManager.getInstance().seekTo(newPosition);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});
}
@Override
protected void initData() {
musicAppInfo();
}
private void musicAppInfo() {
HashMap<String, String> map = new HashMap<>();
showDialog();
HttpBuiler.getInfo(Url.music, map).build().execute(
new GenericsCallback<MusicBean>(new JsonGenericsSerializator()) {
@Override
public void onError(Call call, Exception e, int id) {
dissmiss();
ToastUtil.showShortToast(e.getMessage());
}
@Override
public void onResponse(MusicBean response, int id) {
dissmiss();
if ("0".equals(response.getCode()) && response.getData() != null && !response.getData().isEmpty()) {
restList = response.getData();
// 获取第三条之后的数据(即从索引2开始到末尾)
musicList = new ArrayList<>(restList.subList(3, restList.size()));
MusicCache.setMainMusicList(musicList); // 缓存主列表
startPlaybackIfNeeded();
} else {
ToastUtil.showShortToast("暂无歌曲数据");
}
}
});
}
/**
* 设置歌词样式
*/
private void initLyricStyle(){
// 应用样式
lyricView.getLrcSetting()
.setTimeTextSize(40)
.setSelectLineColor(Color.parseColor("#FF000000"))
.setSelectLineTextSize(25)
.setNormalRowColor(Color.parseColor("#919191"))
.setHeightRowColor(Color.parseColor("#FF000000"))
.setNormalRowTextSize(DensityUtil.sp2px(getContext(), 17))
.setHeightLightRowTextSize(DensityUtil.sp2px(getContext(), 17))
.setTrySelectRowTextSize(DensityUtil.sp2px(getContext(), 17))
.setTimeTextColor(Color.parseColor("#FF000000"))
.setTrySelectRowColor(Color.parseColor("#FF000000"));
lyricView.commitLrcSettings();
}
/**
* 如果还没有播放,则自动播放第一首
*/
private void startPlaybackIfNeeded() {
if (musicList == null || musicList.isEmpty()) return;
// 默认从第0首开始播放(如果还没播放过)
if (MusicPlayerManager.getInstance().getCurrentPlayingPosition() == -1) {
playMusicByPosition(0);
} else {
updateUIWithCurrentSong(); // 否则刷新当前 UI
}
setupUpdateProgressWithHandler(); // 开始定时更新进度
}
/**
* 播放指定位置的歌曲
*/
private void playMusicByPosition(int position) {
if (musicList == null || position < 0 || position >= musicList.size()) return;
MusicBean.DataBean song = musicList.get(position);
String url = song.getMusic(); // 假设 getMusic() 返回音频 URL
MusicPlayerManager.getInstance().play(url, position);
}
/**
* 上一首
*/
private void playPrevious() {
if (musicList == null || musicList.isEmpty()) return;
int pos = MusicPlayerManager.getInstance().getCurrentPlayingPosition();
int prevPos = (pos - 1 + musicList.size()) % musicList.size(); // 循环上一首
playMusicByPosition(prevPos);
}
/**
* 下一首
*/
private void playNext() {
if (musicList == null || musicList.isEmpty()) return;
int pos = MusicPlayerManager.getInstance().getCurrentPlayingPosition();
int nextPos = (pos + 1) % musicList.size(); // 循环下一首
playMusicByPosition(nextPos);
}
/**
* 播放/暂停切换
*/
private void togglePlayPause() {
if (MusicPlayerManager.getInstance().isPlaying()) {
MusicPlayerManager.getInstance().pause();
} else {
MusicPlayerManager.getInstance().resume();
}
}
/**
* 更新 UI 显示当前歌曲信息(包括歌词、标题等)
*/
@SuppressLint("StaticFieldLeak")
private void updateUIWithCurrentSong() {
MusicBean.DataBean currentSong = MusicPlayerManager.getInstance().getCurrentPlayingSong();
if (currentSong == null) return;
String lrcText = currentSong.getLrc();
// List<LrcRow> lrcRows = new LrcDataBuilder().builtFromText(lrcText);
new AsyncTask<String, Void, List<LrcRow>>() {
@Override
protected List<LrcRow> doInBackground(String... params) {
return new LrcDataBuilder().builtFromText(params[0]);
}
@Override
protected void onPostExecute(List<LrcRow> rows) {
if (rows != null && !rows.isEmpty()) {
lyricView.setLrcData(rows);
tv_no_lyric.setVisibility(View.GONE);
} else {
lyricView.setLrcData(null);
tv_no_lyric.setVisibility(View.VISIBLE);
}
}
}.execute(lrcText);
// 更新时间(模拟或通过 MediaPlayer 获取)
int duration = MusicPlayerManager.getInstance().getDuration();
tv_end_time.setText(formatTime(duration));
}
/**
* 定时更新播放进度条和歌词
*/
private void setupUpdateProgressWithHandler() {
if (handler == null) {
handler = new Handler(Looper.getMainLooper());
}
// 定义循环任务
updateProgressRunnable = new Runnable() {
@Override
public void run() {
int currentPosition = MusicPlayerManager.getInstance().getCurrentPosition();
int duration = MusicPlayerManager.getInstance().getDuration();
if (duration > 0) {
// 更新进度条
int progress = (int) (((float) currentPosition / duration) * 100);
seekbar.setProgress(progress);
// 更新时间文本
tv_start_time.setText(formatTime(currentPosition));
//通知 LrcView 当前播放时间(毫秒)
lyricView.seekLrcToTime(currentPosition);
}
// 自动重复执行(每隔 500ms)
handler.postDelayed(this, 500);
}
};
// 开始执行
handler.post(updateProgressRunnable);
}
/**
* 格式化毫秒时间为 mm:ss
*/
private String formatTime(int timeMs) {
int totalSeconds = timeMs / 1000;
int minutes = totalSeconds / 60;
int seconds = totalSeconds % 60;
return String.format("%02d:%02d", minutes, seconds);
}
/**
* 绑定播放器状态监听器
*/
@Override
public void onResume() {
super.onResume();
MusicPlayerManager.getInstance().setOnPlaybackStateChangedListener(playbackListener);
if (musicList != null) {
updateUIWithCurrentSong();
setupUpdateProgressWithHandler();
}
}
@Override
public void onPause() {
super.onPause();
MusicPlayerManager.getInstance().setOnPlaybackStateChangedListener(null);
// 停止 Handler 循环
if (handler != null && updateProgressRunnable != null) {
handler.removeCallbacks(updateProgressRunnable);
}
}
@Override
public void onDestroy() {
super.onDestroy();
MusicPlayerManager.getInstance().release();
// 防止内存泄漏
if (handler != null) {
handler.removeCallbacksAndMessages(null); // 清空所有消息
handler = null;
}
}
// 播放状态监听器
private final MusicPlayerManager.OnPlaybackStateChangedListener playbackListener =
new MusicPlayerManager.OnPlaybackStateChangedListener() {
private int consecutiveErrorCount = 0; // 连续错误计数
private static final int MAX_CONSECUTIVE_ERRORS = 3;
@Override
public void onPlaying(int position) {
consecutiveErrorCount = 0; // 成功播放则清零
updatePlayButtonState(true);
updateUIWithCurrentSong();
}
@Override
public void onPaused() {
updatePlayButtonState(false);
}
@Override
public void onCompletion() {
playNext(); // 正常播放完成才切下一首
}
@Override
public void onError(String errorMsg) {
consecutiveErrorCount++;
Log.e("MusicPlayer", "播放错误 [" + consecutiveErrorCount + "]: " + errorMsg);
// 显示一次错误提示即可
if (consecutiveErrorCount == 1) {
ToastUtil.showShortToast("播放失败,跳过该歌曲");
}
// 防止无限循环:最多连续失败3次就停止
if (consecutiveErrorCount >= MAX_CONSECUTIVE_ERRORS) {
ToastUtil.showShortToast("连续播放失败,已暂停");
MusicPlayerManager.getInstance().pause();
return;
}
// 尝试播放下一首
playNext();
}
};
/**
* 更新播放按钮图标(播放/暂停)
*/
private void updatePlayButtonState(boolean isPlaying) {
if (isPlaying) {
iv_bf.setImageResource(R.mipmap.img_bf); // 替换为你自己的暂停图标
} else {
iv_bf.setImageResource(R.mipmap.img_bf); // 替换为你自己的播放图标
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
@Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
if(requestCode == RC_CAMERA_PERM){
saveCurrentSong();
}
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
}
// 内部歌词解析器
public static class LrcDataBuilder { // 加上 static
public List<LrcRow> builtFromText(String lrcText) {
List<LrcRow> rows = new ArrayList<>();
if (lrcText == null || lrcText.trim().isEmpty()) {
return rows;
}
String[] lines = lrcText.split("\\r?\\n");
for (String line : lines) {
line = line.trim();
if (line.isEmpty()) continue;
List<LrcRow> parsed = parseLrcLine(line);
if (!parsed.isEmpty()) {
rows.addAll(parsed);
}
}
Collections.sort(rows);
return rows;
}
private List<LrcRow> parseLrcLine(String line) {
List<LrcRow> result = new ArrayList<>();
if (line.isEmpty()) return result;
// 支持多种换行符预处理(避免后续污染)
line = line.replaceAll("[\\r\\n\\u2028\\u2029]+", " ");
Pattern pattern = Pattern.compile("\\[(\\d{1,2}):(\\d{2})(?:\\.(\\d{2,3}))?\\]");
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
int min = Integer.parseInt(matcher.group(1));
int sec = Integer.parseInt(matcher.group(2));
int milli = 0;
if (matcher.group(3) != null) {
milli = Integer.parseInt(matcher.group(3));
if (matcher.group(3).length() == 2) milli *= 10; // 补齐毫秒
}
long timeMillis = (min * 60L + sec) * 1000 + milli;
int textStart = matcher.end();
int textEnd = line.length();
// 查找下一个时间标签作为结束点
Matcher nextMatcher = pattern.matcher(line);
if (nextMatcher.find(matcher.start() + 1)) {
textEnd = nextMatcher.start();
}
String rawText = line.substring(textStart, textEnd).trim();
// 再次防御性清理各种空白与特殊字符
String text = rawText
.replaceAll("[\\p{Cc}\\p{Cf}&&[^\\t]]", " ") // 移除控制字符
.replace((char) 0xA0, ' ') // 不间断空格
.replaceAll("\\s+", " ") // 多空格合并
.trim();
if (!text.isEmpty()) {
result.add(new LrcRow(text, matcher.group(0), timeMillis));
}
}
return result;
}
}
private void getSavePermissions() {
if (!PermissionUtils.hasStoragePermissions(getActivity())) {
new PermissionDialog(getActivity(), "权限说明:由于下载歌曲,需要相应的存储权限。拒绝将无法使用此功能").show();
PermissionUtils.requestStoragePermissions(getActivity(), RC_CAMERA_PERM);
} else {
saveCurrentSong(); // 改为保存当前歌曲
}
}
private void saveCurrentSong() {
int pos = MusicPlayerManager.getInstance().getCurrentPlayingPosition();
if (pos == -1) {
ToastUtil.showShortToast("没有正在播放的歌曲");
return;
}
MusicBean.DataBean song = musicList.get(pos);
if (song == null || song.getMusic() == null) {
ToastUtil.showShortToast("歌曲信息不完整");
return;
}
showProgressDialog(getActivity());
new SaveTask(song).execute(); // 传入整个 song 对象更安全
}
private void showProgressDialog(Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("正在保存...");
builder.setCancelable(false);
progressDialog = builder.create();
progressDialog.show();
}
private class SaveTask extends AsyncTask<Void, Void, Boolean> {
private final MusicBean.DataBean song;
private String targetPath;
private Exception exception;
SaveTask(MusicBean.DataBean song) {
this.song = song;
}
@Override
protected Boolean doInBackground(Void... voids) {
try {
String urlStr = song.getMusic();
String fileName = song.getTitle();
if (fileName == null) fileName = "music_" + System.currentTimeMillis();
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
if (!dir.exists()) dir.mkdirs();
targetPath = new File(dir, fileName + ".mp3").getAbsolutePath();
InputStream inputStream = new java.net.URL(urlStr).openStream();
FileOutputStream outStream = new FileOutputStream(targetPath);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
outStream.flush();
outStream.close();
inputStream.close();
// 通知媒体库刷新
Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
scanIntent.setData(Uri.fromFile(new File(targetPath)));
getActivity().sendBroadcast(scanIntent);
return true;
} catch (Exception e) {
e.printStackTrace();
exception = e;
return false;
}
}
@Override
protected void onPostExecute(Boolean success) {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
if (success) {
Toast.makeText(getActivity(), "音乐已保存至: " + targetPath, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getActivity(), "保存失败: " + (exception != null ? exception.getMessage() : "未知错误"), Toast.LENGTH_SHORT).show();
}
}
}
}package com.weishitechsub.quanminchangKmianfei.utils;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.NonNull;
import com.weishitechsub.quanminchangKmianfei.bean.MusicBean;
import java.util.List;
public class MusicPlayerManager {
private static volatile MusicPlayerManager instance; // 双检锁
private MediaPlayer mediaPlayer;
private OnPlaybackStateChangedListener listener;
private int currentPlayingPosition = -1; // 当前主列表播放位置
private String currentPlayingUrl = null;
// 私有构造
private MusicPlayerManager() {
// MediaPlayer 初始化延迟到首次使用
}
// 获取单例
public static MusicPlayerManager getInstance() {
if (instance == null) {
synchronized (MusicPlayerManager.class) {
if (instance == null) {
instance = new MusicPlayerManager();
}
}
}
return instance;
}
// 播放状态监听器
public interface OnPlaybackStateChangedListener {
void onPlaying(int position);
void onPaused();
void onCompletion();
void onError(String errorMsg);
}
public void setOnPlaybackStateChangedListener(OnPlaybackStateChangedListener listener) {
this.listener = listener;
}
/**
* 播放主列表中的歌曲
*/
public void play(@NonNull String musicUrl, int position) {
// 如果正在播放同一首歌,直接返回
if (position == currentPlayingPosition && mediaPlayer != null && mediaPlayer.isPlaying()
&& musicUrl.equals(currentPlayingUrl)) {
return;
}
// 如果切换了歌曲或 URL 不同,则需要重置播放器状态
if (!musicUrl.equals(currentPlayingUrl) || mediaPlayer == null) {
try {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
} catch (Exception e) {
// 忽略停止异常
}
prepareAndPlay(musicUrl, () -> {
currentPlayingPosition = position;
currentPlayingUrl = musicUrl;
if (listener != null) listener.onPlaying(position);
});
} else {
// 同一 URL,但未播放 → 直接 start
try {
int currentPosition = mediaPlayer.getCurrentPosition();
int duration = mediaPlayer.getDuration();
if (duration <= 0 || currentPosition < duration - 100) {
mediaPlayer.start();
if (listener != null) listener.onPlaying(position);
} else {
// 已结束,重新 prepare
mediaPlayer.seekTo(0);
mediaPlayer.start();
if (listener != null) listener.onPlaying(position);
}
} catch (Exception e) {
// 出错则重新准备
prepareAndPlay(musicUrl, () -> {
currentPlayingPosition = position;
currentPlayingUrl = musicUrl;
if (listener != null) listener.onPlaying(position);
});
}
}
}
/**
* 内部方法:准备并播放音乐
*/
private void prepareAndPlay(String musicUrl, Runnable onPreparedAction) {
try {
boolean needNewPlayer = (mediaPlayer == null);
if (needNewPlayer) {
mediaPlayer = new MediaPlayer();
setupListeners();
} else {
// 使用 try-catch 防止 reset 期间异常,并确保状态复位成功
try {
mediaPlayer.reset();
} catch (IllegalStateException e) {
// 某些设备可能在此处抛出异常
Log.e("MusicPlayer", "reset failed, recreating MediaPlayer", e);
mediaPlayer.release();
mediaPlayer = new MediaPlayer();
setupListeners();
}
}
// 设置音频属性
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build());
} else {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
// 添加准备前的状态检查:使用 post 延迟执行,确保 reset 完成
final String url = musicUrl;
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(() -> {
try {
mediaPlayer.setDataSource(url);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(mp -> {
mp.start();
onPreparedAction.run();
});
} catch (Exception e) {
e.printStackTrace();
if (listener != null) {
listener.onError("无法设置数据源: " + e.getMessage());
}
}
}, 50); // 给 reset 留出一点时间(50ms 足够)
} catch (Exception e) {
e.printStackTrace();
if (listener != null) {
listener.onError("初始化失败: " + e.getMessage());
}
}
}
/**
* 设置 MediaPlayer 回调监听
*/
private void setupListeners() {
mediaPlayer.setOnCompletionListener(mp -> {
if (listener != null) {
listener.onCompletion();
}
});
mediaPlayer.setOnErrorListener((mp, what, extra) -> {
if (listener != null) {
listener.onError("播放错误: code=" + what + ", extra=" + extra);
}
return true; // 消费错误,不进入默认行为
});
}
/**
* 暂停播放
*/
public void pause() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
if (listener != null) {
listener.onPaused();
}
}
}
/**
* 继续播放
*/
public void resume() {
if (mediaPlayer != null && !mediaPlayer.isPlaying() && currentPlayingUrl != null) {
mediaPlayer.start();
if (listener != null) {
listener.onPlaying(currentPlayingPosition);
}
}
}
/**
* 是否正在播放
*/
public boolean isPlaying() {
return mediaPlayer != null && mediaPlayer.isPlaying();
}
/**
* 获取当前播放的位置(主列表索引)
*/
public int getCurrentPlayingPosition() {
return currentPlayingPosition;
}
/**
* 获取当前播放的音乐 URL
*/
public String getCurrentPlayingMusicUrl() {
return currentPlayingUrl;
}
/**
* 获取当前播放的歌曲信息(从主列表中查找)
*/
public MusicBean.DataBean getCurrentPlayingSong() {
List<MusicBean.DataBean> mainList = MusicCache.getMainMusicList();
if (mainList != null && currentPlayingPosition >= 0 && currentPlayingPosition < mainList.size()) {
MusicBean.DataBean song = mainList.get(currentPlayingPosition);
if (song != null && song.getMusic().equals(currentPlayingUrl)) {
return song;
}
}
// 回退:根据 URL 查找
if (mainList != null && currentPlayingUrl != null) {
for (int i = 0; i < mainList.size(); i++) {
MusicBean.DataBean song = mainList.get(i);
if (song != null && song.getMusic().equals(currentPlayingUrl)) {
currentPlayingPosition = i; // 自动修正索引
return song;
}
}
}
return null;
}
/**
* 获取当前播放列表(即主列表)
*/
public List<MusicBean.DataBean> getCurrentPlayingList() {
return MusicCache.getMainMusicList();
}
/**
* 跳转到指定时间
*/
public void seekTo(int milliseconds) {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
try {
mediaPlayer.seekTo(milliseconds);
} catch (IllegalStateException e) {
// 当前未初始化或未准备好
Log.e("MusicPlayer", "seekTo failed: not prepared", e);
}
}
}
/**
* 获取当前播放进度(毫秒)
*/
public int getCurrentPosition() {
if (mediaPlayer != null) {
try {
return mediaPlayer.getCurrentPosition();
} catch (IllegalStateException e) {
return 0;
}
}
return 0;
}
/**
* 获取音频总时长(毫秒)
*/
public int getDuration() {
if (mediaPlayer != null) {
try {
return mediaPlayer.getDuration();
} catch (IllegalStateException e) {
return 0;
}
}
return 0;
}
/**
* 释放 MediaPlayer 资源
*/
public void release() {
if (mediaPlayer != null) {
try {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
} catch (Exception e) {
// 忽略异常
} finally {
mediaPlayer.release();
mediaPlayer = null;
}
}
currentPlayingPosition = -1;
currentPlayingUrl = null;
}
}
播放错误: code=-38, extra=0一直弹这个提示框可能是因为请求接口获取的歌曲没有加载完毕就想要播放这个怎么修改