1

I have the following method which simply request a .mp3 file from a URL, loads a MediaPlayer and shows or hide the play button depending if the URL was loaded or not:

public class PlayMusicFragment extends Fragment  {

 private MediaPlayer mediaPlayer;

    private void initializeMusicButton(String url) {
        
        if (Objects.isNull(mediaPlayer)) {
            mediaPlayer = GenericUtils.loadMediaPlayer(url, new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    binding.playMusicButton.setVisibility(VISIBILE);
                }
            }, new MediaPlayer.OnErrorListener() {
                @Override
                public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
                    binding.playMusicButton.setVisibility(GONE);
                    return false;
                }
            });
        }
    
        binding.playButton.setOnClickListener(view -> {
            if (Objects.nonNull(mediaPlayer)) {
                mediaPlayer.start();
            }
        });
    
    }

}

In this fragment, I've also override onStop method in order to release the MediaPlayer:

@Override
public void onStop() {
    super.onStop();
    if (Objects.nonNull(mediaPlayer)) {
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
        }
        mediaPlayer.release();
        mediaPlayer = null;
    }
}

The loadMediaPlayer method does the following:

   public static MediaPlayer loadMediaPlayer(String soundURL, MediaPlayer.OnPreparedListener onPreparedListener, MediaPlayer.OnErrorListener onErrorListener) {
        MediaPlayer mediaPlayer = null;
        try {
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .build());
            mediaPlayer.setOnPreparedListener(onPreparedListener);
            mediaPlayer.setOnErrorListener(onErrorListener);
            mediaPlayer.setDataSource(soundURL);
            mediaPlayer.setLooping(false);
            mediaPlayer.prepareAsync();
        } catch (Exception ex) {
            if (Objects.nonNull(mediaPlayer)) {
                mediaPlayer.release();
            }
        }
        return mediaPlayer;
    }

The problem is that PlayStore Crashlytics report is warning me that the overwritten onStop method code generates an ANR:

enter image description here

I cannot understand why this is happening, I've tested it with my own phone and emulator and I don't notice any ANR.

Any hint?

Nexussim Lements
  • 535
  • 1
  • 15
  • 47

3 Answers3

0

You should not assign null to the released object. Just leave it to the garbage collector.

0

The main thread is blocked by a lock in MediaHTTPConnection. MediaHTTPConnection is used to download a stream you provided. Seems ANR happens when the app tries to release a player when it's not prepared yet (still loading a mp3 file).

Consider moving a release call to a background thread. For example:

public class PlayMusicFragment extends Fragment {

    private Executor executor;
    private MediaPlayer mediaPlayer;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        executor = Executors.newFixedThreadPool(1);
    }

    ...

    @Override
    public void onPause() {
        ...
        MediaPlayer localMediaPlayer = mediaPlayer;
        mediaPlayer = null;

        executor.execute {
            localMediaPlayer.release()
        }
    }
}

jokuskay
  • 81
  • 5
0

you need to move the mediaPlayer.release() method to a background thread. You can do this by using a AsyncTask or a Handler.

public class PlayMusicFragment extends Fragment  {

 private MediaPlayer mediaPlayer;

    private void initializeMusicButton(String url) {
        
        if (Objects.isNull(mediaPlayer)) {
            mediaPlayer = GenericUtils.loadMediaPlayer(url, new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    binding.playMusicButton.setVisibility(VISIBILE);
                }
            }, new MediaPlayer.OnErrorListener() {
                @Override
                public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
                    binding.playMusicButton.setVisibility(GONE);
                    return false;
                }
            });
        }
    
        binding.playButton.setOnClickListener(view -> {
            if (Objects.nonNull(mediaPlayer)) {
                new AsyncTask<Void, Void, Void>() {
                    @Override
                    protected Void doInBackground(Void... voids) {
                        mediaPlayer.release();
                        return null;
                    }
                }.execute();
            }
        });
    
    }

}
Jaspalsinh Gohil
  • 941
  • 1
  • 9
  • 20