Android Java词典应用:dictionaryapi.dev音频播放失败求助
DictionaryAPI音频播放问题排查与解决方案
问题详情
- 开发环境:Android Java词典应用,基于Retrofit获取DictionaryAPI数据,RecyclerView展示内容
- 错误表现:点击音频图标播放
https://api.dictionaryapi.dev/media/pronunciations/en/{word}-us.mp3时,Logcat输出错误:E/MediaPlayerNative: error (1, -2147483648) E/MediaPlayer: Error (1,-2147483648) E/AUDIO_ERROR: MediaPlayer exception: null - 验证情况:其他第三方音频链接(MP3/WAV/FLAC/OGG格式)均可正常播放,仅该API的音频链接失效
相关代码
public class PhoneticAdapter extends RecyclerView.Adapter<PhoneticVH> { private final Context context; private List<Phonetic> phoneticList; private MediaPlayer player; public PhoneticAdapter(Context context, List<Phonetic> phoneticList) { this.context = context; this.phoneticList = phoneticList; } @NonNull @Override public PhoneticVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { return new PhoneticVH(LayoutInflater.from(context).inflate(R.layout.phonetic_list_items, parent, false)); } @Override public void onBindViewHolder(@NonNull PhoneticVH holder, @SuppressLint("RecyclerView") int position) { holder.phonetic_text.setText(phoneticList.get(position).getText()); holder.phonetic_audio.setOnClickListener(view -> { // String audioUrl = "https://" + phoneticList.get(position).getAudio(); player = new MediaPlayer(); try{ AudioAttributes audioAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build(); player.setAudioAttributes(audioAttributes); // player.setDataSource("https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"); // player.setDataSource("https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3"); // player.setDataSource("https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba-online-audio-converter.com_-1.wav"); // player.setDataSource("https://www.learningcontainer.com/wp-content/uploads/2020/02/Sample-FLAC-File.flac"); // player.setDataSource("https://www.learningcontainer.com/wp-content/uploads/2020/02/Sample-OGG-File.ogg"); player.setDataSource("https://" + phoneticList.get(position).getAudio()); player.setOnPreparedListener(mp -> { mp.start(); }); player.setOnErrorListener((mediaPlayer, i, i1) -> { Log.e("AUDIO_ERROR", "MediaPlayer error: " + i); Toast.makeText(context, "Error: " + i, Toast.LENGTH_SHORT).show(); return false; }); player.prepareAsync(); player.prepare(); player.start(); }catch (Exception e){ Log.e("AUDIO_ERROR", "MediaPlayer exception: " + e.getMessage()); Toast.makeText(context, R.string.audio_fail, Toast.LENGTH_SHORT).show(); } }); } @Override public int getItemCount() { if (phoneticList == null) { return 0; } return phoneticList.size(); } @SuppressLint("NotifyDataSetChanged") public void setData(List<Phonetic> phoneticList) { this.phoneticList = phoneticList; notifyDataSetChanged(); } }
问题排查与解决
1. 先修复代码本身的错误
你的代码中同时调用了prepareAsync()和prepare(),这两个方法互斥:
prepareAsync()是异步加载音频,需通过OnPreparedListener回调触发播放prepare()是同步加载,会阻塞线程
同时调用会直接导致MediaPlayer异常,这是当前报错的核心原因之一。修改后的播放逻辑如下:
holder.phonetic_audio.setOnClickListener(view -> { // 先释放旧的MediaPlayer实例,避免内存泄漏 if (player != null) { player.release(); player = null; } player = new MediaPlayer(); try{ AudioAttributes audioAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) // 发音用SPEECH更合适 .build(); player.setAudioAttributes(audioAttributes); String audioUrl = "https://" + phoneticList.get(position).getAudio(); player.setDataSource(audioUrl); player.setOnPreparedListener(mp -> mp.start()); player.setOnErrorListener((mediaPlayer, errorCode, extraCode) -> { Log.e("AUDIO_ERROR", "错误码: " + errorCode + ", 额外码: " + extraCode); Toast.makeText(context, R.string.audio_fail, Toast.LENGTH_SHORT).show(); // 释放异常的MediaPlayer mediaPlayer.release(); return true; }); // 仅调用异步准备,避免阻塞UI线程 player.prepareAsync(); }catch (Exception e){ Log.e("AUDIO_ERROR", "播放异常: " + e.getMessage()); Toast.makeText(context, R.string.audio_fail, Toast.LENGTH_SHORT).show(); if (player != null) { player.release(); player = null; } } });
2. 若问题源于API的处理方案
如果修复代码后仍无法播放,大概率是API返回的音频存在兼容性问题:
- 验证音频有效性:直接在浏览器中打开目标音频链接,确认是否能正常下载播放;若返回404/403,说明API无该词的发音资源
- 替换播放器:Android原生MediaPlayer对某些MP3编码(如特定比特率、采样率)支持有限,推荐改用ExoPlayer,它支持更多音频格式和流协议,兼容性更好
- 缓存音频到本地:先通过OkHttp将音频下载到本地,再用MediaPlayer播放本地文件,绕开在线流的兼容性问题
3. 更换音频链接的对接方案
若要替换为其他词典API的音频源,只需调整以下环节:
- Retrofit数据解析:修改接口返回的实体类(Phonetic),将新API的音频链接字段映射到
audio属性 - 保持播放逻辑不变:修复后的MediaPlayer/ExoPlayer播放逻辑无需改动,只要
phoneticList.get(position).getAudio()能返回有效的音频链接即可 - 适配新链接格式:如果新API的音频链接已包含
https://前缀,去掉代码中手动拼接的"https://",避免重复拼接导致无效链接
内容的提问来源于stack exchange,提问作者Sana Momin
相关产品推荐
相关产品推荐

