web-dev-qa-db-fra.com

java.lang.IllegalStateException: erreur non initialisée dans YouTubeServiceEntity lors de l'utilisation de YouTubePlayerApi

J'utilise YouTubePlayerAPI et YouTubePlayerSupportFragment dans mon application et le message d'erreur suivant s'affiche, mais je n'ai pas pu trouver la cause. Je cherchais des informations mais je n'ai rien trouvé d'utile.

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)

Dans la pile, il n'y a pas de numéro de ligne pointant vers une de mes classes ou activités.

Une idée de ça?

Merci!

MODIFIER

Ma coutume YoutubePlayerFragment Classe: 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>

méthode d'appel:

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

MODIFIER

J'ai découvert l'origine de cette erreur. Voici le scénario:

L'activité commence. Dans onCreate(), il instancie une nouvelle variable YouTubeVideoPlayerFragment et initialise YouTube object (qui lance YouTubeServiceEntity en interne) dans sa méthode newInstance(). Ensuite, le fragment YouTube qui a été instancié auparavant est attaché avec FragmentManager à la FrameLayout correspondante pendant le chargement de la vidéo.

Voici le problème: Si l'utilisateur quitte l'activité avant que la vidéo ait été chargée, l'exception est levée.

Donc, si l'utilisateur souhaite quitter l'activité dans ce cas, que dois-je faire et comment? Je ne sais pas trop quoi faire!

31
GmloMalo

Encore une fois, n'utilisez PAS les constructeurs de fragments ou les méthodes d'usine pour travailler avec des entités liées au cycle de vie ou liées au contexte. En termes simples, de telles entités ne peuvent être utilisées qu'après l'appel de super.onCreate(...).

La question est maintenant, quand appeler la méthode init?

Voici ce que YouTubePlayerFragment documentation dit:

La YouTubePlayer associée à ce fragment sera publiée chaque fois que sa méthode onDestroyView() est appelée. Vous devrez donc appeler à nouveau initialize(String, YouTubePlayer.OnInitializedListener) chaque fois que l'activité associée à ce fragment est recréée, même si l'instance de fragment est conservée pendant la recréation de l'activité en définissant setRetainInstance(boolean).

Vous pouvez être tenté de mettre init() dans onActivityCreated mais c'est trop tard, car onStart était déjà appelé et la mise en page déjà effectuée.

La contrepartie de onDestroyView est onViewCreated et c'est le candidat idéal.

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

Comme suggéré, appelez setRetainInstance(true) dans le constructeur du fragment. Lorsque l'activité est recréée, le fragment ne sera pas recréé, seule son interface utilisateur passera par des événements de cycle de vie.

1
Eugen Pechanec

Le problème est l'initialisation du fragment Youtube. YouTubePlayerSupportFragment doit être étendu à une classe de votre classe et remplace certaines méthodes. Vous devez contrôler l'orientation de l'écran et le 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);
    }
  }

Activité contenant un fragment de 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();
        }
      }
    }
0
beni