1

내 응용 프로그램에는 음악 항목의 ListView가 있고 항목을 클릭하면 MediaPlayer에서 스트리밍 할 해당 mp3 URL을 가져옵니다. 사용자가 재생 버튼을 클릭 할 때마다 MediaPlayer의 데이터 소스를 설정합니다. 내가 재생 버튼을 클릭 한 후 화면이 대화 상자가 열리면 다음 정지 ListView에 스크롤 할 때 이제 문제는 다음과 같습니다ANR 이유 keyDispatchingTimedOut MediaPlayer

AppName is not responding. 
Would you like to close it? 
     Wait  OK 

하지만 스택 트레이스를 가져올 수 없습니다를하지만 그것은 말했다 뭔가 같은 :

ANR my.package.name.AppName ... 
Reason: keyDispatchingTimedOut 

UI 스레드를 기다리지 않게하기 위해 백그라운드 스레드 안에 프로세스를 배치했습니다. 이것은 나의 현재 구현하지만 문제가 계속 지속 : 나는 장소였다 무슨 짓을

Thread t = new Thread() { 
      public void run() { 
       SampleActivity.this.runOnUiThread(new Runnable() { 
        public void run() { 
         try { 
          mp.reset(); 
          mp.setDataSource(musicURI); 
          mp.prepare(); 
          mp.start(); 

          songSeekBar.setEnabled(true); 

          // Changing Button Image to stop image 
          btnPlay.setImageResource(R.drawable.btn_stop); 

          // set Progress bar values 
          songSeekBar.setProgress(0); 
          songSeekBar.setMax(100); 

          // Updating progress bar 
          updateProgressBar(); 
         } catch (IllegalArgumentException e) { 
          e.printStackTrace(); 
         } catch (IllegalStateException e) { 
          e.printStackTrace(); 
         } catch (IOException e) { 
          songSeekBar.setEnabled(false); 
          songTotalDurationLabel.setText("0:00"); 
          songCurrentDurationLabel.setText("0:00"); 
          Log.d(Constant.TAG_SAMPLE, musicTitle 
            + " mp3 file not found."); 
          e.printStackTrace(); 
         } 
        } 
       }); 
      } 
     }; 
     t.start(); 

runOnUiThread, 내가 Thread 만 (작동하지 않는) 시도하고, 또한 doInBackground하지만 내부 Asynctask 시도 (작동하지 않는) Thread 내부 플레이어가 배경에서 놀고있어 멈출 수는 없지만 안쪽에 놓으려고하지 않았습니다. onPostExecute

나는 뭔가를 잃어버린 느낌이 들었습니다. 한 가지 확실한 점은 실제로 배경 스레드에 배치해야하지만 어느 스레드에 배치해야합니까? 어떤 생각이라도 받아 들여진다, 고마워!

는 편집 : 그래서, 난 내 구현을 변경하지만 여전히 지속 :

Thread thread = new Thread() { 
     public void run() { 
      Handler refresh = new Handler(Looper.getMainLooper()); 
      refresh.post(new Runnable() { 
       public void run() { 
        // Play song 
        try { 
         mp.reset(); 
         mp.setDataSource(globalSongIndex); 
         mp.prepare(); 
         mp.start(); 

         songSeekBar.setEnabled(true); 

         // Changing Button Image to pause image 
         btnPlay.setImageResource(R.drawable.btn_stop); 

         // set Progress bar values 
         songSeekBar.setProgress(0); 
         songSeekBar.setMax(100); 

         // Updating progress bar 
         updateProgressBar(); 
        } catch (IllegalArgumentException e) { 
         e.printStackTrace(); 
        } catch (IllegalStateException e) { 
         e.printStackTrace(); 
        } catch (IOException e) { 
         songSeekBar.setEnabled(false); 
         songTotalDurationLabel.setText("0:00"); 
         songCurrentDurationLabel.setText("0:00"); 
         Log.d(Constant.TAG_MYPAGE, musicTitle + " mp3 file not found."); 
         e.printStackTrace(); 
        } 
       } 
      }); 
     } 
    }; 
    thread.start(); 

