如何让MediaPlayer通过URL链接在线播放音乐?现有本地播放代码如何改造
MediaPlayer网络音频播放适配方案
前置配置
首先在AndroidManifest.xml中添加必要配置:
<!-- 网络访问权限 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 如果使用HTTP明文链接,需要在application节点添加如下配置 --> <application ... android:usesCleartextTraffic="true"> ... </application>
核心改造逻辑
原有MediaPlayer.create()方法仅适用于加载本地内置资源,加载网络资源需要改用异步初始化+准备回调的逻辑,避免主线程阻塞、调用方法抛出异常等问题。
改造后代码示例
// 替换原有MediaPlayer.create行,改为手动初始化 mediaPlayer = new MediaPlayer(); // 设置音频流类型为音乐 mediaPlayer.setAudioAttributes( new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ); try { // 替换为你的音乐URL链接 mediaPlayer.setDataSource("https://你的音乐链接地址.mp3"); // 异步准备,禁止调用prepare()阻塞主线程 mediaPlayer.prepareAsync(); } catch (IOException e) { e.printStackTrace(); // 此处可添加链接无效、网络异常的提示逻辑 } runnable = new Runnable() { @Override public void run() { if(mediaPlayer != null && mediaPlayer.isPlaying()) { seekBar.setProgress(mediaPlayer.getCurrentPosition()); } handler.postDelayed(this,500); } }; // 准备完成回调,所有依赖MediaPlayer就绪的逻辑都要放到这里 mediaPlayer.setOnPreparedListener(mp -> { int duration = mp.getDuration(); String sDuration = convertFormat(duration); playerDuration.setText(sDuration); seekBar.setMax(duration); // 准备完成后再开放播放按钮点击权限 btPlay.setEnabled(true); }); btPlay.setOnClickListener(v -> { mediaPlayer.start(); handler.postDelayed(runnable, 0); btPlay.setVisibility(View.GONE); btPause.setVisibility(View.VISIBLE); }); btPause.setOnClickListener(v -> { mediaPlayer.pause(); btPlay.setVisibility(View.VISIBLE); btPause.setVisibility(View.GONE); handler.removeCallbacks(runnable); }); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean b) { if (b && mediaPlayer != null) { mediaPlayer.seekTo(progress); } if(mediaPlayer != null) { playerPosition.setText(convertFormat(mediaPlayer.getCurrentPosition())); } } @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} }); mediaPlayer.setOnCompletionListener(mp -> { btPause.setVisibility(View.GONE); btPlay.setVisibility(View.VISIBLE); mediaPlayer.seekTo(0); handler.removeCallbacks(runnable); }); // 页面销毁时释放资源避免内存泄漏 @Override protected void onDestroy() { super.onDestroy(); if(mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; } handler.removeCallbacks(runnable); }
注意事项
- 初始化阶段要捕获
setDataSource相关的异常,处理无效链接、无网络等异常场景 - 所有调用MediaPlayer方法的位置都要加非空判断,避免空指针异常
- 禁止在主线程调用
prepare()方法,必须使用prepareAsync()异步加载,否则网络较差时会触发ANR - 页面退出或者切换音频时要及时释放MediaPlayer资源
内容的提问来源于stack exchange,提问作者user15583048
相关产品推荐
相关产品推荐

