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!
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éthodeonDestroyView()
est appelée. Vous devrez donc appeler à nouveauinitialize(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éfinissantsetRetainInstance(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.
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();
}
}
}