【问题标题】:How to play Youtube Video in a Fragment in ViewPager, Android如何在 Android 的 ViewPager 中的片段中播放 Youtube 视频
【发布时间】:2017-06-08 05:52:43
【问题描述】:

现在我正在尝试使用 YouTubePlayerSupportFragment 在 ViewPager 的片段中播放 Youtube 视频。 我使用 SmartFragmentStatePagerAdapter 作为 viewpager 适配器。 但是我收到了这个错误:

W/YouTubeAndroidPlayerAPI:YouTube 视频播放因播放器顶部出现未经授权的覆盖而停止。 YouTubePlayerView 不包含在其祖先 android.support.v4.view.ViewPager{41a53898 VFED.... ......I. 0,84-480,730 #7f0c00b8 app:id/viewPager}。祖先的边缘与 YouTubePlayerView 的边缘之间的距离为:左:480,上:0,右:-480,下:376(这些都应该是正数)。

我该如何解决这个问题。 问候

这是 FragmentPageAdapter 代码

public class VideoPagerAdapter extends SmartFragmentStatePagerAdapter 

{
    private UserInfo usrInfo;

public VideoPagerAdapter(FragmentManager fragmentManager, UserInfo userInfo){
    super(fragmentManager);
    usrInfo = userInfo;
}

@Override
public Fragment getItem(int position) {
    VideoDetailFragment videoDetailFragment = new VideoDetailFragment();
    videoDetailFragment.video = usrInfo.videoList.get(position);
    return videoDetailFragment;
}

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

}

我已经在 VideoDetailFragment 中实现了代码。

private YouTubePlayer mYoutubePlayer;
private YouTubePlayerSupportFragment mYoutubeFragment;

private void initYoutubeVideo(){
    mYoutubeFragment = YouTubePlayerSupportFragment.newInstance();
    FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
    transaction.replace(R.id.youtube_layout, mYoutubeFragment).commit();

    mYoutubeFragment.initialize(DEVELOPER_KEY, this);
}

@Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean b) {
    mYoutubePlayer = youTubePlayer;
    if (!b){
        youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.DEFAULT);
        youTubePlayer.loadVideo(VIDEO_ID);
    }
}



@Override
public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
    Log.d(TAG, "*** Youtube Player error : " + youTubeInitializationResult.toString());
    String errorMessage = String.format(getString(R.string.error_youtube_player), youTubeInitializationResult.toString());

    Utils.showAlert(mActivity, errorMessage);
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if (!isVisibleToUser && mYoutubePlayer != null) {
        mYoutubePlayer.release();
    }
    if (isVisibleToUser && mYoutubeFragment != null) {
        mYoutubeFragment.initialize(DEVELOPER_KEY, this);
    }
}

我已经在真机上测试过了

