Android集成Youtube播放

看了下網(wǎng)上關(guān)于集成Youtube視頻開發(fā)的文章不是很多捐顷,

所以今天把我開發(fā)中所遇到的問題和實(shí)現(xiàn)代碼分享給大家。

應(yīng)用運(yùn)行環(huán)境:AndroidTV端雨效、Android手機(jī)端


https://developers.google.com/youtube/iframe_api_reference(YouTube開發(fā)者專區(qū))![](https://img-blog.csdnimg.cn/20190718102141212.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0d5Ymox,size_16,color_FFFFFF,t_70)

這是開發(fā)者專區(qū)中的入口迅涮,上邊這句話的意思是,使用嵌入式播放器在您的應(yīng)用中播放視頻徽龟,并自定義播放體驗(yàn)叮姑。

![在這里插入圖片描述](https://img-blog.csdnimg.cn/20190718102517110.png)

點(diǎn)進(jìn)來可以看到他提供了Android、IOS据悔、和IFrame(html)三種Api,因?yàn)橹皇窃贏ndroid設(shè)備上運(yùn)行传透,所以只講Android和IFrame

這兩種,先說一下這AndroidAPI和IFrameApi的區(qū)別屠尊,

? 1旷祸、AndroidAPI

如果想播放YouTube視頻,Android設(shè)備上必須有YouTube的應(yīng)用讼昆,優(yōu)點(diǎn)是開發(fā)快、適配性比較好。

? 2浸赫、IFrameAPI

基于瀏覽器內(nèi)核闰围,有些設(shè)備使用會(huì)有問題,好處是不用YouTube應(yīng)用的支持既峡,可以直接播放羡榴,缺點(diǎn)是需要跨平臺(tái)開發(fā),步驟繁瑣运敢,適配性比較差.


