본문 바로가기

분노=프로그래밍/Android

[AudioRecord 오류]Unable to retrieve AudioRecord object, can't record

오류 메시지 : 

Unable to retrieve AudioRecord object, can't record.

앱이 죽지는 않으나 녹음 데이터를 저장한 파일을 재생하면 음성출력에 공백이 있거나, 찌지직 거리는 소리가 남.



상황 :


구글링으로 누군가 구현한 샘플 소스를 이용해서 구현한 후 하드한 테스트를 거쳤더니 상기와 같은 오류 로그가 발생했다.

(*하드한 테스트 = 녹음 시작/종료 빠른속도로 번갈아가면서 실행. 초당 3~4연타는 하는 듯)


간헐적으로 NullpointerException이 떨어지면서 앱이 죽기도.


수없이 구글링했지만, native(c) 쪽에서 객체 생성 중 오류가 발생했을 때 오류를 떨구는 안드로이드 OS상의 로그만 검색될 뿐

해결책을 찾지 못함.


추측 :


AudioRecord Referenece를 참조해보니 AudioRecord.class에서 

STATE_INITIALIZED, STATE_UNINITIALIZED 와 같은 상수를 제공하고 있음.


1.상기와 같이 초기화 여부에 대한 상태를 제공해주는 데는 이유가 있을거라 추측


2.녹음 시작, 종료 테스트 시에 미묘한 딜레이를 느낌


3.인터넷에 떠돌아 다니는 대부분의 소스는 stop(), release()를 동시에 호출하고 있는 점을 의심하게 됨.

 일반적으로 release는 프로그래밍에서 메모리 해제를 요청할 때 쓰는 키워드인데

 AudioRecord에서 제공되는 stop() 메서드 내에 release를 구현해서 Client(개발자)에게 제공해도 될 것을

 굳이 release()라는 api를 따로 제공하고 있음.


4.상기 2가지 이유로 추측컨데, 객체에 대한 메모리 생성, 해제에 시간(성능)상의 문제가 있기 때문에

 위와 같은 상태값을 제공해준다고 추측함.


5.일반적으로 녹음처리는 loop를 이용해서 I/O하는 형태로 구현하게 되는데, I/O가 이루어지고 있는 상태에서

  release() 요청으로 인스턴스가 메모리에서 해제되는 바람에 NullpointerException이 발생하거나,

  메모리 해제가 완료되지 않은 시점에서 initialize를 요청하면서 상태값이 엉킨다고 추측.


해결 :

UI상으로 녹음 종료 호출 시 stop() 호출은 그대로.

release()의 호출 시점을 I/O작업이 끝난 후, release()가 호출되도록 구현함.


기존

private void writeAudioDataToFile(){
                //생략
                
                if(null != os){
                        while(isRecording){
                                read = recorder.read(data, 0, bufferSize);
                                
                                if(AudioRecord.ERROR_INVALID_OPERATION != read){
                                        try {
                                                os.write(data);
                                        } catch (IOException e) {
                                                e.printStackTrace();
                                        }
                                }
                        }
                        
                        try {
                                os.close();
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                }
        }
private void stopRecording(){
                if(null != recorder){
                        isRecording = false;
                        
                        recorder.stop();
                        recorder.release();
                        
                        recorder = null;
                        recordingThread = null;
                }
        }

변경

private void writeAudioDataToFile(){
                //생략
                
                if(null != os){
                        while(isRecording){
                                read = recorder.read(data, 0, bufferSize);
                                
                                if(AudioRecord.ERROR_INVALID_OPERATION != read){
                                        try {
                                                os.write(data);
                                        } catch (IOException e) {
                                                e.printStackTrace();
                                        }
                                }
                        }

                        recorder.release();
                        recorder = null;
                        try {
                                os.close();
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                }
        }
private void stopRecording(){
                if(null != recorder){
                        isRecording = false;
                        
                        recorder.stop();
                        recordingThread = null;
                }
        }


P.S : 

변태 테스트(녹음 시작/정지 연타) 덕분에 발생한 오류.

상기 변태 테스트같이 쓸 사람이 얼마나 되겠냐고 말하는 사람이 많겠지만.

세상 인구가 몇억명인데 나같은 변태가 한 명도 없으리란 보장이 없다. =_=;

'분노=프로그래밍 > Android' 카테고리의 다른 글

ADT 23.0.2 ResourceNotFoundException 문제  (0) 2014.10.21
GCM 이용하기 3/3  (4) 2013.04.07
GCM 이용하기 2/3  (15) 2013.04.07
GCM 이용하기 1/3  (1) 2013.04.07