36

I'm using YouTubePlayerAPI and YouTubePlayerSupportFragment in my app and I'm getting the following error, but I couldn't find out what is causing it. I've been looking for information but I haven't found anything useful.

java.lang.IllegalStateException: YouTubeServiceEntity not initialized
    at android.os.Parcel.readException(Parcel.java:1433)
    at android.os.Parcel.readException(Parcel.java:1379)
    at com.google.android.youtube.player.internal.l$a$a.a(Unknown Source)
    at com.google.android.youtube.player.internal.o.a(Unknown Source)
    at com.google.android.youtube.player.internal.ad.a(Unknown Source)
    at com.google.android.youtube.player.YouTubePlayerView.a(Unknown Source)
    at com.google.android.youtube.player.YouTubePlayerView$1.a(Unknown Source)
    at com.google.android.youtube.player.internal.r.g(Unknown Source)
    at com.google.android.youtube.player.internal.r$c.a(Unknown Source)
    at com.google.android.youtube.player.internal.r$b.a(Unknown Source)
    at com.google.android.youtube.player.internal.r$a.handleMessage(Unknown Source)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5041)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    at dalvik.system.NativeStart.main(Native Method)

In the stackstrace there isn't any line number pointing to any of my classes or activities.

Any idea of it?

Thanks!

EDIT

My custom YoutubePlayerFragment Class: YouTubeVideoPlayerFragment.java

public class YouTubeVideoPlayerFragment extends YouTubePlayerSupportFragment {


private static final String ARG_URL = "url";


// ===========================================================
// Constructors
// ===========================================================

/**
 * Mandatory empty constructor for the fragment manager to instantiate the
 * fragment (e.g. upon screen orientation changes).
 */
public YouTubeVideoPlayerFragment() {
}

/**
 * Factory method to generate a new instance of the fragment given a video URL.
 *
 * @param url The video url this fragment represents
 * @return A new instance of this fragment with itemId extras
 */
public static YouTubeVideoPlayerFragment newInstance(String url) {
    final YouTubeVideoPlayerFragment mFragment = new YouTubeVideoPlayerFragment();

    // Set up extras
    final Bundle args = new Bundle();
    args.putString(ARG_URL, url);
    mFragment.setArguments(args);

    // Initialize YouTubePlayer
    mFragment.init();

    return mFragment;
}



@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

}

private void init(){
    initialize(Constants.API_KEY, new YouTubePlayer.OnInitializedListener() {
        @Override
        public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean wasRestored) {
            if (!wasRestored) {
                youTubePlayer.cueVideo(getArguments().getString(ARG_URL));
                youTubePlayer.setShowFullscreenButton(false);
            }
    }
}

fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:background="@color/black" >

    <!-- For YoutubeFragment -->
    <FrameLayout
        android:id="@+id/youtube_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

calling method:

// Create a new instance of YouTubeVideoPlayerFragment providing video id
        // and place it in the corresponding FrameLayout
        final YouTubeVideoPlayerFragment youTubeVideoPlayerFragment = YouTubeVideoPlayerFragment.newInstance(VIDEO_ID);
        final FragmentTransaction ft = getChildFragmentManager().beginTransaction();
        ft.replace(R.id.youtube_fragment, youTubeVideoPlayerFragment);
        ft.commit();

EDIT

I've found out the origin of that error. This is the scenario:

The activity starts. In onCreate() it instantiates a new YouTubeVideoPlayerFragment and initializes YouTube object (which starts the YouTubeServiceEntity internally) in its newInstance() method. Then the YouTube fragment that was instantiated before, is attached with FragmentManager to the corresponding FrameLayout while video is loading.

Here is the issue: If user exits the activity before video had been loaded, the exception is thrown.

So if user want to exit from the activity in that case, what should I do and how? I don't really know what to do!

Onur A.
  • 3,007
  • 3
  • 22
  • 37
GmloMalo
  • 667
  • 7
  • 14
  • 1
    can you show your code where you initialized YouTubeServiceEntity – Syeda Zunaira Dec 20 '14 at 11:40
  • Edited with code @Zoya – GmloMalo Dec 20 '14 at 12:01
  • Sorry but I am still unable to find the initialization of YouTubeServiceEntity. and your logcat is also reporting the same problem – Syeda Zunaira Dec 20 '14 at 12:04
  • Sorry! I dont directly initialize YouTubeServiceEntity. I suppose it is initialized trought the YouTubePlayerApi jar library – GmloMalo Dec 20 '14 at 13:32
  • Did you ever find a work around for this? – Scott Cooper Mar 08 '15 at 12:37
  • 1
    I'm using Youtube api and facing this error very much. Did you find a solution for this? – Huy Duong Tu Dec 28 '15 at 03:08
  • @HuyDuongTu not yet. I haven't guess how could i check if the init has finished as is answered by a user in that link: https://code.google.com/p/gdata-issues/issues/detail?id=6582 – GmloMalo Dec 28 '15 at 22:25
  • Java.lang.IllegalStateException: YouTubeServiceEntity not initialized does that happen when you stay in the activity or when the user exits the activity? – QVDev Jan 25 '17 at 15:12
  • Please take a look into this https://issuetracker.google.com/issues/35175333 – Swapnil Kshirsagar Feb 27 '17 at 12:42
  • where is the actual view declared? I mean where is the YouTubePlayerView? – paul_hundal Apr 01 '17 at 11:15
  • @paul_hundal The view is handled internally by the fragment. [Read the docs.](https://developers.google.com/youtube/android/player/reference/com/google/android/youtube/player/YouTubePlayerFragment) – Eugen Pechanec Apr 09 '17 at 22:25
  • issue isn't about YouTube Android Player Fragment version. I use YouTube Android Player only with activity and have same issue: I get some reports from Google Console `java.lang.IllegalStateException android.os.Parcel.readException` – user25 Jan 05 '19 at 22:54
  • created an issue (official repository) https://github.com/youtube/yt-android-player/issues/23 – user25 Jan 05 '19 at 22:57

3 Answers3

4

Once again, do NOT use fragment constructors or factory methods to work with lifecycle or context bound entities. Simply put, such entities can only be used after super.onCreate(...) has been called.

The question now is, when to call the init method?

Here's what YouTubePlayerFragment documentation says:

The YouTubePlayer associated with this fragment will be released whenever its onDestroyView() method is called. You will therefore have to re-call initialize(String, YouTubePlayer.OnInitializedListener) whenever the activity associated with this fragment is recreated, even if the fragment instance is retained across activity re-creation by setting setRetainInstance(boolean).

You may be tempted to put init() in onActivityCreated but that's too late, since onStart was already called and layout already performed.

Counterpart to onDestroyView is onViewCreated and that's the perfect candidate.

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    init();
}

As suggested call setRetainInstance(true) in the fragment's constructor. When the activity is recreated the fragment will not be recreated, only its UI will go through lifecycle events.

Eugen Pechanec
  • 37,669
  • 7
  • 103
  • 124
  • I use only activity with YouTube player and still I get some reports from Google Console about this issue: `java.lang.IllegalStateException android.os.Parcel.readException`. So it's not about fragments (I don't use them) – user25 Jan 05 '19 at 22:52
  • I'm calling init() from onResume() still getting the crash..Any idea? – Astha Garg Jul 15 '20 at 05:30
  • I am calling init() inside onViewCreated and get the same bug – Duna Nov 12 '20 at 08:58
  • 1
    @Duna Looks like a problem with saved state. Emulate state restoration by going to Developer Settings and check [Don't keep activities](https://stackoverflow.com/questions/22400859/dont-keep-activities-what-is-it-for) option at the end. Then start your player, press Home, then go back to your player. It should crash. Open a new SO question with the entire stack trace. – Eugen Pechanec Nov 12 '20 at 09:30
1

I see the same error reported from a Huawei cellphone.

I see an explanation here:

https://github.com/youtube/yt-android-player/issues/23

Not sure if there is a way to catch the exception in our code.

Pablo Alfonso
  • 2,317
  • 1
  • 18
  • 24
0

The problem is the initialization of the Youtube fragment. YouTubePlayerSupportFragment has to be extended in a class of yours and overrides some methods. You have to control the screen orientation and the onSaveInstanceState.

public class YouTubePlayerFragment extends YouTubePlayerSupportFragment {

  private YouTubePlayer mPlayer;

  public static YouTubePlayerFragment newInstance() {
    return new YouTubePlayerFragment();
  }

  @Override public void onCreate(Bundle bundle) {
    super.onCreate(bundle);

    setRetainInstance(true);
  }

  @Override
  public void initialize(String s, YouTubePlayer.OnInitializedListener onInitializedListener) {
    super.initialize(s, new YouTubePlayer.OnInitializedListener() {
      @Override public void onInitializationSuccess(YouTubePlayer.Provider provider,
      YouTubePlayer youTubePlayer, boolean b) {

        mPlayer = youTubePlayer;

        onInitializedListener.onInitializationSuccess(provider, youTubePlayer, b);
      }

      @Override public void onInitializationFailure(YouTubePlayer.Provider provider,
      YouTubeInitializationResult youTubeInitializationResult) {

        onInitializedListener.onInitializationFailure(provider, youTubeInitializationResult);
      }
    });
  }

  @Override public void onDestroyView() {
    if (mPlayer != null) {

      mPlayer.release();
    }
    super.onDestroyView();
  }

  public YouTubePlayer getPlayer() {
    return mPlayer;
  }
}

YoutubeFragment.class

      public class YoutubeFragment extends Fragment {

    private static final String EXTRA_PLAYED_VIDEO = "EXTRA_PLAYED_VIDEO";
    private static final String EXTRA_IS_PLAYING = "EXTRA_IS_PLAYING";
    private static final String YOUTUBE_FRAGMENT = "YOUTUBE_FRAGMENT";
    private static final String EXTRA_YOUTUBE_ID = "EXTRA_YOUTUBE_ID";

    private RelativeLayout youtubeLayoutContainer;

    private String youtubeId;
    private int playedVideo;
    private boolean isPlaying;

    YouTubePlayer.OnInitializedListener onInitializedListener =
        new YouTubePlayer.OnInitializedListener() {

          @Override
          public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer player,
              boolean wasRestored) {

            if (!wasRestored) {
              setYouTubePlayer(player);
            }
          }

          @Override public void onInitializationFailure(YouTubePlayer.Provider provider,
              YouTubeInitializationResult error) {
          }
        };

    public static YoutubeFragment newInstance(String youtubeId) {
      YoutubeFragment youtubeElements = new YoutubeFragment();

      Bundle bundle = new Bundle();
      bundle.putString(EXTRA_YOUTUBE_ID, youtubeId);
      youtubeElements.setArguments(bundle);

      return youtubeElements;
    }

    @Override public void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      setRetainInstance(true);
    }

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

      View mView = inflater.inflate(R.layout.view_youtube_elements_item, container, false);

      initViews(mView);

      initYoutubeFragment();

      return mView;
    }

    private void initViews(View view) {
      youtubeLayoutContainer = (RelativeLayout) view.findViewById(R.id.youtubeLayoutContainer);

      youtubeLayoutContainer.getViewTreeObserver()
          .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void onGlobalLayout() {
              FrameLayout.LayoutParams lp =
                  new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
                      FrameLayout.LayoutParams.MATCH_PARENT);

              youtubeLayoutContainer.setLayoutParams(lp);
              if (AndroidSdkVersion.hasJellyBean16()) {
                youtubeLayoutContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
              }
            }
          });
    }

    private void initYoutubeFragment() {
      try {
        YouTubePlayerFragment youTubePlayerFragment2 = YouTubePlayerFragment.newInstance();
        youTubePlayerFragment2.initialize(BuildConfig.YOUTUBE_DEVELOPER_KEY, onInitializedListener);

        if (this.getActivity() != null && !this.getActivity().isFinishing()) {
          getChildFragmentManager().beginTransaction()
              .replace(R.id.youtubePlayerFragmentContent, youTubePlayerFragment2, YOUTUBE_FRAGMENT)
              .commitAllowingStateLoss();
        }
      } catch (Exception ignored) {
      }
    }

    public void setYouTubePlayer(final YouTubePlayer player) {
      try {
        if (player == null) {
          return;
        }

        player.setShowFullscreenButton(true);
        player.setPlayerStyle(YouTubePlayer.PlayerStyle.DEFAULT);

        if (playedVideo >= 0) {
          if (playedVideo == 0 || isPlaying) {
            player.loadVideo(youtubeId, playedVideo);
          } else {
            player.cueVideo(youtubeId, playedVideo);
          }
        }
      } catch (Exception ignored) {
      }
    }

    @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
      super.onViewCreated(view, savedInstanceState);

      if (savedInstanceState != null) {
        playedVideo = savedInstanceState.getInt(EXTRA_PLAYED_VIDEO);
        isPlaying = savedInstanceState.getBoolean(EXTRA_IS_PLAYING);
      }
    }

    @Override public void onSaveInstanceState(Bundle outState) {
      try {
        YouTubePlayerFragment youTubePlayerSupportFragment =
            (YouTubePlayerFragment) getChildFragmentManager().findFragmentByTag(YOUTUBE_FRAGMENT);
        YouTubePlayer mPlayer = youTubePlayerSupportFragment.getPlayer();

        if (mPlayer != null) {
          outState.putInt(EXTRA_PLAYED_VIDEO, mPlayer.getCurrentTimeMillis());
          outState.putBoolean(EXTRA_IS_PLAYING, mPlayer.isPlaying());
        }
      } catch (Exception ignored) {
      }

      super.onSaveInstanceState(outState);
    }
  }

Activity containing Youtube Fragment

public class YoutubeContentDataActivity extends BaseActivity {

      private static final String EXTRA_YOUTUBE_VIDEO_ID = "EXTRA_YOUTUBE_VIDEO_ID";
      private static final String TAG_RETAINED_FRAGMENT = "TAG_RETAINED_FRAGMENT";

      public static void open(Context context, String videoId) {

        Intent intent = new Intent(context, YoutubeContentDataActivity.class);
        intent.putExtra(EXTRA_YOUTUBE_VIDEO_ID, videoId);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
      }

      @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_youtube_main_container_layout);

        FragmentManager fm = getSupportFragmentManager();
        YoutubeFragment youtubeElementsFragment =
            (YoutubeFragment) fm.findFragmentByTag(TAG_RETAINED_FRAGMENT);

        // create the fragment and data the first time
        if (youtubeElementsFragment == null) {

          String videoId = getIntent().getStringExtra(EXTRA_YOUTUBE_VIDEO_ID);
          // videoId = "17uHCHfgs60";//"ikO91fQBsTQ";
          youtubeElementsFragment = YoutubeFragment.newInstance(videoId);
          FragmentManager fragmentManager = getSupportFragmentManager();
          fragmentManager.beginTransaction()
              .replace(R.id.youtube_main_container, youtubeElementsFragment, TAG_RETAINED_FRAGMENT)
              .commit();
        }
      }

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

        if (isFinishing()) {
          FragmentManager fm = getSupportFragmentManager();

          YoutubeFragment youtubeElementsFragment =
              (YoutubeFragment) fm.findFragmentByTag(TAG_RETAINED_FRAGMENT);

          fm.beginTransaction().remove(youtubeElementsFragment).commit();
        }
      }
    }
beni
  • 3,019
  • 5
  • 35
  • 55
  • I believe it has nothing to do with fragments, cause I have this issue using only activity: https://github.com/youtube/yt-android-player/issues/23 – user25 Jan 05 '19 at 23:06
  • I have restricted change in screen orientation, still I'm getting this crash..Any idea? – Astha Garg Jul 15 '20 at 05:34