【问题标题】:Android AudioRecord won't initializeAndroid AudioRecord 不会初始化
【发布时间】:2023-03-13 18:30:01
【问题描述】:

我正在尝试实现一个应用程序,它可以监听麦克风输入(特别是呼吸),并根据它呈现数据。我正在使用 Android 类 AudioRecord,在尝试实例化 AudioRecord 时出现三个错误。

AudioRecord: AudioFlinger could not create record track, status: -1
AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -1.
android.media.AudioRecord: Error code -20 when initializing native AudioRecord object.

我发现了这个很棒的帖子:AudioRecord object not initializing

我从已接受的答案中借用了代码,该代码尝试了所有采样率、音频格式和通道配置以尝试解决问题,但没有帮助,我在所有设置中都出现上述错误。根据线程中的一个答案,我还在几个地方添加了对 AudioRecord.release() 的调用,但没有任何区别。

这是我的代码:

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;

public class SoundMeter {

private AudioRecord ar = null;
private int minSize;
private static int[] mSampleRates = new int[] { 8000, 11025, 22050, 32000, 44100 };

public boolean start() {
    ar = findAudioRecord();
    if(ar != null){
        ar.startRecording();
        return true;
    }
    else{
        Log.e("SoundMeter", "ERROR, could not create audio recorder");
        return false;
    }
}

public void stop() {
    if (ar != null) {
        ar.stop();
        ar.release();
    }
}

public double getAmplitude() {
    short[] buffer = new short[minSize];
    ar.read(buffer, 0, minSize);
    int max = 0;
    for (short s : buffer)
    {
        if (Math.abs(s) > max)
        {
            max = Math.abs(s);
        }
    }
    return max;
}

public AudioRecord findAudioRecord() {
    for (int rate : mSampleRates) {
        for (short audioFormat : new short[] { AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT, AudioFormat.ENCODING_PCM_FLOAT }) {
            for (short channelConfig : new short[] { AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO }) {
                try {
                    Log.d("SoundMeter", "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig);
                    int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);

                    if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
                        // check if we can instantiate and have a success
                        Log.d("SoundMeter", "Found a supported bufferSize, attempting to instantiate");
                        AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize);

                        if (recorder.getState() == AudioRecord.STATE_INITIALIZED){
                            minSize = bufferSize;
                            return recorder;
                        }
                        else
                            recorder.release();
                    }
                } catch (Exception e) {
                    Log.e("SoundMeter", rate + " Exception, keep trying.", e);
                }
            }
        }
    }
    return null;
}

}

我也添加了

<uses-permission android:name="android.permission.RECORD_AUDIO"/>

标记到我的清单文件,根据上述线程中的其他答案之一,作为清单标记的子级和应用程序标记的兄弟级。添加此标签后,我已经重建了项目。

这些是我在谷歌上搜索问题时找到的解决方案,但不幸的是,它们似乎不适合我。 我正在我的 Nexus 5 手机(不是模拟器)上进行调试。这些错误在调用 AudioRecord 的构造函数时出现。我已经重新启动了几次手机以尝试释放麦克风,但无济于事。该项目基于Android 4.4,我的手机目前运行的是Android 6.0.1。

非常感谢一些关于我还可以尝试什么、我可能会错过什么的提示。谢谢!

【问题讨论】:

    标签: java android multithreading audiorecord


    【解决方案1】:

    我自己找到了答案。它与权限有关。

    问题是我在手机上运行 API 版本 23 (Android 6.0.1),它不再仅使用清单文件来处理权限。从版本 23 开始,权限改为在运行时授予。我添加了一个确保在运行时请求权限的方法,当我在手机上允许它一次时,它就起作用了。

    private void requestRecordAudioPermission() {
        //check API version, do nothing if API version < 23!
        int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        if (currentapiVersion > android.os.Build.VERSION_CODES.LOLLIPOP){
    
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
    
                // Should we show an explanation?
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
    
                    // Show an expanation to the user *asynchronously* -- don't block
                    // this thread waiting for the user's response! After the user
                    // sees the explanation, try again to request the permission.
    
                } else {
    
                    // No explanation needed, we can request the permission.
    
                    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, 1);
                }
            }
        }
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 1: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    
                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.
                    Log.d("Activity", "Granted!");
    
                } else {
    
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                    Log.d("Activity", "Denied!");
                    finish();
                }
                return;
            }
    
            // other 'case' lines to check for other
            // permissions this app might request
        }
    }
    

    然后,在创建 AudioRecord 之前,我从主要活动中的 onCreate() 方法调用 requestRecordAudioPermission()。

    【讨论】:

    • 你拯救了我的一天!错误日志与权限完全无关,确实是新版本 23 导致了问题。谢谢
    • 很高兴它也帮助了其他人 :)
    • 非常感谢..在这个问题上花了几天时间
    猜你喜欢
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 2012-06-08
    • 1970-01-01
    相关资源
    最近更新 更多