android - YouTube API 在全屏模式下变为空白 - Android

标签 android video youtube landscape android-fullscreen

我正在使用 YouTube API v3并获得 List 的缩略图视频工作得很好,当您单击列表中的视频时,它会在播放视频的列表上方弹出一个视频框。这部分有效。但是视频盒是作为 API 的一部分创建的。库(我假设),因此单击框中的全屏按钮以使其进入全屏状态。但是,当我进入全屏时,视频消失并且是空白的。没有崩溃或任何东西,只是空白。我的初始化工作正常。我得到 errorReason SUCCESS 的值当我记录它时。所以我不知道还有什么可能导致这个空白。

在其他一些 YouTube API我在网上找到的代码,他们使用 Intent进入全屏模式,但这不是 YouTube 中的视频列表类示例用途,所以我不知道是否需要这种方式。 YouTube示例完美地作为列表工作,它显示视频列表,然后当您单击视频框上的那个微小的展开按钮时无缝进入全屏(横向)模式。

Video box over list items

好像我错过了什么?请记住,视频框和全屏模式都是 fragment ,并且是通过程序创建的,而不是在 UI 中。 .在我的 xml 中,您只会看到 fragment 占位符,其中引用了它们的 UI 所在的类。被 build 。

谢谢你的帮助。

视频 Activity .java

package org.azurespot.cutelinks.cutevideos;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.ListFragment;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.youtube.player.YouTubeApiServiceUtil;
import com.google.android.youtube.player.YouTubeInitializationResult;
import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayer.OnFullscreenListener;
import com.google.android.youtube.player.YouTubePlayer.Provider;
import com.google.android.youtube.player.YouTubePlayerFragment;
import com.google.android.youtube.player.YouTubeThumbnailLoader;
import com.google.android.youtube.player.YouTubeThumbnailView;

import org.azurespot.R;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;


