show code block

顯示具有 Youtube android教學 標籤的文章。 顯示所有文章
顯示具有 Youtube android教學 標籤的文章。 顯示所有文章

2017年3月22日 星期三

third-party元件(Youtube API) ─ Youtube API 簡易使用(二) 控制元件、移除SeekBar、自訂按鈕

前言:


今天來講一下YoutubePlay的控制方式。

想要自己控制PLAY、PAUSE按鈕,又或者想要自訂SeekBar。

這時候就必須要一個乾淨純粹的View ─

除了一個Time Bar 和點擊畫面上的Play、Pause外,是不是很乾淨的,很純粹。


其實也可以把所有控制按鈕都拿掉,所有的控制元件都自己設定,就像MixerBox一樣。

MixerBox就是自己控制所有元件的最好例子,單看畫面還不覺得這出自Youtube!

先讓我們看看Youtube官方文件。
https://developers.google.com/youtube/android/player/reference/com/google/android/youtube/player/YouTubePlayer.PlayerStyle

在裡面有一個mothed是專門控制Style的



YouTubePlayer.PlayerStyle

java.lang.Object
   ↳java.lang.Enum<E extends java.lang.Enum<E>>
   ↳com.google.android.youtube.player.YouTubePlayer.PlayerStyle

Overview

The different styles available for the player.

Summary

Enum values
YouTubePlayer.PlayerStyle.CHROMELESSA style that shows no interactive player controls.
YouTubePlayer.PlayerStyle.DEFAULTThe default style, showing all interactive controls.
YouTubePlayer.PlayerStyle.MINIMALA minimal style, showing only a time bar and play/pause controls.
Public methods
static YouTubePlayer.PlayerStylevalueOf(String name)
final static PlayerStyle[]values()


public static final YouTubePlayer.PlayerStyle CHROMELESS

A style that shows no interactive player controls.
這個風格完全移除和畫面的互動,所有東西都必須自訂。
ex:就如同MixerBox一樣,自訂所有畫面

public static final YouTubePlayer.PlayerStyle DEFAULT

The default style, showing all interactive controls.
正常版風格,保留了一切你在Youtube上面看的到的控制元件,包含點它們右下角的Youtube可直接跳轉到它們app觀看的原件。

public static final YouTubePlayer.PlayerStyle MINIMAL

A minimal style, showing only a time bar and play/pause controls.
最小簡化的風格,只保留TimeBar和螢幕上的播放和暫停控制元件。
ex:就如同我前言那張圖一樣,可以明顯看出pause暫停按鈕和下面的TimeBar




程式碼:

先前的程式碼請先參考:http://nikeru8.blogspot.tw/2017/03/androidyoutube-api-youtube-api.html

我們加在讀取成功後的方法內。

onInitializationSuccess


當然要讀取成功後控制這一切才有意義XDD
 @Override
    public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean wasRestored) {
        Toast.makeText(this, "onInitializationSuccess!", Toast.LENGTH_SHORT).show();
        if (youTubePlayer == null) {
            Log.d("CheckPoint", "CheckPoint youtubePlayer == null");
            return;
        }
        // Start buffering
        if (!wasRestored) {
            Log.d("CheckPoint", "CheckPoint !wasRestored");
            youTubePlayer.cueVideo(VIDEO_ID);
        }
//        youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.CHROMELESS);//移除全部控制按鈕
//        youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.DEFAULT);//原版
        youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.MINIMAL);//移除下面的控制按鈕
    }


這邊比較值得注意的是,使用PlayerStyle.CHROMELESS時,因為移除了全部的控制按鈕,你甚至不能按下Play按鈕,要請你自己添加控制元件囉。
不然就會像一張圖片一樣卡在那。




控制元件Code:

如上所述,先在onInitializationSuccess內上程式碼。

youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.CHROMELESS);



再來改變main_activity.xml的布局

main_activity.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_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.chat.a015865.youtube.MainActivity">

    <com.google.android.youtube.player.YouTubePlayerView
        android:id="@+id/player_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:id="@+id/video_control"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/player_view"
        android:background="#444"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:visibility="visible"
        android:weightSum="10"
        tools:layout_editor_absoluteX="84dp"
        tools:layout_editor_absoluteY="374dp">

        <ImageButton
            android:id="@+id/play_video"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:layout_weight="1"
            android:background="@null"
            android:src="@drawable/ic_play" />

        <ImageButton
            android:id="@+id/pause_video"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:layout_weight="1"
            android:background="@null"
            android:src="@drawable/ic_pause" />

        <SeekBar
            android:id="@+id/video_seekbar"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:layout_weight="6"
            android:max="100"
            android:progress="0" />

        <TextView
            android:id="@+id/play_time"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:layout_weight="2"
            android:text="--:--"
            android:textColor="@android:color/white" />
    </LinearLayout>