06-08 19:02:47.012 2562-2562/com.videofeed.tickit W/YouTubeAndroidPlayerAPI: Cannot load modern controls UI. Upgrade to the latest version of the Android YouTube API.
06-08 19:02:47.082 2562-2562/com.videofeed.tickit D/dalvikvm: DexOpt: couldn't find field Landroid/view/accessibility/CaptioningManager$CaptionStyle;.windowColor
06-08 19:02:47.082 2562-2562/com.videofeed.tickit W/dalvikvm: VFY: unable to resolve instance field 10579
06-08 19:02:47.082 2562-2562/com.videofeed.tickit D/dalvikvm: VFY: replacing opcode 0x52 at 0x0019
06-08 19:02:47.082 2562-2562/com.videofeed.tickit W/YouTubeAndroidPlayerAPI: Forcefully created overlay:vtd@41fd4d28 helper:Lazy@41fd5898 view:null status: ...... {...}
06-08 19:02:47.372 2562-2562/com.videofeed.tickit W/YouTubeAndroidPlayerAPI: Cannot load modern controls UI. Upgrade to the latest version of the Android YouTube API.
06-08 19:02:47.442 2562-2562/com.videofeed.tickit W/YouTubeAndroidPlayerAPI: Forcefully created overlay:vtd@42c9fe20 helper:Lazy@42c9fe98 view:null status: ...... {...}
06-08 19:02:47.462 2562-2562/com.videofeed.tickit I/Choreographer: Skipped 40 frames!  The application may be doing too much work on its main thread.
06-08 19:02:47.602 2562-2562/com.videofeed.tickit W/YouTubeAndroidPlayerAPI: Cannot load modern controls UI. Upgrade to the latest version of the Android YouTube API.
06-08 19:02:47.692 2562-2562/com.videofeed.tickit W/YouTubeAndroidPlayerAPI: Forcefully created overlay:vtd@42d8f2a8 helper:Lazy@42d8f320 view:null status: ...... {...}
06-08 19:02:51.912 2562-2604/com.videofeed.tickit D/dalvikvm: GC_FOR_ALLOC freed 15971K, 69% free 7899K/25052K, paused 35ms, total 37ms
06-08 19:02:58.202 2562-2562/com.videofeed.tickit W/YouTubeAndroidPlayerAPI: YouTube video playback stopped due to unauthorized overlay on top of player. The YouTubePlayerView is not contained inside its ancestor android.support.v4.view.ViewPager{42c4a610 VFED.... ......ID 0,84-480,730 #7f0c00b8 app:id/viewPager}. The distances between the ancestor's edges and that of the YouTubePlayerView is: left: -480, top: 0, right: 480, bottom: 376 (these should all be positive).
06-08 19:02:58.222 2562-2562/com.videofeed.tickit W/YouTubeAndroidPlayerAPI: YouTube video playback stopped due to unauthorized overlay on top of player. The YouTubePlayerView is not contained inside its ancestor android.support.v4.view.ViewPager{42c4a610 VFED.... ......ID 0,84-480,730 #7f0c00b8 app:id/viewPager}. The distances between the ancestor's edges and that of the YouTubePlayerView is: left: 480, top: 0, right: -480, bottom: 376 (these should all be positive).

这是登录 Android 工作室。 我附上了截图。 This is the screenshot

【问题讨论】:

  • 请清楚地描述您收到的错误并发布您编写的任何代码。另外指定此错误是在模拟器中发生还是在设备和 Android 版本上发生。
  • 我正在尝试使用 viewpager 播放多个视频。
  • 使用上面的代码,我可以显示Youtube视频。但是当我点击播放按钮时,视频没有播放

标签: android video youtube android-viewpager fragment


【解决方案1】:

这个答案可能为时已晚,但我找到了可能的解决方案。

我遇到了类似的问题,我也尝试在 viewpager 中播放多个视频。 如果 viewpager 中只有一个 youtube 片段,没关系,但是当有多个片段时,视频将无法播放,并显示该错误消息

YouTube 视频播放因播放器顶部出现未经授权的覆盖而停止。

第一个“未经授权的覆盖”不是来自我当前的片段,它位于 查看寻呼机的可见页面。它来自查看寻呼机创建 "next" 到当前片段的页面。

查看寻呼机在滑入可见窗口之前创建页面,因此 youtube 片段是在可见之前创建的,如果您初始化该片段,则 youtube 播放器会检测到奇怪的覆盖错误并停止视频和 youtube 播放器停止,甚至停止在可见页面中正常显示的视频。

在你的情况下,你可以看到错误信息

左:480,上:0,右:-480,下:376

负数是一个窗口宽,所以它的概率与我得到的问题相同。

所以我的解决方案

1.不要在 onCreate() 初始化 youtube,不要在该片段对 viewpager 可见之前进行初始化。

在我的例子中,我使用适配器和片段之间的接口,并在 viewpager 的父页面中,将 OnPageChangeListener 添加到 viewpager,youtube 片段仅在 viewpager 的页面更改为该 youtube 片段后初始化。

页面更改 > 通知适配器 > 界面 > youtubefragment > 开始初始化

第一步后,即使viewpager中有2个或更多youtube片段,第一个视频也应该正常播放,但是当我滑动到第二页时,视频不会播放并显示相同的错误,所以转到第二步

2。当 youtube 片段滑动到视图寻呼机的不可见部分时释放 youtube 播放器

第二个视频没有播放的原因是一样的,第一页有一个 youtubeplayer,它在可见范围之外,它收到一条错误消息,它停止了所有 youtubeplayer,原因我不知道为什么。

当页面更改时,我使用相同的界面。适配器会通过该接口通知正在滑开的youtube片段,释放youtubeplayer,接口实现就是这样,哪个mPlayer就是youtubeplayer通过initialize方法返回的。

      mInitializeListener = new InitializeListener() {
        @Override
        public void startVideo() {
            initialize();
        }

        @Override
        public void stopVideo() {
                mPlayer.release();
        }
    };

还有一些问题我无法回答, 比如为什么一个寻呼机中的 youtubeplayer 会影响其他人..?

但是当我对适配器和片段进行更改时, youtube视频可以正常播放,希望对你有帮助

以下是我在应用中使用的代码

    MediaFragmentViewPager adapter =
        new MediaFragmentViewPager(getChildFragmentManager(), getActivity(), true);
List<MediaData> mediaDataList = new ArrayList<>();

adapter.setmResources(mediaDataList);

imageViewPager.setAdapter(adapter);

ViewPager.OnPageChangeListener pagerchangeListener = new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }
    @Override
    public void onPageSelected(int position) {
        adapter.onPageChanged(position);
    }
    @Override
    public void onPageScrollStateChanged(int state) {

    }
};

