1

외부에서 AudioRecord 클래스를 사용하여 기록한 .wav 파일을 재생하려고합니다. 내 안드로이드 기기의 저장 공간. Play/Pause와 Stop의 두 가지 버튼이 있습니다. 다른 게시물을 읽었지만 문제를 해결할 수 없었습니다. 다음과 같이녹음 및 wav 파일 재생 : 오류 (1, -2147483648) 및 (-38, 0) (API 23 런타임 권한?)

내 코드는 다음과 같습니다

  final MediaPlayer m = new MediaPlayer(); 
     final Button buttonStop = (Button) mView.findViewById(R.id.btnStop); 
     buttonStop.setEnabled(false); 


     final Button buttonPlay = (Button) mView.findViewById(R.id.btnPlay); 

     buttonPlay.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       String fileName = getFileSelected(); 
       Log.i("Info: ", "Play pressed"); 
        if ((!isPlaying && !isPaused) && (getFileSelected().endsWith(".3gp") || getFileSelected().endsWith(".wav"))) { 
         isPlaying = true; 
         isPaused = false; 
         try { 
          m.setDataSource(getActivity().getApplicationContext().getExternalFilesDir(null).toString() + File.separator + fileName); 
         } catch (IOException e) { 
          e.printStackTrace(); 
         } catch (IllegalArgumentException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } catch (IllegalStateException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
         Log.i("Info: ", "DataSource set"); 

         try { 
          m.prepare(); 
         } catch (IllegalStateException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } catch (IOException e) { 
          e.printStackTrace(); 
         } 


     Log.i("Info: ", "Media Player prepare"); 
//       m.setOnPreparedListener(new OnPreparedListener() { 
//        @Override 
//        public void onPrepared(MediaPlayer mediaPlayer) { 
//         m.seekTo(0); 
//         m.start(); 
//        } 
//       }); 
          buttonPlay.setText("Pause"); 
          Log.i("Info: ", "Button Set to Pause"); 
          m.seekTo(0); 
          Log.i("Info: ", "SeektoZero"); 
          m.start(); 
          Log.i("Info: ", "MesiaPlayer Started"); 
          buttonStop.setEnabled(true); 
          Log.i("Info: ", "Stop Button enabled"); 
          Toast.makeText(getActivity().getApplicationContext(), "Playing audio", Toast.LENGTH_LONG).show(); 
          m.setOnCompletionListener(new OnCompletionListener() { 
           @Override 
           public void onCompletion(MediaPlayer mediaPlayer) { 
            isPlaying = false; 
            buttonPlay.setEnabled(true); 
            buttonPlay.setText("Play Selected Recording"); 
            buttonStop.setEnabled(false); 

           } 
          }); 
         } 

         //paused 
         else if (isPaused){ 
          m.seekTo(songPos); 
          m.start(); 
          buttonStop.setEnabled(true); 
          buttonPlay.setText("Pause"); 
          isPaused = false; 
          isPlaying = true; 

         } 

         //isPlaying and not paused 
         else{ 
          songPos = m.getCurrentPosition(); 
          m.pause(); 
          isPaused = true; 
          isPlaying = false; 
          buttonPlay.setText("Play"); 
          buttonStop.setEnabled(false); 

         } 
       } 
      }); 

      buttonStop.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 
        if (isPlaying && !isPaused){ 
         isPlaying = false; 
         isPaused = false; 
         m.pause(); 
         buttonPlay.setEnabled(true); 
         buttonPlay.setText("Play Selected Recording"); 
         buttonStop.setEnabled(false); 
        } 
       } 
      }); 

