You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MediaPlayer.create()出现“Unable to match desired swap behavior”错误的原因

Android MediaPlayer崩溃排查与解决方案

问题背景

用AIDE开发Android应用,包含MainActivity.java和M4APlayer.java两个文件:

  • MainActivity中为名为sugar的EditText添加文本变化监听器,输入1-4时对应四个血糖场景,将场景文本传入M4APlayer.play()方法
  • 添加MediaPlayer.create()后应用崩溃,报错:

Unable to match the desired swap behavior

崩溃原因

核心问题出在M4APlayer.java的代码中:

MediaPlayer mp = MediaPlayer.create(context, R.id.scenario1);

这里错误地传入了布局控件的ID(R.id.scenario1是EditText控件的ID),而MediaPlayer.create()的第二个参数要求的是res/raw目录下的音频资源ID(比如R.raw.scenario1)。资源类型不匹配直接导致了崩溃。

代码修正步骤

1. 准备音频资源

将四个场景对应的m4a音频文件放入res/raw目录(若没有raw目录,在res下新建),命名为scenario1.m4a、scenario2.m4a、scenario3.m4a、scenario4.m4a。

2. 修正M4APlayer.java

根据传入的场景文本匹配对应的音频资源ID,同时完善MediaPlayer的资源管理:

package com.UnitedToolsForSouls.SoundAlert;

import android.content.Context;
import android.media.MediaPlayer;

public class M4APlayer {
    public static void play(Context context, String scenarioText) {
        int soundResId = 0;
        // 根据场景文本匹配音频资源,需与scenario输入框的实际文本对应
        switch(scenarioText) {
            case "血糖低且下降":
                soundResId = R.raw.scenario1;
                break;
            case "血糖低且上升":
                soundResId = R.raw.scenario2;
                break;
            case "血糖高且下降":
                soundResId = R.raw.scenario3;
                break;
            case "血糖高且上升":
                soundResId = R.raw.scenario4;
                break;
        }

        if (soundResId != 0) {
            MediaPlayer mp = MediaPlayer.create(context, soundResId);
            if (mp != null) {
                mp.start();
                // 播放完成后自动释放资源,避免内存泄漏
                mp.setOnCompletionListener(mediaPlayer -> mediaPlayer.release());
            }
        }
    }
}

3. 修正MainActivity.java的类型错误

原代码中scenario1-scenario4被声明为TextView,但实际是EditText控件,修正类型声明:

// 原错误代码
// private static TextView scenario1;
// 修正为
private static EditText scenario1;
private static EditText scenario2;
private static EditText scenario3;
private static EditText scenario4;

4. 优化文本监听逻辑

onTextChanged会在文本变化过程中多次触发,建议移到afterTextChanged中处理,避免重复调用播放:

@Override
public void afterTextChanged(Editable s) {
    String sug = s.toString();
    String s1 = scenario1.getText().toString();
    String s2 = scenario2.getText().toString();
    String s3 = scenario3.getText().toString();
    String s4 = scenario4.getText().toString();

    result.setText("???");
    if (sug.length() == 1) {
        switch(sug.charAt(0)) {
            case '1':
                result.setText(s1);
                break;
            case '2':
                result.setText(s2);
                break;
            case '3':
                result.setText(s3);
                break;
            case '4':
                result.setText(s4);
                break;
        }
        M4APlayer.play(context, result.getText().toString());
    }
}

关于MediaPlayer.create()参数的疑问

MediaPlayer.create()的第二个参数是整数而非字符串,原因是:

  • Android资源系统会将res目录下的所有资源(音频、布局、图片等)编译为唯一的整数ID,这种方式比字符串更高效,能避免文件名拼写错误
  • 系统可以通过ID更好地管理资源(比如适配不同设备、语言的资源变体)
  • 如果需要通过文件名字符串加载音频,可以将文件放入assets目录,通过AssetManager获取输入流后初始化MediaPlayer,但MediaPlayer.create()本身仅支持资源ID的方式。

内容的提问来源于stack exchange,提问作者Michael Lowe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 17:52:33