imageViewPager.addOnPageChangeListener(pagerchangeListener);
pagerchangeListener.onPageSelected(0);

circlePageIndicator.setFillColor(getResources().getColor(R.color.colorAccent));
circlePageIndicator.setViewPager(imageViewPager);

适配器

public class MediaFragmentViewPager  extends FragmentStatePagerAdapter
        implements MediaYoutubeFragment.MediaFullScreenListener {

    protected List<MediaData> mResources;
    private String apiKey = "your apiKey";
    protected Map<Integer, MediaYoutubeFragment.InitializeListener> listenerMap = new HashMap<>();
    private Context context;

    private boolean isFullScreen;

    public MediaFragmentViewPager(FragmentManager fm, Context context, boolean isFullScreen) {
        super(fm);
        this.context = context;
        this.isFullScreen = isFullScreen;
    }

    public int currentPosition = -1;


    @Override
    public void startFullScreen() {
        if (!isFullScreen){
            MediaViewPagerActivity.startActivity(context, itemID, companyId, currentPosition);
        }
    }

    @Override
    public Fragment getItem(int position) {

        if(mResources.get(position).isImage == true){
            Log.i("tag3", "getItem image" + String.valueOf(position));
            MediaImageFragment imageFragment = new MediaImageFragment();
            imageFragment.setImageUrl(mResources.get(position).getImageResource().getImage1080p());
            return  imageFragment;
        } else {
            Log.i("tag3", "getItem video" + String.valueOf(position));
            MediaYoutubeFragment youTubePlayerSupportFragment =
                    MediaYoutubeFragment.newInstance(mResources.get(position).getYoutubeUrl(), this);
            listenerMap.put(position, youTubePlayerSupportFragment.getmInitializeListener());
            return youTubePlayerSupportFragment;
        }
    }

    public void onPageChanged(int position){
        // current page it not null, realse youtubeplayer.
        if(currentPosition != -1){
            if(listenerMap.get(currentPosition) != null){
                listenerMap.get(currentPosition).stopVideo();
            }
        }
        // update current position
        currentPosition = position;
        Log.i("tag3", "onPageSelected " + String.valueOf(position));

        //start loading video
        MediaYoutubeFragment.InitializeListener listener = listenerMap.get(position);
        if(listener != null){
            Log.i("tag3", "startVideo " + String.valueOf(position));
            listener.startVideo();
        } else {
            Log.i("tag3", "startVideo listener is null " + String.valueOf(position));
        }
    }

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

    public List<MediaData> getmResources() {
        return mResources;
    }

    public void setmResources(List<MediaData> mResources) {
        this.mResources = mResources;
    }


}

Youtube 片段