녹화 버튼에 대한 나의 코드 :

   btnStart.setOnClickListener(new View.OnClickListener(){ 
       @Override 
       public void onClick(View view) { 

        if (!isRecordingCheckButton) { 

         startRecording(); 

         isRecordingCheckButton = true; 
         setButtonLabel(R.id.btnStart, "Stop Recording"); 
Toast.makeText(getActivity().getApplicationContext(), "Recording started", Toast.LENGTH_LONG).show(); 
        } 
        else{ 
         stopRecording(); 
        } 
       } 
private void startRecording(){ 

      int hasRecordAudioPermission = ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), permission.RECORD_AUDIO); 

      if (hasRecordAudioPermission != PackageManager.PERMISSION_GRANTED) { 
       if (!shouldShowRequestPermissionRationale(permission.RECORD_AUDIO)) { 
        showMessageOKCancel("You must give permission to write to storage.", 
          new DialogInterface.OnClickListener() { 
           @Override 
           public void onClick(DialogInterface dialog, int which) { 
            requestPermissions(new String[] {permission.RECORD_AUDIO}, 
              111); 
           } 
          }); 
        return; 
       } 

       requestPermissions(new String[] {permission.RECORD_AUDIO}, 
         111); 
       return; 
      } 


      recorder = new AudioRecord(AudioSource.VOICE_RECOGNITION, 
        RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize); 

      int i = recorder.getState(); 
      if(i==1) 
       recorder.startRecording(); 

      isRecording = true; 

      recordingThread = new Thread(new Runnable() { 

       @Override 
       public void run() { 
        writeAudioDataToFile(); 
       } 
      },"AudioRecorder Thread"); 

      recordingThread.start(); 
     } 

     private void writeAudioDataToFile(){ 


      int hasWriteFilePermission = ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE); 

      if (hasWriteFilePermission != PackageManager.PERMISSION_GRANTED) { 
       if (!shouldShowRequestPermissionRationale(permission.WRITE_EXTERNAL_STORAGE)) { 
        showMessageOKCancel("You must give permission to write to storage.", 
          new DialogInterface.OnClickListener() { 
           @Override 
           public void onClick(DialogInterface dialog, int which) { 
            requestPermissions(new String[] {permission.WRITE_EXTERNAL_STORAGE}, 
              111); 
           } 
          }); 
        return; 
       } 

       requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 
         111); 
       return; 
      } 
      byte data[] = new byte[bufferSize]; 
      String filename = getTempFilename(); 
      FileOutputStream os = null; 

      try { 
       os = new FileOutputStream(filename); 
      } catch (FileNotFoundException e) { 
// TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

      int read = 0; 

      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(); 
       } 
      } 
     } 

Wave File 

헤더 :

private void WriteWaveFileHeader(

     FileOutputStream out, long totalAudioLen, 
     long totalDataLen, long longSampleRate, int channels, 
     long byteRate) throws IOException { 

     byte[] header = new byte[44]; 

     header[0] = 'R'; // RIFF/WAVE header 
     header[1] = 'I'; 
     header[2] = 'F'; 
     header[3] = 'F'; 
     header[4] = (byte) (totalDataLen & 0xff); 
     header[5] = (byte) ((totalDataLen >> 8) & 0xff); 
     header[6] = (byte) ((totalDataLen >> 16) & 0xff); 
     header[7] = (byte) ((totalDataLen >> 24) & 0xff); 
     header[8] = 'W'; 
     header[9] = 'A'; 
     header[10] = 'V'; 
     header[11] = 'E'; 
     header[12] = 'f'; // 'fmt ' chunk 
     header[13] = 'm'; 
     header[14] = 't'; 
     header[15] = ' '; 
     header[16] = 16; // 4 bytes: size of 'fmt ' chunk 
     header[17] = 0; 
     header[18] = 0; 
     header[19] = 0; 
     header[20] = 1; // format = 1 
     header[21] = 0; 
     header[22] = (byte) channels; 
     header[23] = 0; 
     header[24] = (byte) (longSampleRate & 0xff); 
     header[25] = (byte) ((longSampleRate >> 8) & 0xff); 
     header[26] = (byte) ((longSampleRate >> 16) & 0xff); 
     header[27] = (byte) ((longSampleRate >> 24) & 0xff); 
     header[28] = (byte) (byteRate & 0xff); 
     header[29] = (byte) ((byteRate >> 8) & 0xff); 
     header[30] = (byte) ((byteRate >> 16) & 0xff); 
     header[31] = (byte) ((byteRate >> 24) & 0xff); 
     header[32] = (byte) (2 * 16/8); // block align 
     header[33] = 0; 
     header[34] = RECORDER_BPP; // bits per sample 
     header[35] = 0; 
     header[36] = 'd'; 
     header[37] = 'a'; 
     header[38] = 't'; 
     header[39] = 'a'; 
     header[40] = (byte) (totalAudioLen & 0xff); 
     header[41] = (byte) ((totalAudioLen >> 8) & 0xff); 
     header[42] = (byte) ((totalAudioLen >> 16) & 0xff); 
     header[43] = (byte) ((totalAudioLen >> 24) & 0xff); 

     out.write(header, 0, 44); 
    } 

