我想在ExoPlayer下面实现下一个和上一个按钮。我将代码基于此线程:
Implementing next button in audio player android
以及这些链接中的链接:
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?
Exoplayer处于一个片段中,并在平板电脑屏幕的屏幕右侧打开,并在用户单击配方步骤之一时在移动屏幕的单独活动中打开。到StepsFragment(实现onClickListener)的数据是通过父级活动(以下代码)中的parcelable发送的。
下一个和上一个按钮仅在移动屏幕上实现(代码工作正常)。我在onClick方法中从父活动传递了arraylist和位置,并在片段中检索它们。该代码在没有按钮的情况下也可以正常工作,列表和位置都通过可打包的方式发送到VideoFragment,仅用于实现按钮。我决定将按钮放在“视频片段”中。
单击下一个或上一个按钮时没有任何反应。代码流在onClickListener中代码上方的注释中指示。我尝试调试,但未显示任何错误。这是传递数组列表的正确方法吗?尽管在调试和日志猫中未显示,但我认为它可能为null。有人可以看看吗?预先谢谢你。
VideoFragment(包含Exoplayer代码):
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);
}
}
父母活动:
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);
}
}
}