public class MediaYoutubeFragment extends YouTubePlayerSupportFragment
        implements YouTubePlayer.OnInitializedListener, YouTubePlayer.OnFullscreenListener {
    private static final String KEY_VIDEO_ID = "VIDEO_ID";

    public String apiKey = "yor apiKey";
    private String mVideoId;
    private YouTubePlayer mPlayer;
    boolean mIsFullScreen;
    private InitializeListener mInitializeListener;
    private MediaFullScreenListener fullScreenListener;

    public InitializeListener getmInitializeListener() {
        return mInitializeListener;
    }

    public void setmInitializeListener(InitializeListener mInitializeListener) {
        this.mInitializeListener = mInitializeListener;
    }

    public void setFullScreenListener(MediaFullScreenListener fullScreenListener) {
        this.fullScreenListener = fullScreenListener;
    }

    public interface MediaFullScreenListener{
        void startFullScreen();
    }

    public interface InitializeListener{
        void startVideo();
        void stopVideo();
    }

    public MediaYoutubeFragment(){
        super();
        mInitializeListener = new InitializeListener() {
            @Override
            public void startVideo() {
                initialize();
            }

            @Override
            public void stopVideo() {
                if (mPlayer != null){
                    mPlayer.release();
                }
            }
        };
    }

    private void initialize() {
        initialize(apiKey, this);
    }

    public static MediaYoutubeFragment newInstance(String videoId, MediaFullScreenListener listener) {
        MediaYoutubeFragment frag = new MediaYoutubeFragment();

        Bundle args = new Bundle();
        args.putString(KEY_VIDEO_ID, videoId);

        frag.setArguments(args);
        frag.setFullScreenListener(listener);
        return frag;
    }

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

        if (getArguments() != null) {
            mVideoId = getArguments().getString(KEY_VIDEO_ID);
        }
    }

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

    @Override
    public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean wasRestored) {
        mPlayer = youTubePlayer;

        mPlayer.setFullscreenControlFlags(FULLSCREEN_FLAG_CUSTOM_LAYOUT);
        mPlayer.setOnFullscreenListener(this);
        mPlayer.setFullscreen(false);
        mPlayer.setShowFullscreenButton(true);

        if (!wasRestored) {
            // load your video
            mPlayer.loadVideo(mVideoId);
        }
        else
        {
            mPlayer.play();
        }
    }

    @Override
    public void onInitializationFailure(YouTubePlayer.Provider provider,
                                        YouTubeInitializationResult youTubeInitializationResult) {

    }

    @Override
    public void onFullscreen(boolean fullscreen) {
        Log.i("tag3", "onFullscreen" + String.valueOf(fullscreen));
        mPlayer.setFullscreen(false);
        fullScreenListener.startFullScreen();
    }

}

我也用自己的activity处理全屏事件,这个viewpager内容不仅是youtube视频,还有图片,所以请忽略那些部分。

因为我在fragment中使用了view pager,所以我使用getChildFragmentManger,我也在Activity中使用了这个适配器,但是它产生了另一个问题,第一个视频不会在第一次viewpager isload时播放,因为监听器被调用在适配器中的 getItem() 之前,所以我做了一些更改,如果适配器是第一次加载(第一个 youtube 页面是第一次加载),监听器将在 getItem 返回片段后立即调用,其他的都是一样的。

【讨论】:

  • 你能分享一下 ViewPager 类和 Fragment 来播放 Youtube 视频吗?
  • 我在我的应用程序中添加了一些示例,第一个是viewpager的页面内容,在我的示例中,它是另一个片段,如果此适配器用于活动,则需要进行一些修改。
  • 在没有所有这些听众的情况下,也许还有另一种方法可以做到这一点。 setUserVisibleHint(boolean isVisibleToUser),viewpager中的fragment的这个方法可以告诉你这个页面在viewpager中是否可见,所以只需改变你的适配器类型,让适配器在每次页面改变时调用getItem(),然后在创建时在片段加载视频如果 isVisibleToUser 为真。
  • @AkshayTaru 这是我制作的一个简单演示应用程序的链接,github.com/theuruz0819/YoutubeViewpagerDemo,它没有使用我之前发布的方法,但它非常简单,也很有效。
  • @BalderLai 抱歉之前的评论我对不同的链接感到困惑。感谢您的链接。很有帮助
【解决方案2】:

所以基本上,问题是您的一个视频正在可见屏幕之外加载,导致覆盖错误。 对于 viewpager,已经加载的页面也会加载视频,但这些视频不在屏幕上导致错误。

解决方案(用于查看器): 一次加载一个视频,即要播放的视频。 通过在页面可见时加载视频来做到这一点。

【讨论】:

    【解决方案3】:

    这是不可能的。因为 YouTubePlayerView 需要它的活动来扩展 YoutubeBaseActivity。 YouTubePlayerView 提供的功能有限。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-21
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      • 1970-01-01
      • 2012-11-28
      • 2015-06-18
      • 2013-12-18
      相关资源
      最近更新 更多