내가 경기 누를 때 나는 다음과 같은 오류를 얻고있다 방금 녹음 한 파일 중 하나를 선택하십시오 :

 07-11 02:59:56.571 20450-20450/com.ibm.watson.developer_cloud.android.examples I/Info:: Media Player prepare 
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples I/Info:: Button Set to Pause 
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: Attempt to perform seekTo in wrong state: mPlayer=0x7f6521e3c0, mCurrentState=0 
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: error (-38, 0) 
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples I/Info:: SeektoZero 
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: start called in state 0 
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: error (-38, 0) 
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples I/Info:: MesiaPlayer Started 
07-11 02:59:56.581 20450-20450/com.ibm.watson.developer_cloud.android.examples I/Info:: Stop Button enabled 
07-11 02:59:56.611 20450-20450/com.ibm.watson.developer_cloud.android.examples I/MediaPlayer: send context aware event 
07-11 02:59:56.611 20450-20450/com.ibm.watson.developer_cloud.android.examples I/MediaPlayer: sendBroadcast CONTEXT_AWARE_MUSIC_INFO - type(error) - id (261) 
07-11 02:59:56.611 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: Error (-38,0) 
07-11 02:59:56.621 20450-20450/com.ibm.watson.developer_cloud.android.examples E/MediaPlayer: Error (-38,0) 
07-11 02:59:56.671 20450-20450/com.ibm.watson.developer_cloud.android.examples W/DisplayListCanvas: DisplayListCanvas is started on unbinded RenderNode (without mOwningView) 

(-38,0)은 상태와 관련되어 있지만 문제를 해결하는 데 문제가 있음을 알고 있습니다. 동일한 코드가 API 19에서 정상적으로 작동했지만 API 23에서이 오류가 발생했습니다. 앱에서 파일을 읽을 수있는 권한이 없기 때문에 오류 (1, -2147483648)가있을 수있는 몇 가지 게시물을 읽었습니다. 그러나, 나는 문제를 해결할 수 없었다. 내가 잘못 가고있는 곳이 어디인지, 아니면 API 23을 추가 할 필요가 있는지 모르겠습니다. mediaPlayer가 외부 저장소에서 파일을 읽으면서 런타임 권한과 관련 될 수 있습니까? 그렇다면 어디에서 허가해야합니까? 내가 그것을 전송하고 내 컴퓨터에서 재생할 때 wav 파일이 제대로 녹음되었습니다.

업데이트 : mediaRecord 클래스와 조건이 제대로 작동하는지 확인하기 위해 다른 wav 파일을 사용했습니다. 이제 문제는 앱이 wav를 읽을 수 없기 때문에 기록하고 저장하는 파일 일뿐입니다 (컴퓨터에서 정상적으로 재생할 수 있음). 나는 런타임 권한을 확인하지 않고 API 19에서 같은 방식으로 기록하고 있으므로 알아낼 수 없습니다.

업데이트 2 : 나는 데이터 소스를 재설정 정지 버튼 onClickListeneronCompletionListenerreset 메소드를 호출했다. 또한 컴퓨터에 기록 된 파일 중 하나를 복사하여 2016-07-10 22:39:40_Recording.wav에서 blabla.wav으로 이름을 바꾼 후 다시 넣습니다. 잘 했어. 하지만 비슷한 날짜 및 시간 이름 형식의 다른 유형의 파일은 읽을 수 있습니다. 문제가 이름과 관련된 것인지 확실하지 않습니다.

이 문제와 관련하여 도움을 받으실 수 있습니다!

+0