을 그런데, 나는 안드로이드 웹 사이트 here에 기반.

+0

당신의 스레드에서 주 스레드에서 실행하는 함수를 호출하지 않는다면 주 스레드를 차단하고 잠재적으로 ANR이 발생합니다 –

+0

ANR을 발생시키지 않는 백그라운드 스레드에서이 스레드를 실행한다고 생각합니까? 스트림에서 미디어 플레이어를 재생할 때 시간이 걸리므로 앱에서 시간 초과가 발생하여 스레드에 배치했습니다.그래서 내가 잘못하고 있니? –

+0

당신이하고있는 일은 스레드를 시작한 후 메인 스레드에서 무거운 작업을 다시 수행하는 것입니다. –

답변

0

코드가 주 스레드에서 실행됩니다. 플레이어를 초기화하는 것은 좋지 않습니다. 완전히 첫 번째 코드에서 두 번째 코드로 변경하지 않았습니다.

문자열 player.prepare()에 ANR이 표시됩니다. 대신에 playerAsync를 사용하십시오. 플레이어 비동기를 준비하거나 다음을 제거하십시오.

Handler refresh = new Handler(Looper.getMainLooper()); 
     refresh.post(new Runnable() { 
      public void run() { 

모든 작업을 백그라운드 스레드로 수행하십시오.

그리고 AsyncTask에 대해 읽어보십시오 - 이것은 백그라운드에서 어떤 작업을 수행하는 데 좋은 수업입니다. 일반 스레드를 사용하는 것보다 훨씬 유용합니다.

올바른 방법은 다음과 같습니다

MediaPlayer mp = new MediaPlayer(); 
mp.setDataSource(YourURI); 
mp.setOnPreparedListener(new OnPreparedListener() { 
    public void onPrepared(MediaPlayer mp) 
    { 
    long duration = mp.getDuration(); 
    mp.start(); 
    } 
}); 
mp.prepareAsync(); 
+0

두 번째 코드에서는 Handler를 적용했지만 그게 전부입니다. 이제 다시'Asyntask'로 바꾸고 그것을'onPostExecute' 안에 넣고'mp.setOnPreparedListener'를 놓았고'onPrepared' 안에'mp.start()'라고 불렀고 그 다음 리스너가'mp.prepareAsync'입니다. 그러나 "유효한 mediaplayer없이 getDuration을 호출하려고 시도했습니다"라는 오류가 있습니다. 이것에 대해서 어떤 말을하니? –

+0

답변을 업데이트했습니다. 그것 좀 봐. prepareAsync를 사용하는 경우 AsyncTask를 사용할 필요가 없습니다. 이미 백그라운드 스레드에서 모든 작업을 수행합니다. –

+0

나는'Thread'와'Asynctask'를 모두 꺼내었지만 ANR은 여전히 ​​나왔습니다.'long duration = mp.getDuration();'이 줄을 제외하고는이 방법을 시도했습니다. –

0

난 당신이 내 구현을 줄 수는, 미안 친구가 내 회사에 속하는 , 난 당신이 스레드에 무엇을 말할 수있는 제거하려면이 SampleActivity.this.runOnUiThread을 (새 실행 가능한() { . 당신이 mp.start 다음이 하나 개의 스레드에서 파일을 재생 한 후 1 초 동안 잠들지 다른 스레드를 것

Thread.sleep(1000); 
SampleActivity.this.runOnUiThread(new Runnable() { 
public void run() { 
        // Update UI 
        try { 

         // Updating progress bar 
          updateProgressBar(); 
}};  

이 ocode을 가지고 있으며, 다른 스레드를 만들 부르는 순간 메소드를 호출 메인 스레드에서 UI 업데이트