在Android中使用YouTube API的最佳方式是什么? [英] What is the best way of using Youtube API in Android?

查看:32
本文介绍了在Android中使用YouTube API的最佳方式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的Android应用程序中实现YouTube API,但有一些限制。

  1. 播放/暂停按钮应可见。(默认样式和最小样式都支持此功能)

  2. 时间栏应可见且可操作。(在最小样式的情况下,时间栏仅可见,但点击它不会产生任何效果)

  3. 用户不应该能够直接共享视频或打开YouTube应用程序。(在本例中,默认为不是选项)

最小样式可以完美地工作,但时间栏不起作用。我曾考虑使用自定义Seekbar,但当视频处于全屏模式时它是不可见的。有什么建议吗?

推荐答案

YouTube API面临的两个主要问题是:

1.将YoutubePlayerStlye设置为最小样式时,无法访问搜索栏(时间栏)。

2.视频末尾会弹出相关视频

1的解决方案:

因此,我们必须构建一个自定义搜索栏来访问时间进度,并根据需要更新(拖动)搜索栏上的时间。但YoutubePlayer不允许在视频上方/顶部显示视图(窗口小部件),如果发生这种情况,您会暂停视频。 因此,解决方案是在youtubePlayer下面绘制一个自定义搜索栏。 我们可以通过以下布局实现这一点:

youtube_player_layout.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".features.video.YoutubePlayerActivity">

    <!-- youtube player view to play videos -->
    <com.google.android.youtube.player.YouTubePlayerView
        android:id="@+id/youtube_player_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@android:color/black"
        android:focusable="true" />

    <!-- Full layout of seekbar, you can also use a constraintLayout-->
    <LinearLayout 
        android:id="@+id/video_control_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="@android:color/black"
        android:gravity="center"
        android:orientation="horizontal">

        <!-- Seekbar to display video progress -->
        <SeekBar
            android:id="@+id/video_seekbar"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginBottom="10dp"
            android:layout_weight="6"
            android:max="100"
            android:progress="0" />

        <!-- Time display -->
        <TextView
            android:id="@+id/play_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:gravity="center"
            android:text="--:--"
            android:textColor="@android:color/white" />

        <!-- FullScreen button -->
        <ImageButton
            android:id="@+id/bt_fullscreen"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:src="@drawable/ic_fullscreen" />
    </LinearLayout>
</LinearLayout>

纵向视图:

景观:

此自定义搜索栏还包含一个全屏按钮(ImageButton),您可以在更改方向时从Kotlin/Java代码上的矢量资源句柄添加该按钮

2的解决方案: 我在网上找到的常见解决方案是在视频结束时将seakTime设置为零。

  @Override
    public void onVideoEnded() {
        if (null == mPlayer) return;
        mPlayer.seekToMillis(0);
        mPlayer.pause();
    }

但此解决方案不是最佳,因为即使您使用它,相关视频有时也会播放半秒,这看起来并不理想。

所以简单的解决方案是永远不要让视频结束,这样在结束时就不会显示相关的视频。要实现这一点,我们必须在视频结束前停止~1.2秒(我认为可以从视频中牺牲~1.2秒,但这取决于用法)。

 if (null == mPlayer) return;
    if (mPlayer.getCurrentTimeMillis() >= (mPlayer.getDurationMillis() - 1200L)) {
        mPlayer.seekToMillis(0);
        mPlayer.pause();
    }

我还发布了youtubePlayer的完整Java代码

YoutubePlayerActivity.java

import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.core.content.ContextCompat;
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;
import com.syncnicia.theguideapp.R;

public class YoutubePlayerActivity extends YouTubeBaseActivity {
    private static final String TAG = "YoutubePlayerActivity";
    private String videoID;
    private YouTubePlayerView youTubePlayerView;
    private TextView mPlayTimeTextView;
    private YouTubePlayer mPlayer;
    private Handler mHandler = null;
    private SeekBar mSeekBar;
    private ImageButton btFullScreen;
    private int seekTime = 0;

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

        //get the video id
        videoID = getIntent().getStringExtra("video_id");
        youTubePlayerView = findViewById(R.id.youtube_player_view);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        btFullScreen = findViewById(R.id.bt_fullscreen);

