Skip to content
Advertisement

Exoplayer multiple instances when loading new fragments

I am creating a radio streaming app for a friend. I decided go down the Exo player route. Everything works fine, apart from if I load a new fragment or turn the screen round. Then I get a new instance of Exo player that starts behind the original. It can get really messy – how can I avoid this?

Here is my code. I open the fragment using:

 public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {

    root = inflater.inflate(R.layout.fragment_home, container, false);

    initializeUIElements(root);


    return root;
}

This is how I call Exo player:

private void initializeUIElements(View root) {

    playSeekBar = root.findViewById(R.id.progressBar1);
    playSeekBar.setMax(100);
    playSeekBar.setVisibility(View.INVISIBLE);





}


@Override
public void onStop() {
    super.onStop();
    if (Util.SDK_INT >= 24) {
        initializeMediaPlayer(root);
    }
}


private void initializeMediaPlayer(View root) {

    playerView = root.findViewById(R.id.video_view);
    player = new SimpleExoPlayer.Builder(getContext()).build();
    playerView.setPlayer(player);

    MediaItem media = MediaItem.fromUri(revurl);
    player.setMediaItem(media);

    player.setPlayWhenReady(playWhenReady);
    player.seekTo(currentWindow, playbackPosition);
    player.prepare();
}

@Override
public void onPause() {
    super.onPause();
    if (Util.SDK_INT < 24) {
        releasePlayer();
    }
}

@Override
public void onStart() {
    super.onStart();
    if (Util.SDK_INT >= 24) {
        initializeMediaPlayer(root);
    }
}

@Override
public void onResume() {
    super.onResume();

    if ((Util.SDK_INT < 24 || player == null)) {
        initializeMediaPlayer(root);
    }
}

@SuppressLint("InlinedApi")
private void hideUi() {
    playerView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
            | View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
private boolean playWhenReady = true;
private int currentWindow = 0;
private long playbackPosition = 0;


private void releasePlayer() {
    if (player != null) {
        playWhenReady = player.getPlayWhenReady();
        playbackPosition = player.getCurrentPosition();
        currentWindow = player.getCurrentWindowIndex();
        player.release();
        player = null;
    }
}

This is an example of the fragment I’m opening:

 public class FacebookFragment extends Fragment {

Context c;
private WebView mwebview;
private String url = "https://www.facebook.com/Revotionofdance";


public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {

    View root = inflater.inflate(R.layout.facebook_fragment, container, false);
    mwebview = (WebView) root.findViewById(R.id.webview);
    mwebview.setWebViewClient(new WebViewClient());
    mwebview.addJavascriptInterface(new WebAppInterface(c), "Android");


    WebSettings webSettings = mwebview.getSettings();
    webSettings.setJavaScriptEnabled(true);
    mwebview.loadUrl(url);


    return root;
}

public class MyWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if ("https://www.facebook.com/Revotionofdance".equals(Uri.parse(url).getHost())) {
            // This is my website, so do not override; let my WebView load the page
            return false;
        }
        // Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        startActivity(intent);
        return true;
    }
}

public class WebAppInterface {
    Context mContext;

    /**
     * Instantiate the interface and set the context
     */
    WebAppInterface(Context c) {
        mContext = c;
    }

    /**
     * Show a toast from the web page
     */
    @JavascriptInterface
    public void showToast(String toast) {
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
    }
}

This is my main activity where I call the fragments from:

  DrawerLayout drawer = findViewById(R.id.drawer_layout);
    NavigationView navigationView = findViewById(R.id.nav_view);
    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    mAppBarConfiguration = new AppBarConfiguration.Builder(
            R.id.nav_home, R.id.nav_facebook, R.id.nav_insta,R.id.nav_snap,R.id.nav_rodr)
            .setDrawerLayout(drawer)
            .build();
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
    NavigationUI.setupWithNavController(navigationView, navController);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onSupportNavigateUp() {
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    return NavigationUI.navigateUp(navController, mAppBarConfiguration)
            || super.onSupportNavigateUp();
}

Advertisement

Answer

According to your code above currently in your onStop() method you initialise a new instance of SimpleExoPlayer instead of release it. You initialize the player in the onStart() or onResume() methods depending on the API level and release the created player in your onPause() or onStop() methods.

Currently you have:

@Override
public void onStop() {
    super.onStop();
    if (Util.SDK_INT >= 24) {
        initializeMediaPlayer(root);
    }
}

Change it to:

@Override
  public void onStop() {
    super.onStop();
    if (Util.SDK_INT >= 24) {
      releasePlayer();
    }
  }
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement