java.lang.IllegalStateException:使用YouTubePlayerApi时,YouTubeServiceEntity未初始化错误

我正在使用YouTubePlayerAPIYouTubePlayerSupportFragment在我的应用程序,我收到以下错误,但我无法找出是什么原因造成的。 我一直在寻找信息,但我没有find有用的东西。

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$aa(Unknown Source) at com.google.android.youtube.player.internal.oa(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.rg(Unknown Source) at com.google.android.youtube.player.internal.r$ca(Unknown Source) at com.google.android.youtube.player.internal.r$ba(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) 

在stackstrace中,没有任何行号指向我的任何类或活动。

有什么想法吗?

谢谢!

编辑

我的自定义YoutubePlayerFragment类: 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 (eg 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> 

调用方法:

 // 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(); 

编辑

我发现了这个错误的起源。 这是场景:

活动开始。 在onCreate()实例化一个新的YouTubeVideoPlayerFragment并在其newInstance()方法中初始化YouTube对象(内部启动YouTubeServiceEntity newInstance() 。 然后,在加载video的同时,之前实例化的YouTube片段将与FragmentManager附加到相应的FrameLayout

问题如下:如果用户在加载video之前退出该活动,则会抛出exception。

因此,如果用户想要退出该活动,我应该怎么做? 我真的不知道该怎么做!

再次,不要使用片段构造函数或工厂方法来处理生命周期或上下文绑定的实体。 简单地说,这样的实体只能在super.onCreate(...)被调用后才能使用。

现在的问题是,何时调用init方法?

以下是YouTubePlayerFragment文档所说的内容:

与这个片段关联的YouTubePlayer只要调用onDestroyView()方法就会被释放。 因此,即使片段实例通过设置setRetainInstance(boolean)在重新创build活动时被保留,每当重新创build与此片段相关联的活动时initialize(String, YouTubePlayer.OnInitializedListener)也必须重新调用initialize(String, YouTubePlayer.OnInitializedListener) setRetainInstance(boolean)

你可能会试图把init()放在onActivityCreated但这已经太晚了,因为onStart已经被调用,layout已经被执行了。

onDestroyViewonViewCreated ,这是完美的人选。

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

build议在片段的构造函数中调用setRetainInstance(true) 。 当活动被重新创build时,片段不会被重新创build,只有它的用户界面会经历生命周期事件。

问题是Youtube片段的初始化。 YouTubePlayerSupportFragment必须在您的类中进行扩展,并覆盖一些方法。 您必须控制屏幕方向和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); } } 

包含Youtube片段的活动

 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(); } } }