安卓足球弹跳记录APP声音级别(Sound Level)始终显示0.0求助
解决声音级别振幅始终显示0.0的问题
作为第一次用Java开发Android应用的新手,遇到这种功能卡壳的情况太正常啦!结合你描述的场景,咱们一步步来排查最可能导致振幅一直显示0.0的原因:
1. 首先检查录音权限是否配置正确
Android系统对录音有严格的权限要求,这是最容易踩的坑:
- 在
AndroidManifest.xml里添加静态权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 如果用MediaRecorder保存文件的话需要 -->
- 对于Android 6.0(API 23)及以上版本,还要在代码中动态申请权限:
private static final int REQUEST_RECORD_AUDIO_PERMISSION = 200; private boolean permissionToRecordAccepted = false; private String[] permissions = {Manifest.permission.RECORD_AUDIO}; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... 其他初始化代码 ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) { permissionToRecordAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED; } if (!permissionToRecordAccepted) finish(); }
2. 检查音频录制组件的初始化与振幅获取逻辑
你目前只贴了代码开头,大概率是音频录制的初始化或者振幅获取方法有问题,这里给你两种常用的实现方式参考:
方式一:使用MediaRecorder获取振幅
private MediaRecorder mediaRecorder; private TextView soundLevelTv; private Handler handler = new Handler(); private Runnable updateSoundLevelRunnable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); soundLevelTv = findViewById(R.id.sound_level_tv); // 确保你的TextView ID正确 // 初始化MediaRecorder mediaRecorder = new MediaRecorder(); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mediaRecorder.setOutputFile(getCacheDir().getAbsolutePath() + "/temp_audio.3gp"); // 临时文件 try { mediaRecorder.prepare(); mediaRecorder.start(); } catch (IOException e) { e.printStackTrace(); } // 定时更新振幅 updateSoundLevelRunnable = new Runnable() { @Override public void run() { if (mediaRecorder != null) { int amplitude = mediaRecorder.getMaxAmplitude(); // 转换为0.0-1.0的浮点数显示(根据需求调整) float soundLevel = amplitude / 32767.0f; soundLevelTv.setText(String.format("%.1f", soundLevel)); } handler.postDelayed(this, 100); // 每100ms更新一次 } }; handler.post(updateSoundLevelRunnable); } @Override protected void onDestroy() { super.onDestroy(); if (mediaRecorder != null) { mediaRecorder.stop(); mediaRecorder.release(); mediaRecorder = null; } handler.removeCallbacks(updateSoundLevelRunnable); }
注意:
getMaxAmplitude()第一次调用会返回0,之后每次调用会返回上次调用以来的最大振幅,所以定时调用才能拿到实时数值。
方式二:使用AudioRecord获取更精准的振幅
如果需要更实时的音频数据,可以用AudioRecord:
private AudioRecord audioRecord; private TextView soundLevelTv; private Thread recordThread; private boolean isRecording = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); soundLevelTv = findViewById(R.id.sound_level_tv); // 配置AudioRecord参数 int sampleRate = 44100; int channelConfig = AudioFormat.CHANNEL_IN_MONO; int audioFormat = AudioFormat.ENCODING_PCM_16BIT; int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelConfig, audioFormat, bufferSize); // 启动录音线程 isRecording = true; recordThread = new Thread(new Runnable() { @Override public void run() { audioRecord.startRecording(); short[] buffer = new short[bufferSize]; while (isRecording) { int readSize = audioRecord.read(buffer, 0, bufferSize); if (readSize > 0) { // 计算当前缓冲区的最大振幅 int maxAmplitude = 0; for (short s : buffer) { int amplitude = Math.abs(s); if (amplitude > maxAmplitude) { maxAmplitude = amplitude; } } float soundLevel = maxAmplitude / 32767.0f; // 回到主线程更新UI runOnUiThread(new Runnable() { @Override public void run() { soundLevelTv.setText(String.format("%.1f", soundLevel)); } }); } } audioRecord.stop(); audioRecord.release(); } }); recordThread.start(); } @Override protected void onDestroy() { super.onDestroy(); isRecording = false; try { recordThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } }
3. 检查TextView的关联是否正确
确认你在代码中通过findViewById正确获取了TextView实例,并且布局文件中的ID和代码里的一致,不然就算计算出了振幅,也没法显示到屏幕上。
如果按照上面的步骤排查后还是有问题,可以把你完整的音频录制相关代码贴出来,这样能更精准地定位问题哦!
内容的提问来源于stack exchange,提问作者RubenDefour
相关产品推荐
相关产品推荐

