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

时间:2014-12-20 11:37:57

标签: android youtube-api

我在我的应用中使用 YouTubePlayerAPI YouTubePlayerSupportFragment ,我收到以下错误,但我找不到导致它的原因。我一直在寻找信息,但我没有找到任何有用的信息。

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)

在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 (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>

调用方法:

// 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方法中实例化一个新的YouTubeServiceEntity并初始化 YouTube 对象(在内部启动newInstance())。然后,在加载视频时,之前实例化的YouTube片段会附加FragmentManager到相应的FrameLayout

以下是问题:如果用户在加载视频之前退出活动,则会引发异常。

因此,如果用户想要在这种情况下退出活动,我该怎么做以及如何做?我真的不知道该怎么做!

4 个答案:

答案 0 :(得分:1)

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

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

这是YouTubePlayerFragment documentation所说的:

  

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

您可能很想将init()放入onActivityCreated,但为时已晚,因为onStart已被调用且布局已经执行。

onDestroyView的对方是onViewCreated,这是完美的候选人。

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

建议在片段的构造函数中调用setRetainInstance(true)。重新创建活动时,不会重新创建片段,只有其UI将通过生命周期事件。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

我看到华为手机也报告了同样的错误。

我在这里看到一个解释:

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

不确定在我们的代码中是否有捕获异常的方法。

答案 3 :(得分:-1)

这段代码是用xamarin.android编写的,应该有帮助

 public class PlayerActivity : YouTubeBaseActivity, IYouTubePlayerOnInitializedListener, IYouTubePlayerPlayerStateChangeListener
{
    private int RECOVERY_DIALOG_REQUEST = 1;
    public static string DEVELOPER_KEY = "key";
    IYouTubePlayer player;



    //  public static string VIDEO_ID = "_OBlgSz8sSM";
    public void OnInitializationFailure(IYouTubePlayerProvider p0, YouTubeInitializationResult p1)
    {
        if (p1.IsUserRecoverableError)
        {

            p1.GetErrorDialog(this, RECOVERY_DIALOG_REQUEST).Show();
        }
        else
        {
            string errorMessage = string.Format(
                    "ERROR", p1.ToString());
            Toast.MakeText(this, errorMessage, ToastLength.Long).Show();
        }
    }

    public void OnInitializationSuccess(IYouTubePlayerProvider p0, IYouTubePlayer p1, bool p2)
    {


        //  YouTubeItem item = JsonConvert.DeserializeObject<YouTubeItem>(Intent.GetStringExtra("VideoID"));
        YouTubeItem itrm = new YouTubeItem();
        itrm.VideoId = Intent.GetStringExtra("VideoID2");
        string VIDEO_ID = itrm.VideoId;
        p1.LoadVideo(VIDEO_ID);
        player = p1;

        p1.SetPlayerStateChangeListener(this);

    }
    protected override void OnCreate(Bundle savedInstanceState)
    {


        base.OnCreate(savedInstanceState);

        SetContentView(Resource.Layout.PlayerLayout);

        YouTubePlayerView youTubeView = FindViewById<YouTubePlayerView>(Resource.Id.youtubeView);
        youTubeView.Initialize(DEVELOPER_KEY, this);
        // Create your application here
    }

    public void OnAdStarted()
    {

    }

    public void OnError(YouTubePlayerErrorReason p0)
    {

    }

    public void OnLoaded(string p0)
    {


    }

    public void OnLoading()
    {


    }

    public void OnVideoEnded()
    {





        }
    }

    public void OnVideoStarted()
    {

    }