2014-11-03 3 views
3

기기에서 배경에서 작동하는 동안 마이크가 사용하는 배터리 양을 측정하려 했으므로 테스트 할 수있는 작은 앱을 작성했습니다.앱 강제 종료 - OutOfMemoryError

내 휴대 전화에 외부 저장 장치에는 앱과 함께 생성 된 600MB PCM 파일 기록과 두 번째 100MB 하드 디스크가 있습니다.

내가 응용 프로그램을 실행하고 100MB 파일을 재생하려고하면 정상적으로 작동합니다. 내가 시도하고 큰 6백메가바이트 하나를 연주 할 때 는 그러나, 코드 라인에 충돌 :

InputStream is = new FileInputStream(file); 

그리고 로그 캣은 오류가 있습니다 : 나는 안드로이드에 많은 파일 IO 물건을하지 않은

`11-03 16:31:03.654 16916-16916/com.bacon.corey.audiotimeshift I/art﹕ Alloc sticky concurrent mark sweep GC freed 6307(421KB) AllocSpace objects, 1(12KB) LOS objects, 33% free, 15MB/23MB, paused 678us total 14.444ms 
11-03 16:31:03.663 16916-16916/com.bacon.corey.audiotimeshift I/art﹕ Alloc partial concurrent mark sweep GC freed 213(22KB) AllocSpace objects, 0(0B) LOS objects, 40% free, 15MB/26MB, paused 659us total 7.132ms 
11-03 16:31:03.679 16916-16916/com.bacon.corey.audiotimeshift I/art﹕ Alloc concurrent mark sweep GC freed 15(12KB) AllocSpace objects, 0(0B) LOS objects, 40% free, 15MB/26MB, paused 830us total 14.191ms 
11-03 16:31:03.681 16916-16916/com.bacon.corey.audiotimeshift I/art﹕ Forcing collection of SoftReferences for 641MB allocation 
11-03 16:31:03.695 16916-16916/com.bacon.corey.audiotimeshift I/art﹕ Alloc concurrent mark sweep GC freed 11(344B) AllocSpace objects, 0(0B) LOS objects, 39% free, 15MB/26MB, paused 645us total 13.989ms 
11-03 16:31:03.700 16916-16916/com.bacon.corey.audiotimeshift E/art﹕ Throwing OutOfMemoryError "Failed to allocate a 672164876 byte allocation with 11094652 free bytes and 176MB until OOM" 
11-03 16:31:03.703 16916-16916/com.bacon.corey.audiotimeshift D/AndroidRuntime﹕ Shutting down VM 
11-03 16:31:03.713 16916-16916/com.bacon.corey.audiotimeshift E/AndroidRuntime﹕ FATAL EXCEPTION: main 
    Process: com.bacon.corey.audiotimeshift, PID: 16916 
    java.lang.IllegalStateException: Could not execute method of the activity 
      at android.view.View$1.onClick(View.java:4007) 
      at android.view.View.performClick(View.java:4756) 
      at android.view.View$PerformClick.run(View.java:19749) 
      at android.os.Handler.handleCallback(Handler.java:739) 
      at android.os.Handler.dispatchMessage(Handler.java:95) 
      at android.os.Looper.loop(Looper.java:135) 
      at android.app.ActivityThread.main(ActivityThread.java:5221) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:372) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
    Caused by: java.lang.reflect.InvocationTargetException 
      at java.lang.reflect.Method.invoke(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:372) 
      at android.view.View$1.onClick(View.java:4002) 
            at android.view.View.performClick(View.java:4756) 
            at android.view.View$PerformClick.run(View.java:19749) 
            at android.os.Handler.handleCallback(Handler.java:739) 
            at android.os.Handler.dispatchMessage(Handler.java:95) 
            at android.os.Looper.loop(Looper.java:135) 
            at android.app.ActivityThread.main(ActivityThread.java:5221) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at java.lang.reflect.Method.invoke(Method.java:372) 
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
    Caused by: java.lang.OutOfMemoryError: Failed to allocate a 672164876 byte allocation with 11094652 free bytes and 176MB until OOM 
      at com.bacon.corey.audiotimeshift.MainActivity.play(MainActivity.java:87) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at java.lang.reflect.Method.invoke(Method.java:372) 
            at android.view.View$1.onClick(View.java:4002) 
            at android.view.View.performClick(View.java:4756) 
            at android.view.View$PerformClick.run(View.java:19749) 
            at android.os.Handler.handleCallback(Handler.java:739) 
            at android.os.Handler.dispatchMessage(Handler.java:95) 
            at android.os.Looper.loop(Looper.java:135) 
            at android.app.ActivityThread.main(ActivityThread.java:5221) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at java.lang.reflect.Method.invoke(Method.java:372) 
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)` 

을 , 그래서 나는 정말로 내가 여기서 잘못하고있는 것이 확실하지 않다. 누군가 내가 잘못 갔다는 것을 지적하지 않으면 매우 감사 할 것입니다.

클래스 코드는 다음과 같습니다. 사전 코리에

감사합니다 :)

당신이 그것으로 아무것도하기 전에 메모리에 전체 오디오 파일을로드하는 것 같습니다
 public void play(View view) { 
     Toast.makeText(this, "play", Toast.LENGTH_SHORT).show(); 

// Get the file we want to playback. 
     File file = new File(Environment.getExternalStorageDirectory() + File.separator + "ACS.pcm"); 
// Get the length of the audio stored in the file (16 bit so 2 bytes per short) 
// and create a short array to store the recorded audio. 
     int musicLength = (int)(file.length()/2); 
     short[] music = new short[musicLength]; 


     try { 
// Create a DataInputStream to read the audio data back from the saved file. 
      InputStream is = new FileInputStream(file); 
      BufferedInputStream bis = new BufferedInputStream(is); 
      DataInputStream dis = new DataInputStream(bis); 

// Read the file into the music array. 
      int i = 0; 
      while (dis.available() > 0) { 
       music[musicLength-1-i] = dis.readShort(); 
       i++; 
      } 


// Close the input streams. 
      dis.close(); 


// Create a new AudioTrack object using the same parameters as the AudioRecord 
// object used to create the file. 
      AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 
        44100, 
        AudioFormat.CHANNEL_OUT_MONO, 
        AudioFormat.ENCODING_PCM_16BIT, 
        musicLength, 
        AudioTrack.MODE_STREAM); 
// Start playback 
      audioTrack.play(); 

// Write the music buffer to the AudioTrack object 
      audioTrack.write(music, 0, musicLength); 


     } catch (Throwable t) { 
      Log.e("AudioTrack","Playback Failed"); 
     } 
    } 

답변

0

. 파일 크기가 672164876 바이트 (641MB) 인 것처럼보기에 좋지 않은 접근 방식입니다. 그럴 경우 길이가 일 것입니다. 총 RAM이 최대 1-2GB 인 휴대 기기에 할당 할 수있는 것보다 많은 RAM이 필요합니다. 실행중인 모든 앱 (Android OS 자체)간에 공유 할 수 있습니다.

이렇게 낮은 수준 (모든 바이트를 읽고이를 재생할 무언가에 직접 쓰는 것)을 시도한 것은 대단한 일이지만, 기본 제공 Android 미디어 API MediaPlayer 같은 in this other StackOverflow post 또는 일부 높은 수준의 라이브러리, 어떤 중 모든 내용을 메모리에 파일을 스트리밍하고 재생해야하므로 그렇게 할 필요가 없습니다.