I want implement next and previous buttons below the ExoPlayer. I'm basing my code on this thread:
Implementing next button in audio player android
and the links in these ones:
How to add Listener for next , previous , rewind and forward in Exoplayer
How to add next song and previous song play button in audio player using android studio2.3?
The Exoplayer is in a fragment and opens on the right side of the screen on a tablet screen and in a separate activity on a mobile screen when the user clicks on one of the recipe steps. Data to the StepsFragment(implements an onClickListener) is sent via parcelable from the parent activity(code below).
Next and previous buttons are only implemented on the mobile screen(code works fine). I'm passing the arraylist and position from the parent activity in the onClick method and retrieving them in the fragment. The code works fine w/o the buttons, and both the list and the position are sent via parcelable to the VideoFragment only to implement the buttons. I decided to put the buttons in the Video Fragment.
Nothing happens when clicking on either the next or previous button. Code flow is indicated in the comments above the code in the onClickListener. I've tried to debug but no errors are displayed. Is this the right way to pass the arraylist? Although it's not shown in the debug and the log cat, I think it might be null. Can someone please have a look? Thank you in advance.
VideoFragment(contains Exoplayer code):
public class VideoFragment extends Fragment
{
// Tag for logging
private static final String TAG = VideoFragment.class.getSimpleName();
/**
* Mandatory empty constructor for the fragment manager to instantiate the fragment
*/
public VideoFragment()
{
}
ArrayList<Steps> stepsArrayList;
Steps stepClicked;
Recipes recipes;
SimpleExoPlayer mExoPlayer;
@BindView(R.id.playerView)
SimpleExoPlayerView mPlayerView;
@BindView(R.id.thumbnail_url)
ImageView thumbnailUrlImage;
public int stepPosition;
private long mPlayerPosition;
String videoUrl;
Uri videoUrl_Parse;
Uri thumbnailUrl_Parse;
String thumbnailUrl;
@BindView(R.id.previous_button)
Button previousButton;
@BindView(R.id.next_button)
Button nextButton;
@BindView(R.id.step_long_description)
TextView stepLongDescription;
String stepLongDescriptionUrl;
boolean mTwoPane;
private static final String KEY_POSITION = "position";
public static final String STEPS_LIST_INDEX = "list_index";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
//Inflate the Steps fragment layout
View rootView = inflater.inflate(R.layout.fragment_video, container, false);
// Bind the views
ButterKnife.bind(this, rootView);
Bundle bundle = this.getArguments();
if (bundle != null)
{
//Track whether to display a two-pane or single-pane UI
stepClicked = getArguments().getParcelable("Steps");
if (stepClicked != null)
{
mTwoPane = getArguments().getBoolean("TwoPane");
stepPosition = getArguments().getInt("StepPosition");
stepsArrayList = getArguments().getParcelableArrayList("StepsArrayList");
stepsArrayList = new ArrayList<>();
videoUrl = stepClicked.getVideoUrl();
Log.i("VideoUrl: ", stepClicked.getVideoUrl());
videoUrl_Parse = Uri.parse(videoUrl);
thumbnailUrl = stepClicked.getThumbnailUrl();
thumbnailUrl_Parse = Uri.parse(thumbnailUrl);
stepLongDescriptionUrl = stepClicked.getStepLongDescription();
Log.i("Step: ", stepClicked.getStepLongDescription());
stepLongDescription.setText(stepLongDescriptionUrl);
if (thumbnailUrl != null)
{
Picasso.with(getContext())
.load(thumbnailUrl_Parse)
.into(thumbnailUrlImage);
}
}
if (mTwoPane)
{
previousButton.setVisibility(View.INVISIBLE);
nextButton.setVisibility(View.INVISIBLE);
} else
{
previousButton.setVisibility(View.VISIBLE);
nextButton.setVisibility(View.VISIBLE);
//https://stackoverflow.com/questions/45253477/implementing-next-button-in-audio-player-android
nextButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
if (stepPosition < stepsArrayList.size() - 1)
{
//Add or subtract the position in 1
stepClicked= stepsArrayList.get(stepPosition);
stepPosition++;
//Using the position, get the current step from the steps list
stepClicked= stepsArrayList.get(stepPosition);
//Extract the video uri from the current step
videoUrl = stepClicked.getVideoUrl();
Log.d("VideoUrlNext: ", stepClicked.getVideoUrl());
videoUrl_Parse = Uri.parse(videoUrl);
//Call initializePlayer() by passing the new video uri
initializePlayer(videoUrl_Parse);
}
}
});
previousButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
if (stepPosition> 0)
{
stepPosition--;
//Using the position, get the current step from the steps list
stepClicked= stepsArrayList.get(stepPosition);
//Extract the video uri from the current step
videoUrl = stepClicked.getVideoUrl();
videoUrl_Parse = Uri.parse(videoUrl);
//Call initializePlayer() by passing the new video uri
initializePlayer(videoUrl_Parse);
}
}
});
}
}
if (savedInstanceState != null)
{
stepsArrayList = savedInstanceState.getParcelableArrayList(STEPS_LIST_INDEX);
mPlayerPosition = savedInstanceState.getLong(KEY_POSITION);
}
// Return the root view
return rootView;
}
//ExoPlayer code based on: https://codelabs.developers.google.com/codelabs/exoplayer-intro/#2
public void initializePlayer(Uri videoUrl)
{
if (mExoPlayer == null)
{
TrackSelector trackSelector = new DefaultTrackSelector();
LoadControl loadControl = new DefaultLoadControl();
mExoPlayer = ExoPlayerFactory.newSimpleInstance(getActivity(), trackSelector, loadControl);
mPlayerView.setPlayer((SimpleExoPlayer) mExoPlayer);
String userAgent = Util.getUserAgent(getContext(), "Baking App");
MediaSource mediaSource = new ExtractorMediaSource(videoUrl,
new DefaultDataSourceFactory(getContext(), userAgent),
new DefaultExtractorsFactory(), null, null);
mExoPlayer.prepare(mediaSource);
if (mPlayerPosition != C.TIME_UNSET)
{
mExoPlayer.seekTo(mPlayerPosition);
}
mExoPlayer.setPlayWhenReady(true);
}
}
@Override
public void onStart()
{
super.onStart();
if (Util.SDK_INT > 23 || mExoPlayer == null)
{
initializePlayer(videoUrl_Parse);
}
}
@Override
public void onPause()
{
super.onPause();
if (mExoPlayer != null)
{
mPlayerPosition = mExoPlayer.getCurrentPosition();
}
if (Util.SDK_INT <= 23)
{
releasePlayer();
}
}
@Override
public void onResume()
{
super.onResume();
if ((Util.SDK_INT <= 23 || mExoPlayer == null))
{
mPlayerPosition = mExoPlayer.getCurrentPosition();
}
}
@Override
public void onStop()
{
super.onStop();
if (Util.SDK_INT > 23 || mExoPlayer != null)
{
mExoPlayer.getCurrentPosition();
}
releasePlayer();
}
/**
* Release ExoPlayer.
*/
private void releasePlayer()
{
if (mExoPlayer != null)
{
mPlayerPosition = mExoPlayer.getCurrentPosition();
mExoPlayer.release();
mExoPlayer = null;
}
}
@Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
//Save the fragment's state here
outState.putParcelableArrayList(STEPS_LIST_INDEX, stepsArrayList);
outState.putLong(KEY_POSITION, mPlayerPosition);
super.onSaveInstanceState(outState);
}
}
Parent Activity:
public class IngredientStepsActivity extends AppCompatActivity implements StepsListFragment.OnStepClickListener
{
private static final String TAG = IngredientStepsActivity.class.getSimpleName();
private Context context;
Recipes recipes;
// Track whether to display a two-pane or single-pane UI
public boolean mTwoPane;
public int stepPosition;
ArrayList<Steps> stepsArrayList;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ingredientsteps);
// Determine if you're creating a two-pane or single-pane display
if (savedInstanceState == null)
{
if (getIntent() != null && getIntent().getExtras() != null)
{
recipes = getIntent().getExtras().getParcelable("Recipes");
if(findViewById(R.id.tablet_detail_layout) != null)
{
// This LinearLayout will only initially exist in the two-pane tablet case
mTwoPane = true;
// Only create new fragments when there is no previously saved state
/*
Add the fragment to its container using a FragmentManager and a Transaction
Send the ingredients array list in Parcelable to the Ingredients Fragment
*/
FragmentManager fragmentManager = getSupportFragmentManager();
Bundle ingredientsBundle = new Bundle();
ingredientsBundle.putParcelable("Recipes", recipes);
//Pass Over the bundle to the Ingredients Fragment
IngredientsFragment ingredientsFragment = new IngredientsFragment();
ingredientsFragment.setArguments(ingredientsBundle);
fragmentManager.beginTransaction().replace(R.id.ingredients_fragment_container, ingredientsFragment).commit();
//Pack Data in a bundle call the bundle "stepsBundle" to differentiate it from the "ingredientsBundle"
Bundle stepsBundle = new Bundle();
stepsBundle.putParcelable("Recipes", recipes);
//Pass Over the bundle to the Steps Fragment
StepsListFragment stepsListFragment = new StepsListFragment();
stepsListFragment.setArguments(stepsBundle);
fragmentManager.beginTransaction().replace(R.id.steps_fragment_container, stepsListFragment).commit();
}
else
{
// We're in single-pane mode and displaying fragments on a phone in separate activities
mTwoPane = false;
FragmentManager fragmentManager = getSupportFragmentManager();
Bundle ingredientsBundle = new Bundle();
ingredientsBundle.putParcelable("Recipes", recipes);
//Pass Over the bundle to the Ingredients Fragment
IngredientsFragment ingredientsFragment = new IngredientsFragment();
ingredientsFragment.setArguments(ingredientsBundle);
fragmentManager.beginTransaction().replace(R.id.ingredients_fragment_container, ingredientsFragment).commit();
//Pack Data in a bundle call the bundle "stepsBundle" to differentiate it from the "ingredientsBundle"
Bundle stepsBundle = new Bundle();
stepsBundle.putParcelable("Recipes", recipes);
//Pass Over the bundle to the Steps Fragment
StepsListFragment stepsListFragment = new StepsListFragment();
stepsListFragment.setArguments(stepsBundle);
fragmentManager.beginTransaction().replace(R.id.steps_fragment_container, stepsListFragment).commit();
}
}
}}
@Override
public void onClick(Steps stepClicked)
{
if (mTwoPane)
{
Bundle stepsVideoBundle = new Bundle();
stepsVideoBundle.putParcelable("Steps", stepClicked);
stepsVideoBundle.putBoolean("TwoPane", mTwoPane);
stepsVideoBundle.putInt("StepPosition", stepPosition);
stepsVideoBundle.putParcelableArrayList("StepsArrayList", stepsArrayList);
VideoFragment videoFragment = new VideoFragment();
videoFragment.setArguments(stepsVideoBundle);
getSupportFragmentManager().beginTransaction().replace(R.id.video_fragment_container, videoFragment).commit();
}
else
{
Log.i("Step: ", stepClicked.getStepShortDescription());
Intent intent = new Intent(IngredientStepsActivity.this, VideoPhoneActivity.class);
intent.putExtra("Steps", stepClicked);
startActivity(intent);
}
}
}