![在這里插入圖片描述](https://img-blog.csdnimg.cn/2019071810454856.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0d5Ymox,size_16,color_FFFFFF,t_70)

基本上國外Android設(shè)備上都會(huì)自帶YouTube應(yīng)用校仑,但是我負(fù)責(zé)的項(xiàng)目在AndroidTV端運(yùn)行,


Android盒子更新比較慢传惠,YouTube對(duì)2012年以前的智能電視不再提供支持迄沫,所以項(xiàng)目開發(fā)中我選擇了IFrameAPI的方式。

所以就先講IFrameApi的方式卦方。

**IFrameAPI**

? Android端需要做的有兩件事


? 1羊瘩、Android通過webview調(diào)用html,在接口中傳入YouTube視頻的id盼砍、以及視頻的寬高 尘吗。


? 如何獲取視頻id?


? 訪問Youtube的網(wǎng)站浇坐,當(dāng)前播放視頻地址欄v后面的就是視頻id睬捶,如:


? https://www.youtube.com/watch?v=1xRjMEIzn48


? 2、通過Android的遙控器監(jiān)聽事件調(diào)用html中的方式控制視頻的播放近刘、暫停侧戴、快進(jìn)、快退功能跌宛。


? android代碼


**MainActivity**


? ```javascript

package com.example.administrator.intelchange;

import android.annotation.SuppressLint;

import android.app.Activity;

import android.os.Bundle;

import android.util.DisplayMetrics;

import android.util.Log;

import android.view.KeyEvent;

import android.webkit.WebSettings;

import android.webkit.WebView;

import android.webkit.WebViewClient;

public class MainActivity extends Activity {

? ? private static final String TAG = "MainActivity";

? ? WebView wv_common_webview;

? ? @Override

? ? protected void onCreate(Bundle savedInstanceState) {

? ? ? ? super.onCreate(savedInstanceState);

? ? ? ? setContentView(R.layout.activity_main);

? ? ? ? DisplayMetrics outMetrics = new DisplayMetrics();

? ? ? ? getWindowManager().getDefaultDisplay().getMetrics(outMetrics);

? ? ? ? int widthPixels = outMetrics.widthPixels;

? ? ? ? int heightPixels = outMetrics.heightPixels;

? ? ? ? wv_common_webview = (WebView) findViewById(R.id.webview);

? ? ? ? String id="_vw0dH3ic4A";

? ? ? ? //調(diào)用本地html

? ? ? ? //wv_common_webview.loadUrl("file:///android_asset/111.html");

? ? ? //調(diào)用服務(wù)端html

? ? ? ? wv_common_webview.loadUrl("http://ott.bangtv.tv/yt/play.html?v="+id+"&w="+widthPixels*0.75+"&h="+heightPixels*0.75);

? ? ? ? //加上下面這段代碼可以使網(wǎng)頁中的鏈接不以瀏覽器的方式打開

? ? ? ? wv_common_webview.setWebViewClient(new WebViewClient());

? ? ? ? //得到webview設(shè)置

? ? ? ? WebSettings webSettings = wv_common_webview.getSettings();

? ? ? ? //允許使用javascript

? ? ? ? webSettings.setJavaScriptEnabled(true);

? ? ? ? webSettings.setUseWideViewPort(true);

? ? ? ? webSettings.setLoadWithOverviewMode(true);

? ? ? ? wv_common_webview.getSettings().setBuiltInZoomControls(true);

? ? ? ? wv_common_webview.getSettings().setUseWideViewPort(true);

? ? ? ? wv_common_webview.getSettings().setLoadWithOverviewMode(true);

? ? ? ? wv_common_webview.getSettings().setTextZoom(100);

? ? ? ? wv_common_webview.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);

? ? ? ? // 如果頁面中鏈接酗宋,如果希望點(diǎn)擊鏈接繼續(xù)在當(dāng)前browser中響應(yīng),

? ? ? ? ? ? ? ? // 而不是新開Android的系統(tǒng)browser中響應(yīng)該鏈接疆拘,必須覆蓋webview的WebViewClient對(duì)象

? ? ? ? ? ? ? ? wv_common_webview.setWebViewClient(new WebViewClient() {

? ? ? ? ? ? ? ? ? ? public boolean shouldOverrideUrlLoading(WebView view, String url) {

? ? ? ? ? ? ? ? ? ? ? ? //? 重寫此方法表明點(diǎn)擊網(wǎng)頁里面的鏈接還是在當(dāng)前的webview里跳轉(zhuǎn)蜕猫,不跳到瀏覽器那邊

? ? ? ? ? ? ? ? ? ? ? ? view.loadUrl(url);

? ? ? ? ? ? ? ? ? ? ? ? return true;

? ? ? ? ? ? ? ? ? ? }

? ? ? ? });

? ? }


? ? //調(diào)用html中的方法,傳入按鍵狀態(tài)

? ? @SuppressLint("SetJavaScriptEnabled")

? ? public void testJS(int keycode,String key) {

? ? ? ? if (keycode == KeyEvent.KEYCODE_DPAD_LEFT) {

? ? ? ? ? ? wv_common_webview.loadUrl("javascript:operation( "+KeyEvent.KEYCODE_DPAD_LEFT+","+key+")");

? ? ? ? }else if(keycode == KeyEvent.KEYCODE_DPAD_RIGHT){

? ? ? ? ? ? wv_common_webview.loadUrl("javascript:operation( "+KeyEvent.KEYCODE_DPAD_RIGHT+","+key+")");

? ? ? ? }

? ? ? ? else if(keycode == KeyEvent.KEYCODE_DPAD_UP){

? ? ? ? ? ? wv_common_webview.loadUrl("javascript:operation( "+KeyEvent.KEYCODE_DPAD_UP+","+key+")");

? ? ? ? }else if(keycode == KeyEvent.KEYCODE_DPAD_DOWN){

? ? ? ? ? ? wv_common_webview.loadUrl("javascript:operation( "+KeyEvent.KEYCODE_DPAD_DOWN+","+key+")");

? ? ? ? }

? ? ? ? else if(keycode == KeyEvent.KEYCODE_DPAD_CENTER){

? ? ? ? ? ? wv_common_webview.loadUrl("javascript:operation( "+KeyEvent.KEYCODE_DPAD_CENTER+","+key+")");

? ? ? ? }

? ? }

//

? ? /**

? ? * 監(jiān)聽遙控器按鍵事件

? ? */

? ? @Override

? ? public boolean dispatchKeyEvent(KeyEvent event) {

? ? ? ? // TODO Auto-generated method stub

? ? ? ? //? ? ? ? if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT

//? ? ? ? ? ? ? ? | event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP

//? ? ? ? ? ? ? ? | event.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT

//? ? ? ? ? ? ? ? | event.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN‘’

//? ? ? ? ? ? ? ? ? | event.getKeyCode()? == KeyEvent.KEYCODE_DPAD_CENTER

//? ? ? ? ? ? ? ? ? && event.getAction() == KeyEvent.ACTION_DOWN) {

//? ? ? ? ? ? testJS(event.getKeyCode(),"0");

//

//? ? ? ? }

//? ? ? ? if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT

//? ? ? ? ? ? ? ? | event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP

//? ? ? ? ? ? ? ? |event.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT

//? ? ? ? ? ? ? ? | event.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN

//? ? ? ? ? ? ? ? &&event.getAction() == KeyEvent.ACTION_UP) {

//? ? ? ? ? ? testJS(event.getKeyCode(),"1");

//

//? ? ? ? }

? ? ? ? //按鍵按下時(shí)傳參數(shù)給html哎迄,”0“為按下回右,”1“為按鍵抬起

? ? ? if(event.getKeyCode()? == KeyEvent.KEYCODE_DPAD_LEFT&&event.getAction() == KeyEvent.ACTION_DOWN ){

? ? ? ? ? ? testJS(event.getKeyCode(),"0");

//? ? ? ? ? ? Toast.makeText(this,"點(diǎn)擊了左鍵",0.LENGTH_SHORT).show();

? ? ? ? }

? ? ? ? if(event.getKeyCode()? == KeyEvent.KEYCODE_DPAD_LEFT&& event.getAction() == KeyEvent.ACTION_UP){

? ? ? ? ? ? testJS(event.getKeyCode(),"1");

//? ? ? ? ? ? Toast.makeText(this,"點(diǎn)擊了左鍵",Toast.LENGTH_SHORT).show();

? ? ? ? }

? ? ? ? if(event.getKeyCode()? == KeyEvent.KEYCODE_DPAD_RIGHT&&event.getAction() == KeyEvent.ACTION_DOWN){

//? ? ? ? ? ? Toast.makeText(this,"點(diǎn)擊了右鍵",Toast.LENGTH_SHORT).show();

? ? ? ? ? ? testJS(event.getKeyCode(),"0");

? ? ? ? }

? ? ? ? if(event.getKeyCode()? == KeyEvent.KEYCODE_DPAD_RIGHT&&event.getAction() == KeyEvent.ACTION_UP){

//? ? ? ? ? ? Toast.makeText(this,"點(diǎn)擊了右鍵",Toast.LENGTH_SHORT).show();

? ? ? ? ? ? testJS(event.getKeyCode(),"1");

? ? ? ? }

? ? ? ? if(event.getKeyCode()? == KeyEvent.KEYCODE_DPAD_UP&&event.getAction() == KeyEvent.ACTION_DOWN){

//? ? ? ? ? ? Toast.makeText(this,"點(diǎn)擊了上鍵",Toast.LENGTH_SHORT).show();

? ? ? ? ? ? testJS(event.getKeyCode(),"0");

? ? ? ? }

? ? ? ? if(event.getKeyCode()? == KeyEvent.KEYCODE_DPAD_UP&&event.getAction() == KeyEvent.ACTION_UP){

//? ? ? ? ? ? Toast.makeText(this,"點(diǎn)擊了上鍵",Toast.LENGTH_SHORT).show();

? ? ? ? ? ? testJS(event.getKeyCode(),"1");

? ? ? ? }

? ? ? ? if(event.getKeyCode()? == KeyEvent.KEYCODE_DPAD_DOWN&&event.getAction() == KeyEvent.ACTION_DOWN){

//? ? ? ? ? ? Toast.makeText(this,"點(diǎn)擊了下鍵",Toast.LENGTH_SHORT).show();

? ? ? ? ? ? testJS(event.getKeyCode(),"0");

? ? ? ? }

? ? ? ? if(event.getKeyCode()? == KeyEvent.KEYCODE_DPAD_DOWN&&event.getAction() == KeyEvent.ACTION_UP){

//? ? ? ? ? ? Toast.makeText(this,"點(diǎn)擊了下鍵",Toast.LENGTH_SHORT).show();

? ? ? ? ? ? testJS(event.getKeyCode(),"1");

? ? ? ? }

? ? ? ? if(event.getKeyCode()? == KeyEvent.KEYCODE_DPAD_CENTER&& event.getAction() != KeyEvent.ACTION_UP){

? ? ? ? ? ? testJS(event.getKeyCode(),"0");

//? ? ? ? ? ? Toast.makeText(this,"點(diǎn)擊了確定鍵",Toast.LENGTH_SHORT).show();

? ? ? ? }

? ? ? ? ? if (event.getKeyCode() == KeyEvent.KEYCODE_BACK){

? ? ? ? ? ? this.finish();

? ? ? ? ? }

? ? ? ? return true;

? ? }

}

```

```javascript

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

? ? android:layout_width="match_parent"

? ? android:layout_height="match_parent"

? ? android:orientation="vertical">

? ? <WebView

? ? ? ? android:id="@+id/webview"

? ? ? ? android:layout_width="match_parent"

? ? ? ? android:layout_height="match_parent"></WebView>

</LinearLayout>

```

**html代碼**

urlhelper.js

```javascript

/**

* 獲取url參數(shù)

* @param {string} name

*/

function getQueryString(name){

? ? var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");

? ? var r = window.location.search.substr(1).match(reg);

? ? if(r!=null)return? unescape(r[2]); return null;

}

```

player.html

```javascript

<!DOCTYPE html>

<html lang="en">

<head>

? ? <meta charset="UTF-8">

? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">

? ? <meta http-equiv="X-UA-Compatible" content="ie=edge">

? ? <title>play</title>

? ? <style>*,body,html,div,p,img{border:0;margin:0;padding:0;}</style>

</head>

<body>

? ? ? ? <div id="show"></div>

? ? ? ? <div id="showup"></div>

? ? ? ? <div id="player"></div>

? ? ? ? <script src="./urlhelper.js"></script>

? ? ? ? <script>

? ? ? ? ? //獲取視頻ID

? ? ? ? ? var vid = getQueryString("v");

? ? ? ? ? var w = parseInt(getQueryString("w"));

? ? ? ? ? var h =? parseInt(getQueryString("h"));

? ? ? ? ? // document.getElementById('show').innerHTML=w+ '? '+ h;

? ? ? ? ? //初始化播放器

? ? ? ? ? var tag = document.createElement('script');

? ? ? ? ? tag.src = "https://www.youtube.com/iframe_api";

? ? ? ? ? var firstScriptTag = document.getElementsByTagName('script')[0];

? ? ? ? ? firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);


? ? ? ? ? var player;

? ? ? ? ? var duration = 0;

? ? ? ? ? function onYouTubeIframeAPIReady() {

? ? ? ? ? ? player = new YT.Player('player', {

? ? ? ? ? ? ? height: 360,

? ? ? ? ? ? ? width: 640,

? ? ? ? ? ? ? videoId: vid,

? ? ? ? ? ? ? events: {

? ? ? ? ? ? ? ? 'onReady': onPlayerReady,

? ? ? ? ? ? ? ? 'onStateChange': onPlayerStateChange

? ? ? ? ? ? ? }

? ? ? ? ? ? });

? ? ? ? ? }


? ? ? ? ? function onPlayerReady(event) {

? ? ? ? ? ? duration = player.getDuration();

? ? ? ? ? ? // var fr = player.getIframe();

? ? ? ? ? ? event.target.playVideo();

? ? ? ? ? }


? ? ? ? ? //全局視頻信息

? ? ? ? ? var state; //視頻播放狀態(tài)

? ? ? ? ? var keyCode=-1; //對(duì)應(yīng)按鍵

? ? ? ? ? var keyEv=-1; //事件

? ? ? ? ? var optime = 0; //時(shí)間點(diǎn)

? ? ? ? ? //按鍵

? ? ? ? ? var keyCodeLeft = 21;

? ? ? ? ? var keyCodeRight = 22;

? ? ? ? ? var keyCodeOk = 23;

? ? ? ? ? var keyCodeUp = 24;

? ? ? ? ? var keyCodeDown = 25;

? ? ? ? ? //事件

? ? ? ? ? var keyEvDown = 0;

? ? ? ? ? var keyEvUp = 1;


? ? ? ? ? function onPlayerStateChange(event) {

? ? ? ? ? ? state = event.data;

? ? ? ? ? }

? ? ? ? ? //操作 keycode按鍵 ev事件 0-按下 1-抬起

? ? ? ? ? function operation(keycode, ev){

? ? ? ? ? ? switch(keycode){

? ? ? ? ? ? ? case keyCodeLeft:

? ? ? ? ? ? ? ? left(ev);

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? case keyCodeRight:

? ? ? ? ? ? ? ? right(ev);

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? case keyCodeOk:

? ? ? ? ? ? ? ? ok(ev);

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? case keyCodeUp:

? ? ? ? ? ? ? ? up(ev);

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? case keyCodeDown:

? ? ? ? ? ? ? ? down(ev);

? ? ? ? ? ? ? break;

? ? ? ? ? ? }

? ? ? ? ? }

? ? ? ? ? //ok鍵

? ? ? ? ? function ok(ev){

? ? ? ? ? ? state == YT.PlayerState.PLAYING?player.pauseVideo():player.playVideo();

? ? ? ? ? }

? ? ? ? ? //右鍵

? ? ? ? ? function right(ev){

? ? ? ? ? ? if(ev){

? ? ? ? ? ? }else{

? ? ? ? ? ? ? //計(jì)算時(shí)間,重新加載

? ? ? ? ? ? ? var ctime = player.getCurrentTime();

? ? ? ? ? ? ? ctime += 5;

? ? ? ? ? ? ? ctime = ctime<duration?ctime:duration;

? ? ? ? ? ? ? player.seekTo(ctime, true);

? ? ? ? ? ? }

? ? ? ? ? ? // if(ev){

? ? ? ? ? ? //? //定位

? ? ? ? ? ? //? document.getElementById('showup').innerHTML = optime+ '? 11111';

? ? ? ? ? ? //? optime = optime<duration?optime:duration;

? ? ? ? ? ? //? player.seekTo(optime, true);

? ? ? ? ? ? //? optime = 0;

? ? ? ? ? ? //? // keyEv = -1;

? ? ? ? ? ? // }else{

? ? ? ? ? ? //? if(optime == 0){

? ? ? ? ? ? //? ? optime = player.getCurrentTime();

? ? ? ? ? ? //? }

? ? ? ? ? ? //? optime += 5;

? ? ? ? ? ? // }

? ? ? ? ? }

? ? ? ? ? //左鍵

? ? ? ? ? function left(ev){

? ? ? ? ? ? if(ev){

? ? ? ? ? ? }else{

? ? ? ? ? ? ? //計(jì)算時(shí)間漱挚,重新加載

? ? ? ? ? ? ? var ctime = player.getCurrentTime();

? ? ? ? ? ? ? ctime -= 5;

? ? ? ? ? ? ? ctime = ctime>0?ctime:0;

? ? ? ? ? ? ? player.seekTo(ctime, true);

? ? ? ? ? ? }

? ? ? ? ? ? // if(ev){

? ? ? ? ? ? //? //定位

? ? ? ? ? ? //? optime = optime>0?optime:0;

? ? ? ? ? ? //? player.seekTo(optime, true);

? ? ? ? ? ? //? optime = 0;

? ? ? ? ? ? // }else{

? ? ? ? ? ? //? if(optime == 0){

? ? ? ? ? ? //? ? optime = player.getCurrentTime();

? ? ? ? ? ? //? }

? ? ? ? ? ? //? optime -= 5;

? ? ? ? ? ? // }

? ? ? ? ? }

? ? ? ? ? //向上

? ? ? ? ? function up(){}

? ? ? ? ? //向下

? ? ? ? ? function down(){}


? ? ? ? </script>

</body>

</html>

```

**AndroidAPI**

要運(yùn)行AndroidAPi的Youtube視頻翔烁,需要:

1、Android Studio SDK 1.2或更高版本旨涝。

2蹬屹、適用 于API 23或更高版本的Android SDK包,包括最新版本的Google Repository,Android支持庫和Google Play服務(wù)慨默。

3贩耐、在您的測試設(shè)備上訪問互聯(lián)網(wǎng)。

4厦取、Google帳戶潮太。

開發(fā)前,需要在google注冊(cè)您的應(yīng)用虾攻,包括你的數(shù)字簽名和證書铡买。

1、進(jìn)入google[開發(fā)控制臺(tái)](https://console.developers.google.com/)霎箍,

2奇钞、創(chuàng)建一個(gè)新項(xiàng)目。我的是ALXYoutubePlayer朋沮。

3蛇券、在該項(xiàng)目中創(chuàng)建后出現(xiàn)的頁面上,展開API和驗(yàn)證左側(cè)邊欄樊拓,單擊的API纠亚。在API的列表,點(diǎn)擊YouTube數(shù)據(jù)API并啟用

YouTube數(shù)據(jù)API V3后面的頁面上筋夏。

在左側(cè)邊欄蒂胞,選擇證書。對(duì)于資格證書条篷,API支持的OAuth 2.0骗随,使用服務(wù)帳戶的API密鑰和。我們將使用API密鑰選項(xiàng)赴叹。

選擇API密鑰從添加憑據(jù)下拉菜單鸿染。會(huì)顯示一個(gè)彈出讓你指定密鑰類型。選擇Android的關(guān)鍵乞巧。接下來選擇添加包名和指紋涨椒,并添

加Android應(yīng)用程序的包名(我的是vc.zz.qduxsh.alxyoutubeplayer),然后在終端中運(yùn)行以下命令來獲取SHA-1證書指紋绽媒。

keytool -list -v -keystore ~/.android/debug.keystore‘’

輸入的android系統(tǒng)提示時(shí)作為密碼蚕冬。上位于調(diào)試密鑰庫上面的命令打印資料?/ .android / debug.keystore您的計(jì)算機(jī)上。這是通

過Eclipse中或Android工作室當(dāng)你第一次建立了一個(gè)Android應(yīng)用程序自動(dòng)生成的是辕。在終端方面囤热,你會(huì)看到MD5和SHA-1證書指

紋。復(fù)制SHA-1指紋获三,并將其粘貼在谷歌開發(fā)者控制臺(tái)旁蔼,然后點(diǎn)擊創(chuàng)建按鈕锨苏。API密鑰將會(huì)產(chǎn)生。稍后我們將使用此牌芋。

在Andropid項(xiàng)目中蚓炬,創(chuàng)建一個(gè)名為類Config.java并粘貼以下松逊。

```javascript

package vc.zz.qduxsh.alxyoutubeplayer;

/**

* Created by gzj? on 7/15/19.

*/

public final class Config {

? ? private Config() {

? ? }

? ? public static final String YOUTUBE_API_KEY = "YOUR API KEY";

}

```

然后一個(gè)下載的最新版本的Android版YouTube播放器API的躺屁。下載完成后放到libs目錄下,右鍵--》add as library

地址:https://developers.google.com/youtube/android/player/downloads/

![在這里插入圖片描述](https://img-blog.csdnimg.cn/20190718153344955.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0d5Ymox,size_16,color_FFFFFF,t_70)

在build.gradle中加入

compile files('libs/YouTubeAndroidPlayerApi.jar')

activity_youtube.xml

```javascript

<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=".MainActivity">

? ? <com.google.android.youtube.player.YouTubePlayerView

? ? ? ? android:id="@+id/youtube_view"

? ? ? ? android:layout_width="match_parent"

? ? ? ? android:layout_height="wrap_content"/>

</RelativeLayout>

```

MainActivity.java

```javascript

package vc.zz.qduxsh.alxyoutubeplayer;

import android.content.Intent;

import android.content.pm.ActivityInfo;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.webkit.WebChromeClient;

import android.widget.Button;

import android.widget.FrameLayout;

import android.widget.LinearLayout;

import java.util.ArrayList;

import java.util.List;

import vc.zz.qduxsh.alxyoutubeplayer.player.YoutubePlayerView;

public class MainActivity extends AppCompatActivity {

? ? private List<YoutubePlayerView> playerViewList;//一個(gè)頁面可以播放多個(gè)視頻经宏,將所有的播放控件收集到這里進(jìn)行維護(hù)犀暑,主要是控制離開頁面時(shí)候的暫停

? ? //定位到y(tǒng)outube的某個(gè)視頻有三種方式

? ? public static final String VideoUrl_normal = "https://www.youtube.com/watch?v=PFKutKoYX7E";//這種是最普通的寫在地址欄中的視頻地址

? ? private View mVideoProgressView;

? ? private View mCustomView;//全屏顯示的View

? ? private View mVideoFullScreenBack;

? ? private LinearLayout ll_player_container;

? ? private int mOriginalSystemUiVisibility;

? ? private int mOriginalOrientation;

? ? private WebChromeClient.CustomViewCallback mCustomViewCallback;

? ? Button btnWebview;

? ? Button btnvideo;

? ? @Override

? ? protected void onCreate(Bundle savedInstanceState) {

? ? ? ? super.onCreate(savedInstanceState);

? ? ? ? setContentView(R.layout.activity_main);

? ? ? ? btnWebview = (Button) findViewById(R.id.btn_webview);

? ? ? ? btnvideo = (Button) findViewById(R.id.btn_videoview);

? ? ? ? btnWebview.setOnClickListener(new View.OnClickListener() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onClick(View view) {

? ? ? ? ? ? ? ? String videoUrl = VideoUrl_normal;

? ? ? ? ? ? ? ? String videoID = YoutubePlayerView.parseIDfromVideoUrl(videoUrl);

? ? ? ? ? ? ? ? Log.i("Alex","視頻的ID是=="+videoID);

? ? ? ? ? ? ? ? View youtubeView = LayoutInflater.from(MainActivity.this).inflate(R.layout.layout_youtube_player, null);

? ? ? ? ? ? ? ? YoutubePlayerView youtubePlayerView = (YoutubePlayerView) youtubeView.findViewById(R.id.youtubePlayerView);

? ? ? ? ? ? ? ? youtubePlayerView.setAutoPlayerHeight(MainActivity.this);

? ? ? ? ? ? ? ? youtubePlayerView.initialize(videoID, new YoutubePlayerCallBack(youtubePlayerView), mWebChromeClient);

? ? ? ? ? ? ? ? mVideoFullScreenBack = findViewById(R.id.detail_video_back);

? ? ? ? ? ? ? ? if(playerViewList == null){

? ? ? ? ? ? ? ? ? ? playerViewList = new ArrayList<>();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ll_player_container = (LinearLayout) findViewById(R.id.ll_player_container);

? ? ? ? ? ? ? ? ll_player_container.addView(youtubeView);

? ? ? ? ? ? ? ? playerViewList.add(youtubePlayerView);

? ? ? ? ? ? ? ? youtubePlayerView.seekToMillis(80000);

? ? ? ? ? ? }

? ? ? ? });

? ? ? ? btnvideo.setOnClickListener(new View.OnClickListener() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onClick(View view) {

? ? ? ? ? ? ? ? Intent intent = new Intent(MainActivity.this,YoutubeActivity.class);

? ? ? ? ? ? ? ? startActivity(intent);

? ? ? ? ? ? }

? ? ? ? });

? ? }

? ? @Override

? ? protected void onStart() {

? ? ? ? super.onStart();

? ? }

? ? private class YoutubePlayerCallBack implements YoutubePlayerView.YouTubeListener {

? ? ? ? private YoutubePlayerView mYoutubeView;

? ? ? ? YoutubePlayerCallBack(YoutubePlayerView view){

? ? ? ? ? ? this.mYoutubeView = view;

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onReady() {

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onStateChange(YoutubePlayerView.STATE state) {

? ? ? ? ? ? if(state == YoutubePlayerView.STATE.PLAYING && mYoutubeView!=null){

? ? ? ? ? ? ? ? if(playerViewList!=null){

? ? ? ? ? ? ? ? ? ? for(YoutubePlayerView v : playerViewList){

? ? ? ? ? ? ? ? ? ? ? ? if (v != null && v != mYoutubeView && (v.getPlayerState() == YoutubePlayerView.STATE.PLAYING ||

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? v.getPlayerState() == YoutubePlayerView.STATE.PAUSED)) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? v.stop();

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onPlaybackQualityChange(String arg) {

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onPlaybackRateChange(String arg) {

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onError(String arg) {

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onApiChange(String arg) {

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onCurrentSecond(double second) {

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onDuration(double duration) {

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void logs(String log) {

? ? ? ? }

? ? }

? ? /**

? ? * 用于全屏顯示的代碼

? ? */

? ? private WebChromeClient mWebChromeClient = new WebChromeClient(){

? ? ? ? @Override

? ? ? ? public View getVideoLoadingProgressView() {

? ? ? ? ? ? if (mVideoProgressView == null) {

? ? ? ? ? ? ? ? LayoutInflater inflater = LayoutInflater.from(MainActivity.this);

? ? ? ? ? ? ? ? mVideoProgressView = inflater.inflate(R.layout.video_layout_loading, null);

? ? ? ? ? ? }

? ? ? ? ? ? return mVideoProgressView;

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {

? ? ? ? ? ? // if a view already exists then immediately terminate the new one

? ? ? ? ? ? if (mCustomView != null) {

? ? ? ? ? ? ? ? onHideCustomView();

? ? ? ? ? ? ? ? return;

? ? ? ? ? ? }

? ? ? ? ? ? // 1. Stash the current state

? ? ? ? ? ? mCustomView = view;

? ? ? ? ? ? mOriginalSystemUiVisibility = MainActivity.this.getWindow().getDecorView().getSystemUiVisibility();

? ? ? ? ? ? mOriginalOrientation = MainActivity.this.getRequestedOrientation();

? ? ? ? ? ? Log.i("Alex","原來的屏幕方向是"+mOriginalOrientation);

? ? ? ? ? ? // 2. Stash the custom view callback

? ? ? ? ? ? mCustomViewCallback = callback;

? ? ? ? ? ? // 3. Add the custom view to the view hierarchy

? ? ? ? ? ? FrameLayout decor = (FrameLayout) MainActivity.this.getWindow().getDecorView();

? ? ? ? ? ? decor.addView(mCustomView, new FrameLayout.LayoutParams(

? ? ? ? ? ? ? ? ? ? ViewGroup.LayoutParams.MATCH_PARENT,

? ? ? ? ? ? ? ? ? ? ViewGroup.LayoutParams.MATCH_PARENT));

? ? ? ? ? ? if(mVideoFullScreenBack!=null){

? ? ? ? ? ? ? ? mVideoFullScreenBack.setVisibility(View.VISIBLE);

? ? ? ? ? ? }

? ? ? ? ? ? // 4. Change the state of the window

? ? ? ? ? ? MainActivity.this.getWindow().getDecorView().setSystemUiVisibility(

? ? ? ? ? ? ? ? ? ? View.SYSTEM_UI_FLAG_LAYOUT_STABLE |

? ? ? ? ? ? ? ? ? ? ? ? ? ? View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |

? ? ? ? ? ? ? ? ? ? ? ? ? ? View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |

? ? ? ? ? ? ? ? ? ? ? ? ? ? View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |

? ? ? ? ? ? ? ? ? ? ? ? ? ? View.SYSTEM_UI_FLAG_FULLSCREEN |

? ? ? ? ? ? ? ? ? ? ? ? ? ? View.SYSTEM_UI_FLAG_IMMERSIVE);

? ? ? ? ? ? MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onHideCustomView() {

? ? ? ? ? ? // 1. Remove the custom view

? ? ? ? ? ? FrameLayout decor = (FrameLayout) MainActivity.this.getWindow().getDecorView();

? ? ? ? ? ? decor.removeView(mCustomView);

? ? ? ? ? ? mCustomView = null;

? ? ? ? ? ? if(mVideoFullScreenBack!=null){

? ? ? ? ? ? ? ? mVideoFullScreenBack.setVisibility(View.GONE);

? ? ? ? ? ? }

? ? ? ? ? ? // 2. Restore the state to it's original form

? ? ? ? ? ? MainActivity.this.getWindow().getDecorView().setSystemUiVisibility(mOriginalSystemUiVisibility);

? ? ? ? ? ? MainActivity.this.setRequestedOrientation(mOriginalOrientation);

? ? ? ? ? ? // 3. Call the custom view callback

? ? ? ? ? ? if(mCustomViewCallback!=null){

? ? ? ? ? ? ? ? mCustomViewCallback.onCustomViewHidden();

? ? ? ? ? ? ? ? mCustomViewCallback = null;

? ? ? ? ? ? }

? ? ? ? }

? ? };

? ? @Override

? ? public void onPause() {

? ? ? ? //視頻播放器當(dāng)頁面停止的時(shí)候所有的視頻播放全部暫停

? ? ? ? if(playerViewList!=null){

? ? ? ? ? ? for(YoutubePlayerView v : playerViewList){

? ? ? ? ? ? ? ? if(v.getPlayerState() == YoutubePlayerView.STATE.PLAYING ){

? ? ? ? ? ? ? ? ? ? v.pause();

? ? ? ? ? ? ? ? }else if(v.getPlayerState() == YoutubePlayerView.STATE.BUFFERING){

? ? ? ? ? ? ? ? ? ? v.stop();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? super.onPause();

? ? }

? ? @Override

? ? public void onDestroy() {

? ? ? ? super.onDestroy();

? ? ? ? if (playerViewList != null) {

? ? ? ? ? ? for (YoutubePlayerView v : playerViewList) {

? ? ? ? ? ? ? ? if (v != null) v.onDestroy();

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? public boolean closeFullScreen(){

? ? ? ? if(mCustomView!=null && mCustomViewCallback!=null){

? ? ? ? ? ? mWebChromeClient.onHideCustomView();

? ? ? ? ? ? return true;

? ? ? ? }

? ? ? ? return false;

? ? }

? ? @Override

? ? public void onBackPressed() {

? ? ? ? Log.i("Alex", "進(jìn)入onBackPressed方法");

? ? ? ? closeFullScreen();

? ? ? ? super.onBackPressed();

? ? }

}

```

在上面的代碼中,我們創(chuàng)建一個(gè)類烁兰,是的子類YouTubeBaseActivity耐亏。這需要利用YouTubePlayerView。我們使用

YouTubePlayer.OnInitializedListener偵聽初始化成功或失敗沪斟。該接口有兩個(gè)方法广辰,一個(gè)名為onInitializationFailure()和

onInitializationSuccess() 。

例如主之,如果YouTube應(yīng)用是不是安裝在用戶的設(shè)備上或已過期择吊,對(duì)話將有一個(gè)提示,經(jīng)確認(rèn)后槽奕,將打開谷歌Play商店安裝或相應(yīng)

地更新它的用戶几睛。如果YouTube應(yīng)用在設(shè)備上禁用,則該提示將打開系統(tǒng)設(shè)置為用戶啟用它粤攒。

當(dāng)用戶從錯(cuò)誤恢復(fù)對(duì)話返回所森,的onActivityResult()被調(diào)用檢查,查看是否用戶執(zhí)行的恢復(fù)操作夯接。如果是這樣焕济,我們重試初始

化。

運(yùn)行該應(yīng)用程序盔几,你應(yīng)該能夠發(fā)揮在代碼中指定的視頻晴弃。請(qǐng)注意,您將需要您的設(shè)備上的YouTube應(yīng)用问欠。該API客戶端庫與分布

的YouTube應(yīng)用為Android平臺(tái)的部分服務(wù)進(jìn)行交互肝匆。用戶需要運(yùn)行移動(dòng)版YouTube應(yīng)用程式(或更高)的版本4.2.16使用API。

通常情況下顺献,運(yùn)行Android 2.2(升級(jí)Froyo)或更高版本有谷歌Play商店應(yīng)用的設(shè)備應(yīng)該能夠運(yùn)行向上的最新版本的YouTube應(yīng)

用旗国。

這意味著什么,除非你已經(jīng)安裝了谷歌Apps的虛擬設(shè)備注整,您將無法測試在模擬器上的代碼能曾。默認(rèn)的Android模擬器不支持在設(shè)備

上安裝谷歌企業(yè)應(yīng)用套件度硝,但如果你使用的模擬器像Genymotion,就可以使用了寿冕。即使在我的模擬器安裝了谷歌企業(yè)應(yīng)用套

件蕊程,我仍然無法播放視頻。視頻縮略圖加載沒關(guān)系的看法驼唱,但在攻播放按鈕藻茂,加載指示燈會(huì)出現(xiàn),但再裝載會(huì)失敗玫恳,“連接到服

務(wù)器丟失”的消息辨赐。您可能需要準(zhǔn)備一個(gè)真正的設(shè)備。

結(jié)論

Android版的YouTube庫提供了一個(gè)很好的API京办,你可以自定義此API掀序,我們僅僅觸及了它的邊緣。要了解更多關(guān)于庫惭婿,一定要通

過文檔閱讀并隨附庫下載示例應(yīng)用程序不恭。

你可以在這里下載完整的項(xiàng)目。記得放置在您的密鑰Config.java文件财饥。

IFrameAPI:https://github.com/gongzaijing/intelchange.git

AndroidAPI:https://github.com/gongzaijing/Android-VideoTube-master.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末换吧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子佑力,更是在濱河造成了極大的恐慌式散,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件打颤,死亡現(xiàn)場離奇詭異暴拄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)编饺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門乖篷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人透且,你說我怎么就攤上這事撕蔼。” “怎么了秽誊?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵鲸沮,是天一觀的道長。 經(jīng)常有香客問我锅论,道長讼溺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任最易,我火速辦了婚禮怒坯,結(jié)果婚禮上炫狱,老公的妹妹穿的比我還像新娘。我一直安慰自己剔猿,他們只是感情好视译,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著归敬,像睡著了一般酷含。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上弄慰,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天第美,我揣著相機(jī)與錄音蝶锋,去河邊找鬼陆爽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛扳缕,可吹牛的內(nèi)容都是我干的慌闭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼躯舔,長吁一口氣:“原來是場噩夢啊……” “哼驴剔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起粥庄,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤丧失,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后惜互,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體布讹,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年训堆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了描验。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坑鱼,死狀恐怖膘流,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鲁沥,我是刑警寧澤呼股,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站画恰,受9級(jí)特大地震影響彭谁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜阐枣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一马靠、第九天 我趴在偏房一處隱蔽的房頂上張望奄抽。 院中可真熱鬧,春花似錦甩鳄、人聲如沸逞度。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽档泽。三九已至,卻和暖如春揖赴,著一層夾襖步出監(jiān)牢的瞬間馆匿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國打工燥滑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留渐北,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓铭拧,卻偏偏與公主長得像赃蛛,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子搀菩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容