在 Android 中制作完美的 Chromeless Youtube 播放器

Posted

技术标签:

【中文标题】在 Android 中制作完美的 Chromeless Youtube 播放器【英文标题】:Making a perfect Chromeless Youtube Player in Android 【发布时间】:2016-07-27 01:28:54 【问题描述】:

我在制作 CHROMELESS youtube 播放器视图时创建的内容就在这里。它正在完美地加载和播放,但即使视频完成,缓冲圈也会连续播放。任何人都可以在不需要时帮助我删除缓冲进度并制作完美的 youtube 播放器吗?

MainActivity.java

package com.rocky.youtubedemo;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

import com.google.android.youtube.player.YouTubeBaseActivity;
import com.google.android.youtube.player.YouTubeInitializationResult;
import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayerView;

public class MainActivity extends YouTubeBaseActivity implements YouTubePlayer.OnInitializedListener 

    private static final int RECOVERY_REQUEST = 1;
    private static String YOUTUBE_API_KEY = "";
    private YouTubePlayerView youTubeView;
    private Context context;
    private MyPlayerStateChangeListener playerStateChangeListener;
    private MyPlaybackEventListener playbackEventListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;

        playerStateChangeListener = new MyPlayerStateChangeListener();
        playbackEventListener = new MyPlaybackEventListener();

        YOUTUBE_API_KEY = "PLACE_YOUR_API_KEY_HERE";

        youTubeView = (YouTubePlayerView) findViewById(R.id.youtube_view);
        youTubeView.initialize(YOUTUBE_API_KEY, this);
    

    @Override
    public void onInitializationSuccess(YouTubePlayer.Provider provider, final YouTubePlayer player, boolean wasRestored) 

        player.setPlayerStateChangeListener(playerStateChangeListener);
        player.setPlaybackEventListener(playbackEventListener);

        if (!wasRestored) 
            player.loadVideo("fhWaJi1Hsfo"); // Plays https://www.youtube.com/watch?v=fhWaJi1Hsfo
            player.setPlayerStyle(YouTubePlayer.PlayerStyle.CHROMELESS);
        
    

    @Override
    public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult errorReason) 
        if (errorReason.isUserRecoverableError()) 
            Toast.makeText(context, errorReason.toString(), Toast.LENGTH_LONG).show();
//            errorReason.getErrorDialog(this, RECOVERY_REQUEST).show();
         else 
            String error = errorReason.toString();
            Toast.makeText(context, error, Toast.LENGTH_LONG).show();
        
    

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
        if (requestCode == RECOVERY_REQUEST) 
            // Retry initialization if user performed a recovery action
            getYouTubePlayerProvider().initialize(YOUTUBE_API_KEY, this);
        
    

    private void showMessage(String message) 
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    

    protected YouTubePlayer.Provider getYouTubePlayerProvider() 
        return youTubeView;
    

    private final class MyPlaybackEventListener implements YouTubePlayer.PlaybackEventListener 

        @Override
        public void onPlaying() 
            // Called when playback starts, either due to user action or call to play().
            showMessage("Playing");
        

        @Override
        public void onPaused() 
            // Called when playback is paused, either due to user action or call to pause().
            showMessage("Paused");
        

        @Override
        public void onStopped() 
            // Called when playback stops for a reason other than being paused.
            showMessage("Stopped");
        

        @Override
        public void onBuffering(boolean b) 
            showMessage("buffer");
        

        @Override
        public void onSeekTo(int i) 
            // Called when a jump in playback position occurs, either
            // due to user scrubbing or call to seekRelativeMillis() or seekToMillis()
        
    

    private final class MyPlayerStateChangeListener implements YouTubePlayer.PlayerStateChangeListener 

        @Override
        public void onLoading() 
            showMessage("loading");
        

        @Override
        public void onLoaded(String s) 
            showMessage("loaded");
        

        @Override
        public void onAdStarted() 
            // Called when playback of an advertisement starts.
        

        @Override
        public void onVideoStarted() 
            // Called when playback of the video starts.
            showMessage("started");
        

        @Override
        public void onVideoEnded() 
            // Called when the video reaches its end.
        

        @Override
        public void onError(YouTubePlayer.ErrorReason errorReason) 
            // Called when an error occurs.
        
    

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    tools:context=".MainActivity">

    <com.google.android.youtube.player.YouTubePlayerView
        android:id="@+id/youtube_view"
        android:layout_
        android:layout_/>

</RelativeLayout>

【问题讨论】:

【参考方案1】:

在您的onInitializationSuccess() 中,在播放器上设置PlaybackEventListener。覆盖 onBuffering() 并执行以下操作:

ViewGroup ytView = youTubeView; // if you are using YouTubePlayerView
ViewGroup ytView = (ViewGroup)ytPlayerFragment.getView(); // if you are using YouTubePlayerFragment
ProgressBar progressBar;
try 
    // As of 2016-02-16, the ProgressBar is at position 0 -> 3 -> 2 in the view tree of the Youtube Player Fragment/View
    ViewGroup child1 = (ViewGroup)ytView.getChildAt(0);
    ViewGroup child2 = (ViewGroup)child1.getChildAt(3);
    progressBar = (ProgressBar)child2.getChildAt(2);
 catch (Throwable t) 
    // As its position may change, we fallback to looking for it
    progressBar = findProgressBar(ytView);
    // I recommend reporting this problem so that you can update the code in the try branch: direct access is more efficient than searching for it


int visibility = isBuffering ? View.VISIBLE : View.INVISIBLE;
if (progressBar != null) 
    progressBar.setVisibility(visibility);
    // Note that you could store the ProgressBar instance somewhere from here, and use that later instead of accessing it again.

制作这样的方法:

private ProgressBar findProgressBar(View view) 
        if (view instanceof ProgressBar) 
            return (ProgressBar)view;
         else if (view instanceof ViewGroup) 
            ViewGroup viewGroup = (ViewGroup)view;
            for (int i = 0; i < viewGroup.getChildCount(); i++) 
                ProgressBar res = findProgressBar(viewGroup.getChildAt(i));
                if (res != null) return res;
            
        
        return null
    

通过这种方式,您可以在缓冲时启用进度,在不缓冲时禁用它。

【讨论】:

@ArthTilva 我尝试了同样的方法,但在播放视频时仍然显示进度条,这是我使用的 onBuffering() 方法的代码,与您给出的相同:pastebin.com/sfsJNtgr @RaghavSatyadev 如果你有那个演示,请帮助 Sophie,我现在没有那个。 @Sophie,这实际上是一个项目,但如果你能等几个小时,我会给你做一个演示。通过 raghavsatyadev@gmail.com 与我联系

以上是关于在 Android 中制作完美的 Chromeless Youtube 播放器的主要内容,如果未能解决你的问题,请参考以下文章

适用于 Android 的完美 OCR 扫描

如何在 Android 中将时钟应用小部件与系统时钟完美同步?

如何自己编译android系统并制作刷机包

当我制作签名的 APK 时,我的 Android 本地数据库不起作用

在 Swift 中将 ui Image 制作成完美的圆圈

如何制作完美伴奏、