</RelativeLayout>





MainActivity.java

public class MainActivity extends YouTubeBaseActivity implements YouTubePlayer.OnInitializedListener, View.OnClickListener {


    public static final String API_KEY = "AIzaSyAPThx6WbAxjnX2En0qtf9OhD80tUcp380";

    //https://www.youtube.com/watch?v=
    public static final String VIDEO_ID = "qZIWO9TqvIA";

    private YouTubePlayer mYoutubePlayer;
    private View mPlayButtonLayout;
    private TextView mPlayTimeTextView;

    private Handler mHandler = null;
    private SeekBar mSeekBar;


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

        final YouTubePlayerView mYoutubePlayerView = (YouTubePlayerView) findViewById(R.id.player_view);
        mYoutubePlayerView.initialize(API_KEY, this);
        initView();
        mPlayButtonLayout = findViewById(R.id.video_control);
        findViewById(R.id.play_video).setOnClickListener(this);
        findViewById(R.id.pause_video).setOnClickListener(this);

        mPlayTimeTextView = (TextView) findViewById(R.id.play_time);
        mSeekBar = (SeekBar) findViewById(R.id.video_seekbar);
        mSeekBar.setOnSeekBarChangeListener(mVideoSeekBarChangeListener);
        mHandler = new Handler();
    }

    private void initView() {

    }

    @Override
    public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean wasRestored) {
        Toast.makeText(this, "onInitializationSuccess!", Toast.LENGTH_SHORT).show();
        mYoutubePlayer = youTubePlayer;
        if (youTubePlayer == null) {
            Log.d("CheckPoint", "CheckPoint youtubePlayer == null");
            return;
        }
        // Start buffering
        if (!wasRestored) {
            Log.d("CheckPoint", "CheckPoint !wasRestored");
            youTubePlayer.cueVideo(VIDEO_ID);
        }
        youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.CHROMELESS);
//        youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.DEFAULT);//原版
//        youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.MINIMAL);//移除下面的控制按鈕

        youTubePlayer.setPlayerStateChangeListener(mPlayerStateChangeListener);//影片在run時的狀態
        youTubePlayer.setPlaybackEventListener(mPlaybacckEventListener);
    }

    YouTubePlayer.PlaybackEventListener mPlaybacckEventListener = 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) {
            Log.d("CheckPoint", "CheckPoint i = " + i);
            mHandler.postDelayed(runnable, 100);
        }
    };
    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() {

        }

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

        }
    };

    @Override
    public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
        Toast.makeText(this, "Failed to initialize.", Toast.LENGTH_LONG).show();
    }

    SeekBar.OnSeekBarChangeListener mVideoSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(final SeekBar seekBar, final int progress, boolean fromUser) {
            long lengthPlayed = (mYoutubePlayer.getDurationMillis() * progress) / 100;
            mYoutubePlayer.seekToMillis((int) lengthPlayed);
            seekBar.setProgress(progress);
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    };

    private void displayCurrentTime() {
        if (mYoutubePlayer == null) return;
        String formattedTime = formatTime(mYoutubePlayer.getDurationMillis() - mYoutubePlayer.getCurrentTimeMillis());
        mPlayTimeTextView.setText(formattedTime);
    }

    private String formatTime(int millis) {
        int seconds = millis / 1000;
        int minutes = seconds / 60;
        int hours = minutes / 60;
        return (hours == 0 ? "- - : " : formatS(hours) + ":") + formatS(minutes % 60) + ":" + formatS(seconds % 60);
    }

    private String formatS(int x) {
        String s = "" + x;
        if (s.length() == 1)
            s = "0" + s;
        return s;
    }


    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            displayCurrentTime();

            mHandler.postDelayed(this, 100);
        }
    };

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.play_video:
                if (null != mYoutubePlayer && !mYoutubePlayer.isPlaying())
                    mYoutubePlayer.play();
                break;
            case R.id.pause_video:
                if (null != mYoutubePlayer && mYoutubePlayer.isPlaying())
                    mYoutubePlayer.pause();
                break;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        mYoutubePlayer.release();
        mYoutubePlayer = null;
        mHandler.removeCallbacks(runnable);
    }
}


edit(2017/03/27)
上面無法和seekbar連動,當你移動seekbar影片會跟著移動,但影片再撥放的時候seekbar無法連動。
我試過RunOnUiThread設定seekbar會發生錯誤。
我修好的話會在上傳新code







third-party元件(Youtube API)─ Youtube API 簡易使用、匯入專案lib

前言:


此篇我們來實作內崁Youtube影音的功能。

為什麼不用WebView直接內崁?

