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

如何在Android Studio中循环遍历二进制串播放对应20ms音频

问题根因
  • 你写的for循环直接连续调用MediaPlayer.start(),该方法是异步执行的,不会阻塞线程等待音频播放完成,相当于所有比特对应的音频播放指令会在几毫秒内全部触发,自然会出现播放顺序混乱、音频重叠的问题
  • 你将setOnCompletionListener监听设置放在了for循环执行之后,调用start()时监听还未挂载,且播放完成后直接执行release()释放资源,后续要复用同一个MediaPlayer实例播放时会直接报错
  • 20ms属于极短音频,MediaPlayer本身的启动、加载延迟较高,并不适配这类短音频高频连续播放的场景,更推荐使用SoundPool实现
修复后实现代码
import android.media.AudioAttributes;
import android.media.SoundPool;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private SoundPool soundPool;
    private int sound1200;
    private int sound1600;
    private String binString = "011100101010111010101011101000";
    private int currentIndex = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化SoundPool
        AudioAttributes audioAttributes = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_MEDIA)
                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                .build();
        soundPool = new SoundPool.Builder()
                .setMaxStreams(1) // 同时只允许1个音频流播放,避免重叠
                .setAudioAttributes(audioAttributes)
                .build();

        // 加载两个音频文件
        sound1200 = soundPool.load(this, R.raw.wave1200hz, 1);
        sound1600 = soundPool.load(this, R.raw.wave1600hz, 1);

        // 音频加载完成监听,加载完成后开始播放
        soundPool.setOnLoadCompleteListener((soundPool, sampleId, status) -> {
            if (currentIndex == 0) {
                playNextBit();
            }
        });
    }

    private void playNextBit() {
        if (currentIndex >= binString.length()) {
            // 所有比特播放完成,释放资源
            soundPool.release();
            soundPool = null;
            return;
        }

        char bit = binString.charAt(currentIndex);
        int soundId = bit == '0' ? sound1200 : sound1600;

        // 播放当前比特对应的音频
        soundPool.play(soundId, 1, 1, 1, 0, 1.0f);
        currentIndex++;

        // 20ms后播放下一个比特,和音频时长对齐
        getWindow().getDecorView().postDelayed(this::playNextBit, 20);
    }

    // 页面销毁时释放资源,避免内存泄漏
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (soundPool != null) {
            soundPool.release();
            soundPool = null;
        }
    }
}
代码逻辑说明
  • 用SoundPool提前加载两个短音频,启动延迟远低于MediaPlayer,适配短音频高频播放场景
  • 设置setMaxStreams(1)保证同一时间只有一个音频播放,不会出现重叠
  • 采用递归+延迟调用的方式,每播放完一个20ms音频后再处理下一个比特位,严格保证播放顺序
  • 增加了资源释放逻辑,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 20:15:02