我正在尝试实现一个监听麦克风输入(特别是呼吸)的应用程序,并根据它提供数据.我正在使用
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,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,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.
非常感谢我可以尝试的其他一些提示,我可能错过了什么.谢谢!
解决方法
我自己找到了答案.它与权限有关.
问题是我在手机上运行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().