public class VideosActivity extends ActionBarActivity implements
        OnFullscreenListener {

    /** The duration of the animation sliding up the video in portrait. */
    private static final int ANIMATION_DURATION_MILLIS = 300;
    /** The padding between the video list and the video in landscape orientation. */
    private static final int LANDSCAPE_VIDEO_PADDING_DP = 5;
    protected static final int RECOVERY_DIALOG_REQUEST = 1;
    /** The padding between the video list and the video in landscape orientation. */
    private VideoListFragment listFragment;
    private VideoFragment videoFragment;
    private View videoBox;
    private View closeButton;
    private boolean isFullscreen;
    private boolean isPortrait;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_videos);

        getSupportActionBar().setDisplayUseLogoEnabled(false);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        listFragment = (VideoListFragment) getFragmentManager().
                findFragmentById(R.id.list_fragment);
        videoFragment = (VideoFragment) getFragmentManager().findFragmentById
                        (R.id.video_fragment_container);

        videoBox = findViewById(R.id.video_box);
        closeButton = findViewById(R.id.close_button);

        videoBox.setVisibility(View.INVISIBLE);

        layout();

        checkYouTubeApi();

    }

    private void checkYouTubeApi() {
        YouTubeInitializationResult errorReason =
                YouTubeApiServiceUtil.isYouTubeApiServiceAvailable(this);
        Log.e("ERROR RESULT", "Error initialization result is " + errorReason);
        if (errorReason.isUserRecoverableError()) {
            errorReason.getErrorDialog(this, RECOVERY_DIALOG_REQUEST).show();
        } else if (errorReason != YouTubeInitializationResult.SUCCESS){
            String errorMessage = String.format(getString(R.string.error_player),
                    errorReason.toString());
            Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == RECOVERY_DIALOG_REQUEST) {
            // Recreate the activity if user performed a recovery action
            recreate();
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        layout();
    }

    @Override
    public void onFullscreen(boolean isFullscreen) {
        this.isFullscreen = isFullscreen;

        layout();
    }

    /**
     * Sets up the layout programatically for the three different states. Portrait, landscape or
     * fullscreen+landscape. This has to be done programmatically because we handle the orientation
     * changes ourselves in order to get fluent fullscreen transitions, so the xml layout resources
     * do not get reloaded.
     */
    private void layout() {
        isPortrait =
                getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
        listFragment.getView().setVisibility(isFullscreen ? View.GONE : View.VISIBLE);
        listFragment.setLabelVisibility(isPortrait);
        closeButton.setVisibility(isPortrait ? View.VISIBLE : View.GONE);

        if (isFullscreen) {
            videoBox.setTranslationY(0); // Reset any translation that was applied in portrait.
            setLayoutSize(videoFragment.getView(), MATCH_PARENT, MATCH_PARENT);
            setLayoutSizeAndGravity(videoBox, MATCH_PARENT, MATCH_PARENT, Gravity.TOP | Gravity.START);
        } else if (isPortrait) {
            setLayoutSize(listFragment.getView(), MATCH_PARENT, MATCH_PARENT);
            setLayoutSize(videoFragment.getView(), MATCH_PARENT, WRAP_CONTENT);
            setLayoutSizeAndGravity(videoBox, MATCH_PARENT, WRAP_CONTENT, Gravity.BOTTOM);
        } else {
            videoBox.setTranslationY(0); // Reset any translation that was applied in portrait.
            int screenWidth = dpToPx(getResources().getConfiguration().screenWidthDp);
            setLayoutSize(listFragment.getView(), screenWidth / 4, MATCH_PARENT);
            int videoWidth = screenWidth - screenWidth / 4 - dpToPx(LANDSCAPE_VIDEO_PADDING_DP);
            setLayoutSize(videoFragment.getView(), videoWidth, WRAP_CONTENT);
            setLayoutSizeAndGravity(videoBox, videoWidth, WRAP_CONTENT,
                    Gravity.END | Gravity.CENTER_VERTICAL);
        }
    }

    public void onClickClose(@SuppressWarnings("unused") View view) {
        listFragment.getListView().clearChoices();
        listFragment.getListView().requestLayout();
        videoFragment.pause();
        ViewPropertyAnimator animator = videoBox.animate()
                .translationYBy(videoBox.getHeight())
                .setDuration(ANIMATION_DURATION_MILLIS);
        runOnAnimationEnd(animator, new Runnable() {
            @Override
            public void run() {
                videoBox.setVisibility(View.INVISIBLE);
            }
        });
    }

    private void runOnAnimationEnd(ViewPropertyAnimator animator, final Runnable runnable) {
        if (Build.VERSION.SDK_INT >= 21) {
            animator.withEndAction(runnable);
        } else {
            animator.setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    runnable.run();
                }
            });
        }
    }

    /**
     * A fragment that shows a static list of videos.
     */
    public static class VideoListFragment extends ListFragment{
        private static final List<VideoEntry> VIDEO_LIST;
        static {
            List<VideoEntry> list = new ArrayList<VideoEntry>();
            list.add(new VideoEntry("Corgi Puppy Cam", "kvxJNEl6OD4"));
            list.add(new VideoEntry("Husky Puppy Cam", "wo04ZWLAnvo"));
            list.add(new VideoEntry("Yorkie Puppy Cam", "Fen9ZXNS2Ug"));
            list.add(new VideoEntry("Schnauzer Puppy Live Cam", "i2-MnWWoL6M"));
            list.add(new VideoEntry("Relaxing Bird Feeder", "jMbtQLQoWZ8"));
            list.add(new VideoEntry("Guy Gets Smothered by Bunnies on Japan's Rabbit Island!", "pY-GncsZ-UE"));
            list.add(new VideoEntry("キツネ100匹! - Fox Village", "tMo9FWwKoiA"));
            list.add(new VideoEntry("Cute Alpacas!", "bwL7xUC6LqQ"));
            list.add(new VideoEntry("Cute Pygmy Goats!", "ScCa7fZ-xPA"));
            list.add(new VideoEntry("Cute Peruvian Hairless Dogs!", "le8yAr7PlSE"));
            list.add(new VideoEntry("Cute Baby Boar Piglets!", "Ww9zBgvxt80"));
            list.add(new VideoEntry("The Red Pandas of Darjeeling District, India.", "Cn3tk-rUl5Q"));
            list.add(new VideoEntry("Smart and Clever Animals", "V7BVUjB93ew"));
            list.add(new VideoEntry("Animal Odd Couples 1of2", "k9pzi8W8At0"));
            list.add(new VideoEntry("Pets Interrupting Yoga", "QQYK5vT9TBI"));
            list.add(new VideoEntry("Two Chinchillas, One Sock!", "e56I_syIMwk"));
            VIDEO_LIST = Collections.unmodifiableList(list);
        }

        private PageAdapter adapter;
        private View videoBox;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            adapter = new PageAdapter(getActivity(), VIDEO_LIST);
        }

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);

            videoBox = getActivity().findViewById(R.id.video_box);
            getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            setListAdapter(adapter);
        }

        @Override
        public void onListItemClick(ListView l, View v, int position, long id) {
            String videoId = VIDEO_LIST.get(position).videoId;

            VideoFragment videoFragment =
                    (VideoFragment) getFragmentManager().findFragmentById(R.id.video_fragment_container);
            videoFragment.setVideoId(videoId);

            // The videoBox is INVISIBLE if no video was previously selected, so we need to show it now.
            if (videoBox.getVisibility() != View.VISIBLE) {
                if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                    // Initially translate off the screen so that it can be animated in from below.
                    videoBox.setTranslationY(videoBox.getHeight());
                }
                videoBox.setVisibility(View.VISIBLE);
            }

            // If the fragment is off the screen, we animate it in.
            if (videoBox.getTranslationY() > 0) {
                videoBox.animate().translationY(0).setDuration(ANIMATION_DURATION_MILLIS);
            }
        }

        @Override
        public void onDestroyView() {
            super.onDestroyView();

            adapter.releaseLoaders();
        }

        public void setLabelVisibility(boolean visible) {
            adapter.setLabelVisibility(visible);
        }

    }


    private static final class PageAdapter extends BaseAdapter {

        private final List<VideoEntry> entries;
        private final List<View> entryViews;
        private final Map<YouTubeThumbnailView, YouTubeThumbnailLoader> thumbnailViewToLoaderMap;
        private final LayoutInflater inflater;
        private final ThumbnailListener thumbnailListener;

        private boolean labelsVisible;

        public PageAdapter(Context context, List<VideoEntry> entries) {
            this.entries = entries;

            entryViews = new ArrayList<>();
            thumbnailViewToLoaderMap = new HashMap<>();
            inflater = LayoutInflater.from(context);
            thumbnailListener = new ThumbnailListener();

            labelsVisible = true;
        }

        public void releaseLoaders() {
            for (YouTubeThumbnailLoader loader : thumbnailViewToLoaderMap.values()) {
                loader.release();
            }
        }

        public void setLabelVisibility(boolean visible) {
            labelsVisible = visible;
            for (View view : entryViews) {
                view.findViewById(R.id.text).setVisibility(visible ? View.VISIBLE : View.GONE);
            }
        }

        @Override
        public int getCount() {
            return entries.size();
        }

        @Override
        public VideoEntry getItem(int position) {
            return entries.get(position);
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = convertView;
            VideoEntry entry = entries.get(position);

            // There are three cases here
            if (view == null) {
                // 1) The view has not yet been created - we need to initialize the YouTubeThumbnailView.
                view = inflater.inflate(R.layout.you_tube_row_item, parent, false);
                YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
                thumbnail.setTag(entry.videoId);
                thumbnail.initialize(DeveloperKey.DEVELOPER_KEY, thumbnailListener);
            } else {
                YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
                YouTubeThumbnailLoader loader = thumbnailViewToLoaderMap.get(thumbnail);
                if (loader == null) {
                    // 2) The view is already created, and is currently being initialized. We store the
                    //    current videoId in the tag.
                    thumbnail.setTag(entry.videoId);
                } else {
                    // 3) The view is already created and already initialized. Simply set the right videoId
                    //    on the loader.
                    thumbnail.setImageResource(R.drawable.loading_thumbnail);
                    loader.setVideo(entry.videoId);
                }
            }
            TextView label = ((TextView) view.findViewById(R.id.text));
            label.setText(entry.text);
            label.setVisibility(labelsVisible ? View.VISIBLE : View.GONE);
            return view;
        }

        private final class ThumbnailListener implements
                YouTubeThumbnailView.OnInitializedListener,
                YouTubeThumbnailLoader.OnThumbnailLoadedListener {

            @Override
            public void onInitializationSuccess(
                    YouTubeThumbnailView view, YouTubeThumbnailLoader loader) {
                loader.setOnThumbnailLoadedListener(this);
                thumbnailViewToLoaderMap.put(view, loader);
                view.setImageResource(R.drawable.loading_thumbnail);
                String videoId = (String) view.getTag();
                loader.setVideo(videoId);
            }

            @Override
            public void onInitializationFailure(
                    YouTubeThumbnailView view, YouTubeInitializationResult loader) {
                view.setImageResource(R.drawable.no_thumbnail);
            }

            @Override
            public void onThumbnailLoaded(YouTubeThumbnailView view, String videoId) {
            }

            @Override
            public void onThumbnailError(YouTubeThumbnailView view, YouTubeThumbnailLoader.ErrorReason errorReason) {
                view.setImageResource(R.drawable.no_thumbnail);
            }
        }

    }


    public static class VideoFragment extends YouTubePlayerFragment
            implements YouTubePlayer.OnInitializedListener {

        YouTubePlayer player;
        private String videoId;

        public static VideoFragment newInstance() {
            return new VideoFragment();
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            initialize(DeveloperKey.DEVELOPER_KEY, this);
            newInstance();
        }

        @Override
        public void onDestroy() {
            if (player != null) {
                player.release();
            }
            super.onDestroy();
        }

        public void setVideoId(String videoId) {
            if (videoId != null && !videoId.equals(this.videoId)) {
                this.videoId = videoId;
                if (player != null) {
                    player.cueVideo(videoId);
                }
            }
        }

        public void pause() {
            if (player != null) {
                player.pause();
            }
        }

        @Override
        public void onInitializationSuccess(Provider provider,
                                      YouTubePlayer player, boolean restored) {
            this.player = player;
            player.addFullscreenControlFlag(YouTubePlayer.
                    FULLSCREEN_FLAG_CUSTOM_LAYOUT);
            player.setOnFullscreenListener((VideosActivity) getActivity());
            if (!restored && videoId != null) {
                player.cueVideo(videoId);
            }
        }

        @Override
        public void onInitializationFailure(Provider provider,
                                            YouTubeInitializationResult result) {
            this.player = null;
        }
    }

    private static final class VideoEntry {
        private final String text;
        private final String videoId;

        public VideoEntry(String text, String videoId) {
            this.text = text;
            this.videoId = videoId;
        }
    }

    // Utility methods for layouting.

    private int dpToPx(int dp) {
        return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
    }

    private static void setLayoutSize(View view, int width, int height) {
        ViewGroup.LayoutParams params = view.getLayoutParams();
        params.width = width;
        params.height = height;
        view.setLayoutParams(params);
    }

    private static void setLayoutSizeAndGravity(View view, int width, int height, int gravity) {
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view.getLayoutParams();
        params.width = width;
        params.height = height;
        view.setLayoutParams(params);
    }


