2016-06-25 4 views
3

마이크 입력 (특히 호흡)을 수신하고이를 기반으로 데이터를 표시하는 앱을 구현하려고합니다. 안드로이드 클래스 AudioRecord를 사용하고 AudioRecord를 인스턴스화하려고 할 때 세 가지 오류가 발생합니다. Android 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

I은 ​​문제 해결을 위해 모든 샘플 레이트, 오디오 포맷 및 채널 구성을 시도 허용 대답의 코드를 차용 한을,하지만하지 않았다 도움, 모든 설정에 위의 오류가 발생합니다. 스레드의 답변 중 하나에 따라 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을 실행 중입니다.

내가 시도 할 수있는 것, 놓친 것일 수있는 것에 대한 많은 정보를 매우 높이 평가할 것입니다. 고맙습니다!

답변

7

직접 답변을 찾았습니다. 그것은 허가와 관련이 있습니다.

문제는 내 휴대 전화에서 더 이상 매니페스트 파일 만 사용하여 권한을 처리하지 않는 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()를 호출합니다.

+1

내 하루를 저장했습니다. 오류 로그는 사용 권한과 완전히 관련이 없으며 문제를 일으키는 새로운 버전 23이었습니다. 고마워요 –

+1

다른 사람도 도와 줘서 기뻐요 :) – Helena

+0

고맙습니다.이 이슈에 며칠을 보냈습니다. – sharry

관련 문제