        btFullScreen.setOnClickListener(view -> {
            int orientation = this.getResources().getConfiguration().orientation;
            if (null != mPlayer) {
                if (mPlayer.isPlaying()) {
                    mPlayer.pause();
                }
                if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    
                } else {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    
                }
                mPlayer.play();
            }
        });
        mPlayTimeTextView = (TextView) findViewById(R.id.play_time);
        mSeekBar = (SeekBar) findViewById(R.id.video_seekbar);
        mSeekBar.setOnSeekBarChangeListener(mVideoSeekBarChangeListener);
        mHandler = new Handler();
        initializeYoutubePlayer();

    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mPlayer != null) {
            initializeYoutubePlayer();
        }
    }

    private void initializeYoutubePlayer() {
        youTubePlayerView.initialize(String.valueOf(getText(R.string.youtube_key)), new YouTubePlayer.OnInitializedListener() {

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

                if (null == youTubePlayer) return;
                mPlayer = youTubePlayer;

                displayCurrentTime();
                //if initialization success then load the video id to youtube player
                if (!wasRestored) {
                    if (videoID != null) {

                        youTubePlayer.loadVideo(videoID, seekTime);
                    }
                }
                //set the player style here: like CHROMELESS, MINIMAL, DEFAULT
                youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.MINIMAL);

                // Add listeners to YouTubePlayer instance
                youTubePlayer.setPlayerStateChangeListener(mPlayerStateChangeListener);
                youTubePlayer.setPlaybackEventListener(playbackEventListener);
            }

            private final YouTubePlayer.PlaybackEventListener playbackEventListener = new YouTubePlayer.PlaybackEventListener() {

                @Override
                public void onPlaying() {
                    mHandler.postDelayed(runnable, 100);
                    displayCurrentTime();
                }

                @Override
                public void onPaused() {
                    mHandler.removeCallbacks(runnable);
                }

                @Override
                public void onStopped() {
                    mHandler.removeCallbacks(runnable);
                }

                @Override
                public void onBuffering(boolean b) {
                }

                @Override
                public void onSeekTo(int i) {
                    mHandler.postDelayed(runnable, 100);
                }
            };

            @Override
            public void onInitializationFailure(YouTubePlayer.Provider arg0, YouTubeInitializationResult arg1) {
                //print or show error if initialization failed
                Log.e(TAG, "Youtube Player View initialization failed:" + arg1);
                if (arg1.toString().equals("SERVICE_VERSION_UPDATE_REQUIRED")) {
                    Toast.makeText(YoutubePlayerActivity.this, "Please Update your Youtube to latest version.", Toast.LENGTH_SHORT).show();
                }
            }

        });

    }

    YouTubePlayer.PlayerStateChangeListener mPlayerStateChangeListener = new YouTubePlayer.PlayerStateChangeListener() {
        @Override
        public void onLoading() {

        }

        @Override
        public void onLoaded(String s) {

        }

        @Override
        public void onAdStarted() {

        }

        @Override
        public void onVideoStarted() {
            displayCurrentTime();

        }

        @Override
        public void onVideoEnded() {
            if (null == mPlayer) return;
            mPlayer.seekToMillis(0);
            mPlayer.pause();
        }

        @Override
        public void onError(YouTubePlayer.ErrorReason errorReason) {

        }
    };
    SeekBar.OnSeekBarChangeListener mVideoSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            if (null == mPlayer) return;
            long lengthPlayed = (mPlayer.getDurationMillis() * seekBar.getProgress()) / 100;
            mPlayer.seekToMillis((int) lengthPlayed);
        }
    };

    private void displayCurrentTime() {
        //To stop video 1.2s before it ends
        if (null == mPlayer) return;
        if (mPlayer.getCurrentTimeMillis() >= (mPlayer.getDurationMillis() - 1200L)) {
            mPlayer.seekToMillis(0);
            mPlayer.pause();
        }
        String formattedTime = formatTime(mPlayer.getDurationMillis() - mPlayer.getCurrentTimeMillis());
        mPlayTimeTextView.setText(formattedTime);
        int playPercent = (int) (((float) mPlayer.getCurrentTimeMillis() / (float) mPlayer.getDurationMillis()) * 100);
        // update live progress
        mSeekBar.setProgress(playPercent);
    }

    private String formatTime(int millis) {
        int seconds = millis / 1000;
        int minutes = seconds / 60;
        int hours = minutes / 60;

        return (hours == 0 ? "" : hours + ":") + String.format("%02d:%02d", minutes % 60, seconds % 60);
    }


    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            displayCurrentTime();
            mHandler.postDelayed(this, 100);
        }
    };

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

    @Override
    protected void onPause() {
        super.onPause();
        if (mPlayer != null) {
            seekTime = mPlayer.getCurrentTimeMillis();
        }

    }

    @Override
    protected void onStop() {
        if (mPlayer != null) {
            mPlayer.release();
        }
        super.onStop();
    }

  // To switch fullScreen icon when orientation changes
 @Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {

        btFullScreen.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_fullscreen));

    } else if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){

        btFullScreen.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_fullscreen_exit));

    }
}
}

我认为直接复制粘贴并添加绘图对象就足以使其正常工作。

如果代码仍然令人困惑,请让我知道,我将向其添加更多注释。

我希望它对每个人都有效!!因为我😅花了一个多小时。

这篇关于在Android中使用YouTube API的最佳方式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