I found some similar situation, like this and this, but none of then solved my problem.
I have wanna have a screen with youtube video and some text information like this:
I'm using a activity and a fragment, both with base class that extended YouTubeBaseActivity and YouTubePlayerFragment.
But when I'm trying to open the fragment it show a npe but it don't show where. Since I'm getting the layout and view right, I don't now what is going on.
Hope that it don't get downvotes because is a npe question, but is different from usual, this API call don't show me where the NPE happen and I saw the other people has problems like this
Obs: I'm using this extend base concept because more places will have this videos behaviour and I'm trying to avoid code repeat.
XML
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".screens.mine.fragments.MineStepsFragment">
<com.google.android.youtube.player.YouTubePlayerView
android:id="@+id/mine_steps_youtube_player"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/background_white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
</com.google.android.youtube.player.YouTubePlayerView>
</android.support.constraint.ConstraintLayout>
Activity
public class MineAccidentActivity extends BaseYoutubeActivity {
@Override
protected void initializeActionBar() {
actionbarLeftBtn.setVisibility(View.VISIBLE);
actionbarTitle.setVisibility(View.VISIBLE);
}
@Override
protected int getActionbarTitle() {
return R.string.mine_accident;
}
@Override
protected int getContentView() {
return R.layout.mine_accident_activity;
}
@Override
protected void assignViews() {
MineAccidentController.getInstance().attachToActivity(this, R.id.mine_container);
}
@Override
protected void prepareViews() {}
/////////////////// BACK ////////////////////
@Override
public void onBackPressed() {
if (!MineAccidentController.getInstance().isFirstFragmentShown()) {
MineAccidentController.getInstance().showPreviousFragment();
} else {
super.onBackPressed();
}
}
/////////////////// LIFE CYCLE ////////////////////
@Override
protected void onDestroy() {
MineAccidentController.getInstance().onDestroy();
super.onDestroy();
}
}
Fragment Controller
public class MineAccidentController extends BaseYoutubeController {
private String accidentType;
@Override
protected ArrayList<android.app.Fragment> initFragments() {
ArrayList<android.app.Fragment> fragments = new ArrayList<>();
fragments.add(new MineStepsFragment());
return fragments;
}
//create Class
public static MineAccidentController getInstance() {
if (null == instance) {
synchronized (MineAccidentController.class) {
if (null == instance) {
setInstance(new MineAccidentController());
}
}
}
return (MineAccidentController) instance;
}
public String getAccidentType() {
return accidentType;
}
public void setAccidentType(String accidentType) {
this.accidentType = accidentType;
}
}
Fragment
public class MineStepsFragment extends BaseYoutubeFragment {
//Not in Layout
private String videoUrl;
////////////// IMPLEMENT_METHODS //////////////
@Override
protected int getFragmentContentView() {
return R.layout.mine_steps_fragment;
}
@Override
protected int getYoutubePlayerView() {
return R.id.mine_steps_youtube_player;
}
@Override
protected void assignViews() {
}
@Override
protected void prepareViews() {
}
@Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean wasRestored) {
if(!wasRestored){
checkType();
youTubePlayer.cueVideo(videoUrl);
}
}
@Override
public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
showErrorToast(getActivity(), R.string.error_initialize_video);
}
////////////// FUNCTIONS //////////////
private void checkType() {
if(MineAccidentController.getInstance().getAccidentType().equals(Parameters.ACCIDENT_PERSONAL)){
videoUrl = Properties.MINE_PERSONAL_VIDEO;
}
else {
videoUrl = Properties.MINE_WORK_VIDEO;
}
}
}
Base Fragment
public abstract class BaseYoutubeFragment extends YouTubePlayerFragment implements YouTubePlayer.OnInitializedListener {
protected View fragmentView = null;
protected YouTubePlayerView youTubePlayerView;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
assignViews();
prepareViews();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
fragmentView = inflater.inflate(getFragmentContentView(), container, false);
youTubePlayerView = fragmentView.findViewById(getYoutubePlayerView());
youTubePlayerView.initialize(com.can_apps.eva_ngo.properties.Properties.API_KEY, this);
return fragmentView;
}
/////////////////// ABSTRACT METHODS ////////////////////
protected abstract int getFragmentContentView(); //Get Layout R.layout.name_file
protected abstract int getYoutubePlayerView(); //Get Container for YOutube Video
protected abstract void assignViews(); //Used for findById the params
protected abstract void prepareViews(); //Used for start the values of params
/////////////////// SHOW MESSAGES ////////////////////
public void showErrorToast(Context context, final int message) {
Toast toast = Toast.makeText(context, getString(message), Toast.LENGTH_SHORT);
View view = toast.getView();
view.setBackgroundResource(R.color.background_red_transparent);
toast.show();
}
/////////////////// SNACK BAR ////////////////////
public void showSnackBar(final int text) {
Snackbar.make(Objects.requireNonNull(getView()), getString(text), Snackbar.LENGTH_SHORT).show();
}
public void showSnackBar(final int mainTextStringId, final int actionStringId, View.OnClickListener listener) {
Snackbar.make(Objects.requireNonNull(getView()),
getString(mainTextStringId),
Snackbar.LENGTH_LONG)
.setAction(getString(actionStringId), listener).show();
}
}
Looking at the logcat it looks like your YouTubePlayerView
is null when you are calling one of its methods.
The YouTube Player API is quite buggy and difficult to use correctly. To solve this problems (and others) I have built an alternative player Android-YouTube-Player, it's open source and you can do whatever you want with it.
In your case, you won't have to meddle with Fragments and transactions, since my YouTubePlayerView
is just a regular view and requires no special Fragments or Activities. You can drop it wherever you want.
Hope it could be useful to you as well!