アプリで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
をインスタンス化し、そのnewInstance()
でYouTubeオブジェクト(内部でYouTubeServiceEntity
を開始します)を初期化します。方法。次に、以前にインスタンス化されたYouTube
フラグメントが、ビデオのロード中に対応するFragmentManager
にFrameLayout
でアタッチされます。
ここに問題があります:ビデオがロードされる前にユーザーがアクティビティを終了すると、例外がスローされます。
その場合、ユーザーがアクティビティを終了したい場合は、どうすればよいですか?どうしたらいいのかわからない!
繰り返しになりますが、ライフサイクルまたはコンテキストにバインドされたエンティティを操作するためにフラグメントコンストラクタまたはファクトリメソッドを使用しないでください。簡単に言えば、このようなエンティティは、super.onCreate(...)
が呼び出された後にのみ使用できます。
問題は、いつinit
メソッドを呼び出すかということです。
YouTubePlayerFragment
ドキュメント の内容は次のとおりです。
このフラグメントに関連付けられている
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のみがライフサイクルイベントを通過します。
問題は、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();
}
}
}