ANR Reason keyDispatchingTimedOut MediaPlayer

3.1k views Asked by At

In my app, I have a ListView of music items and when I click an item, I fetch its corresponding mp3 URL to stream in my MediaPlayer. I set the MediaPlayer's datasource and more everytime the user clicks on the Play button. Now the problem is when I click Play button, and scroll the ListView the screen freezes then a dialog opens:

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

but I couldn't get the stacktrace but it said something like:

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

I've read to place my process inside a background thread to not make the UI thread wait. This is my current implementation but the problem still persists:

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

What I did was place a runOnUiThread inside Thread (not working), I tried Thread only (not working), and also tried Asynctask inside its doInBackground but the player is playing at the background and cannot be stopped but I haven't tried placing it inside onPostExecute

I have a feeling I'm missing something. One thing's for sure, I should really place it inside a background thread but which one? Any idea is accepted, thank you!

EDIT: So, I changed my implementation but it still persists:

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

by the way, I based it on the android website here.

2

There are 2 answers

0
Pulkit Sethi On

I cannot give you my implementation, sorry mate belongs to my company, what i can tell you is in your thread remove this SampleActivity.this.runOnUiThread(new Runnable() { . the moment you call mp.start create another thread that has this ocode

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

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

This would play your file in one thread and then have another thread that sleeps for 1 second and then calls a method in main thread to update UI

3
Alexander Mikhaylov On

Ok, your code executes in main thread. It's not good idea initialize a player. Totally you didn't change anything from first code to second.

ANR appears in string player.prepare(). Try to use playerAsync instead of. It will be prepare player asynchronous or you remove this:

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

and make all job in background thread.

And read about AsyncTask - this is a good class to do some work in the background. Much more useful than using ordinary threads.

The right way looks like it:

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