메신저 확인이가 문제를 해결하는 것입니다,하지만 난'isPlaying'하고'isPaused'이 모두 false로 설정되어 buttonStop.setOnClickListener''에, 잠재적 인 버그를 발견했을 수도 있습니다. 살펴보기 –

+0

재생/일시 중지를 누르면 오류가 발생합니다. isPlaying과 isPaused를 체크로 사용 했으므로 stop 버튼을 누르면 mediaPlayer가 멈추고 (위치 추적없이 일시 중지됨) 다음에 재생을 누르면 MediaPlayer가 처음부터 재생을 시작합니다. – skbrhmn

+0

첫 번째 if 문을 확인할 수 있습니다.당신의 조건이 틀린 것, 나는'(! isPlaying &&! isPaused)'이 의심스러워 보입니다! 또한, 일부 로그 문을 던져서 응용 프로그램의 흐름을 확인하십시오. –

답변

0

나는이 문제를 해결했다. 파일 이름의 콜론 제거 오류 (1, -2147483648). MediaPlayer가 파일을 인식하고 읽을 수 없습니다. 이름을 다른 형식으로 변경하면이 문제가 해결됩니다.

오류 (-38, 0)는 주와 관련이 있으며 문제가 발생한 지점을 파악하는 데 시간이 걸렸습니다. State Diagram은 큰 도움이되었습니다. 다음 코드는 작동 :

final MediaPlayer m = new MediaPlayer(); 
     final Button buttonStop = (Button) mView.findViewById(R.id.btnStop); 
     buttonStop.setEnabled(false); 


     final Button buttonPlay = (Button) mView.findViewById(R.id.btnPlay); 

     buttonPlay.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 

       String fileName = getFileSelected(); 
       if(!fileName.endsWith(".3gp") && !fileName.endsWith(".wav")){ 

       } 
       else if ((!isPlaying && !isPaused)) { 
        isPlaying = true; 
        isPaused = false; 

        int hasReadFilesPermission = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE); 
        if (hasReadFilesPermission != PackageManager.PERMISSION_GRANTED) { 
         if (!shouldShowRequestPermissionRationale(permission.READ_EXTERNAL_STORAGE)) { 
          showMessageOKCancel("You must give permission to read from storage.", 
            new DialogInterface.OnClickListener() { 
             @Override 
             public void onClick(DialogInterface dialog, int which) { 
              requestPermissions(new String[] {permission.READ_EXTERNAL_STORAGE}, 
                223); 
             } 
            }); 
          return ; 
         } 

         requestPermissions(new String[] {permission.READ_EXTERNAL_STORAGE}, 
           223); 
         return ; 
        } 
        fileName = getFileSelected(); 
        displayResult(getActivity().getApplicationContext().getExternalFilesDir(null).toString() + File.separator + fileName); 
        try { 
         m.setDataSource(getActivity().getApplicationContext().getExternalFilesDir(null).toString() + File.separator + fileName); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } catch (IllegalArgumentException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } catch (IllegalStateException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
        try { 
         m.prepare(); 
        } catch (IllegalStateException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
        buttonPlay.setText("Pause"); 
        m.seekTo(0); 
        m.start(); 
        buttonStop.setEnabled(true); 
        Toast.makeText(getActivity().getApplicationContext(), "Playing audio", Toast.LENGTH_LONG).show(); 
        m.setOnCompletionListener(new OnCompletionListener() { 
         @Override 
         public void onCompletion(MediaPlayer mediaPlayer) { 
          m.reset(); 
          isPlaying = false; 
          isPaused = false; 
          buttonPlay.setEnabled(true); 
          buttonPlay.setText("Play Selected Recording"); 
          buttonStop.setEnabled(false); 

         } 
        }); 
       } 

       //paused 
       else if (isPaused){ 
        m.seekTo(songPos); 
        m.start(); 
        buttonStop.setEnabled(true); 
        buttonPlay.setText("Pause"); 
        isPaused = false; 
        isPlaying = true; 

       } 

       //isPlaying and not paused 
       else{ 
        songPos = m.getCurrentPosition(); 
        m.pause(); 
        isPaused = true; 
        isPlaying = false; 
        buttonPlay.setText("Play"); 
        buttonStop.setEnabled(false); 

       } 
      } 
     });