因為WebView內崁的方式很醜阿。
會變下圖這樣


我不想要下面這些東西,想要單純的只有影片,其他東西我可以自由地運用。

當然還有一些比較特別的使用方式。

像是MixerBox,就是拿這個在營利。







1、首先先去這網頁下載他們的api
https://developers.google.com/youtube/android/player/downloads/


下載下來會是一個.zip檔案那要怎麼import到android studio內呢?



2、先解壓縮吧。
然後打開資料夾找到libs檔案我們需要的東西在裡面。

你會找到YouTubeAndroidPlayerApi.jar這的檔案。

然後找到你的專案在最最上層開一個libs資料夾,以後好方便管理你import的東西。
3、回到Android Studio內,右上方File >> Project Structure...


按下去之後,找到你自己專案,案ok


我們就可以使用Youtube API囉




程式碼:

先給網路權限吧!

AndroidManifest

<uses-permission android:name="android.permission.INTERNET" />


1、增加YouTubePlayerView到xml內

在main_activity.java內設定View

main_activity.java

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.chat.a015865.youtube.MainActivity">

    <com.google.android.youtube.player.YouTubePlayerView
        android:id="@+id/player_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</android.support.constraint.ConstraintLayout>



2、初始化YouTubePlayerView(Initialize)

MainActivity.java內,在要使用YouTubePlayerViewactivity都一定要改extends繼承變成YouTubeBaseActivity,並且imp;ements YouTubePlayer.OnInitializedListener

implements YouTubePlayer.OnInitializedListener 之後,請implements methods

拿到onInitializationSuccess(初始化成功)和onInitializationFailure(初始化失敗)

在onCreate內初始化YouTubePlayerView

mYoutubePlayerView.initialize(API_KEY, this);

API_KEY目前用不到,可以先隨便給值。

Youtube網址的格式 https://www.youtube.com/watch?v= xxxxxx 後面的的xxxxxx可以改變你想看的頻道。試著去YOUTUBE上找你喜愛的頻道,COPY後面的xxxxxx回到MainActivity.java改變VEDIO_ID,就可以改變你要看的東西。


MainActivity.java

public class MainActivity extends YouTubeBaseActivity implements YouTubePlayer.OnInitializedListener {


    public static final String API_KEY = "htyhry";

    //https://www.youtube.com/watch?v=
    public static final String VIDEO_ID = "OsUr8N7t4zc";
    private YouTubePlayerView mYoutubePlayerView;

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

        mYoutubePlayerView = (YouTubePlayerView) findViewById(R.id.player_view);
        mYoutubePlayerView.initialize(API_KEY, this);
    }

    @Override
    public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean wasRestored) {
        Toast.makeText(this, "onInitializationSuccess!", Toast.LENGTH_SHORT).show();
        if (youTubePlayer == null) {
            Log.d("CheckPoint", "CheckPoint youtubePlayer == null");
            return;
        }
        
        if (!wasRestored) {
            Log.d("CheckPoint", "CheckPoint !wasRestored");
            youTubePlayer.cueVideo(VIDEO_ID);
        }
    }

    @Override
    public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
        Toast.makeText(this, "Failed to initialize.", Toast.LENGTH_LONG).show();

    }
}


這時候你就可以開始跑你的專案了,五月天的頑固就出現拉!


3、控制 YouTubePlayer 事件

其中還有一些控制YouTubePlayer的方法,像是可以再按暫停的同時,加入你要的廣告....之類的。
MainAcitivity.java內 >> onInitializationSuccess這裡面加入這個方法,可以控制Loading、onLoaded、onAdStarted....等等。

 youTubePlayer.setPlayerStateChangeListener(new YouTubePlayer.PlayerStateChangeListener() {
            @Override
            public void onLoading() {
                Log.d("CheckPoint", "CheckPoint onLoading");
            }

            @Override
            public void onLoaded(String s) {
                Log.d("CheckPoint", "CheckPoint onLoaded");
            }

            @Override
            public void onAdStarted() {
                Log.d("CheckPoint", "CheckPoint onAdStarted");
            }

            @Override
            public void onVideoStarted() {
                Log.d("CheckPoint", "CheckPoint onVideoStarted");
            }

            @Override
            public void onVideoEnded() {
                Log.d("CheckPoint", "CheckPoint onVideoEnded");
            }

            @Override
            public void onError(YouTubePlayer.ErrorReason errorReason) {
                Log.d("CheckPoint", "CheckPoint onError = " + errorReason);
            }
        });





文獻:


Demo:











協程(coroutine) - 協程為什麼要學它?

 Coroutine 協程 再強調一次 協程就是由kotlin官方所提供的線程api //Thread Thread { }.start() //Executor val execu...