//    @Override
//    public boolean onCreateOptionsMenu(Menu menu) {
//        // Inflate the menu; this adds items to the action bar if it is present.
//        getMenuInflater().inflate(R.menu.menu_webcams, menu);
//        return true;
//    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Makes the UP caret go back to the previous fragment MakeCuteFragment
        switch (item.getItemId()) {
            case android.R.id.home:
                android.app.FragmentManager fm = getFragmentManager();
                fm.popBackStack();
                finish();

                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

Activity 视频.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#2198bb">

        <fragment
            class="org.azurespot.cutelinks.cutevideos.VideosActivity$VideoListFragment"
            android:id="@+id/list_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="15dp"
            android:background="@drawable/button_border"/>

        <LinearLayout
            android:id="@+id/video_box"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:layout_margin="15dp"
            android:orientation="vertical"
            android:background="@drawable/button_border">

            <ImageButton
                android:id="@+id/close_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:src="@android:drawable/btn_dialog"
                android:onClick="onClickClose"/>

            <fragment
                class="org.azurespot.cutelinks.cutevideos.VideosActivity$VideoFragment"
                android:id="@+id/video_fragment_container"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

        </LinearLayout>
    </RelativeLayout>
</merge>

最佳答案

问题在于 onInitializationSuccess() 中的标志。方法。 YouTube 样本附带的标志是 FULLSCREEN_FLAG_CUSTOM_LAYOUT ,根据 YouTube API docs它实际上禁用了全屏 View ,以便您可以手动编写 View 。由于此标志在 YouTube 的示例中有效,我不知道我必须手动更改它。所以我只需要更改标志,我选择了FULLSCREEN_FLAG_ALWAYS_FULLSCREEN_IN_LANDSCAPE ,现在从视频框(如上所示)进入全屏模式,它进入全屏模式并继续播放视频。好吧,实际上它被编码为暂停,当你改变方向时,但你可以按下播放,它就可以工作了。

关于android - YouTube API 在全屏模式下变为空白 - Android,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28871366/

相关文章:

android - AOSP - 构建自定义图像并在 SDK 上使用 Android 模拟器运行它们

Android 显示来自 URL 的图片

android - 通过 youtube 数据 v3 的可恢复上传上传视频时需要 Api key

php - youtube-dl 获取直接下载网址

video - Google API用于从youtube视频中提取标签

youtube - 尝试使用Reporting API提取Youtube内容所有者报告时出现403响应

java - 从 Android 项目创建 jar

Android:将照片保存到照片库

ios - 在 iOS 上以 30fps 播放 200fps 视频

iphone - 当用户旋转到横向时全屏播放视频,然后在视频停止时以编程方式旋转回来