看了下网上关于集成Yoube视频开发的文章不是很多,

所以今天把我开发中所遇到的问题和实现代码分享给大家。

应用运行环境:AndroidTV端、Android手机端


这是开发者专区中的入口,上边这句话的意思是,使用嵌入式播放器在您的应用中播放视频,并自定义播放体验。

点进来可以看到他提供了Android、IOS、和IFrame(html)三种Api,因为只是在Android设备上运行,所以只讲Android和IFrame

这两种,先说一下这AndroidAPI和IFrameApi的区别,

1、AndroidAPI

如果想播放Yoube视频,Android设备上必须有Yoube的应用,优点是开发快、适配性比较好。

2、IFrameAPI

基于浏览器内核,有些设备使用会有问题,好处是不用Yoube应用的支持,可以直接播放,缺点是需要跨平台开发,步骤繁琐,适配性比较差.


基本上国外Android设备上都会自带Yoube应用,但是我负责的项目在AndroidTV端运行,

Android盒子更新比较慢,Yoube对2012年以前的智能电视不再提供支持,所以项目开发中我选择了IFrameAPI的方式。

所以就先讲IFrameApi的方式。

IFrameAPI

Android端需要做的有两件事

1、Android通过webview调用html,在接口中传入Yoube视频的id、以及视频的宽高 。

如何获取视频id?

访问Yoube的网站,当前播放视频地址栏v后面的就是视频id,如:

2、通过Android的遥控器监听事件调用html中的方式控制视频的播放、暂停、快进、快退功能。

android代码

MainActivity

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;@Overrideprotected 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";//调用本地html//wv_common_webview.loadUrl("file:///android_asset/111.html");//调用服务端htmlwv_common_webview.loadUrl("http://ott.bangtv.tv/yt/play.html?v="+id+"&w="+widthPixels*0.75+"&h="+heightPixels*0.75);//加上下面这段代码可以使网页中的链接不以浏览器的方式打开wv_common_webview.setWebViewClient(new WebViewClient());//得到webview设置WebSettings webSettings = wv_common_webview.getSettings();//允许使用javascriptwebSettings.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);// 如果页面中链接,如果希望点击链接继续在当前browser中响应,// 而不是新开Android的系统browser中响应该链接,必须覆盖webview的WebViewClient对象wv_common_webview.setWebViewClient(new WebViewClient() {public boolean shouldOverrideUrlLoading(WebView view, String url) {//  重写此方法表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边view.loadUrl(url);return true;}});}//调用html中的方法,传入按键状态@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+")");}}///*** 监听遥控器按键事件*/@Overridepublic 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");
//
//        }//按键按下时传参数给html,”0“为按下,”1“为按键抬起if(event.getKeyCode()   == KeyEvent.KEYCODE_DPAD_LEFT&&event.getAction() == KeyEvent.ACTION_DOWN ){testJS(event.getKeyCode(),"0");
//            Toast.makeText(this,"点击了左键",0.LENGTH_SHORT).show();}if(event.getKeyCode()   == KeyEvent.KEYCODE_DPAD_LEFT&& event.getAction() == KeyEvent.ACTION_UP){testJS(event.getKeyCode(),"1");
//            Toast.makeText(this,"点击了左键",Toast.LENGTH_SHORT).show();}if(event.getKeyCode()   == KeyEvent.KEYCODE_DPAD_RIGHT&&event.getAction() == KeyEvent.ACTION_DOWN){
//            Toast.makeText(this,"点击了右键",Toast.LENGTH_SHORT).show();testJS(event.getKeyCode(),"0");}if(event.getKeyCode()   == KeyEvent.KEYCODE_DPAD_RIGHT&&event.getAction() == KeyEvent.ACTION_UP){
//            Toast.makeText(this,"点击了右键",Toast.LENGTH_SHORT).show();testJS(event.getKeyCode(),"1");}if(event.getKeyCode()   == KeyEvent.KEYCODE_DPAD_UP&&event.getAction() == KeyEvent.ACTION_DOWN){
//            Toast.makeText(this,"点击了上键",Toast.LENGTH_SHORT).show();testJS(event.getKeyCode(),"0");}if(event.getKeyCode()   == KeyEvent.KEYCODE_DPAD_UP&&event.getAction() == KeyEvent.ACTION_UP){
//            Toast.makeText(this,"点击了上键",Toast.LENGTH_SHORT).show();testJS(event.getKeyCode(),"1");}if(event.getKeyCode()   == KeyEvent.KEYCODE_DPAD_DOWN&&event.getAction() == KeyEvent.ACTION_DOWN){
//            Toast.makeText(this,"点击了下键",Toast.LENGTH_SHORT).show();testJS(event.getKeyCode(),"0");}if(event.getKeyCode()   == KeyEvent.KEYCODE_DPAD_DOWN&&event.getAction() == KeyEvent.ACTION_UP){
//            Toast.makeText(this,"点击了下键",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,"点击了确定键",Toast.LENGTH_SHORT).show();}if (event.getKeyCode() == KeyEvent.KEYCODE_BACK){this.finish();}return true;}}
<?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"><WebViewandroid:id="@+id/webview"android:layout_width="match_parent"android:layout_height="match_parent"></WebView></LinearLayout>

html代码

urlhelper.js


/*** 获取url参数* @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

<!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>//获取视频IDvar 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; //视频播放状态var keyCode=-1; //对应按键var keyEv=-1; //事件var optime = 0; //时间点//按键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{//计算时间,重新加载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{//计算时间,重新加载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

要运行AndroidAPi的Yoube视频,需要:

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

2、适用 于API 23或更高版本的Android SDK包,包括最新版本的Google Repository,Android支持库和Google Play服务。

3、在您的测试设备上访问互联网。

4、Google帐户。

开发前,需要在google注册您的应用,包括你的数字签名和证书。

1、进入google开发控制台

2、创建一个新项目。我的是ALXYoutubePlayer。

3、在该项目中创建后出现的页面上,展开API和验证左侧边栏,单击的API。在API的列表,点击Yoube数据API并启用

Yoube数据API V3后面的页面上。

在左侧边栏,选择证书。对于资格证书,API支持的OAuth 2.0,使用服务帐户的API密钥和。我们将使用API密钥选项。

选择API密钥从添加凭据下拉菜单。会显示一个弹出让你指定密钥类型。选择Android的关键。接下来选择添加包名和指纹,并添

加Android应用程序的包名(我的是vc.zz.qduxsh.alxyoutubeplayer),然后在终端中运行以下命令来获取SHA-1证书指纹。

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

输入的android系统提示时作为密码。上位于调试密钥库上面的命令打印资料〜/ .android / debug.keystore您的计算机上。这是通

过Eclipse中或Android工作室当你第一次建立了一个Android应用程序自动生成的。在终端方面,你会看到MD5和SHA-1证书指

纹。复制SHA-1指纹,并将其粘贴在谷歌开发者控制台,然后点击创建按钮。API密钥将会产生。稍后我们将使用此。

在Andropid项目中,创建一个名为类Config.java并粘贴以下。

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";}

然后一个下载的最新版本的Android版Yoube播放器API的。下载完成后放到libs目录下,右键–》add as library

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

在build.gradle中加入

compile files(‘libs/YouTubeAndroidPlayerApi.jar’)

activity_youtube.xml

<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.YouTubePlayerViewandroid:id="@+id/youtube_view"android:layout_width="match_parent"android:layout_height="wrap_content"/></RelativeLayout>

MainActivity.java

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;//一个页面可以播放多个视频,将所有的播放控件收集到这里进行维护,主要是控制离开页面时候的暂停//定位到youtube的某个视频有三种方式public static final String VideoUrl_normal = "https://www.youtube.com/watch?v=PFKutKoYX7E";//这种是最普通的写在地址栏中的视频地址private View mVideoProgressView;private View mCustomView;//全屏显示的Viewprivate View mVideoFullScreenBack;private LinearLayout ll_player_container;private int mOriginalSystemUiVisibility;private int mOriginalOrientation;private WebChromeClient.CustomViewCallback mCustomViewCallback;Button btnWebview;Button btnvideo;@Overrideprotected 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() {@Overridepublic 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() {@Overridepublic void onClick(View view) {Intent intent = new Intent(MainActivity.this,YoutubeActivity.class);startActivity(intent);}});}@Overrideprotected void onStart() {super.onStart();}private class YoutubePlayerCallBack implements YoutubePlayerView.YouTubeListener {private YoutubePlayerView mYoutubeView;YoutubePlayerCallBack(YoutubePlayerView view){this.mYoutubeView = view;}@Overridepublic void onReady() {}@Overridepublic 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();}}}}}@Overridepublic void onPlaybackQualityChange(String arg) {}@Overridepublic void onPlaybackRateChange(String arg) {}@Overridepublic void onError(String arg) {}@Overridepublic void onApiChange(String arg) {}@Overridepublic void onCurrentSecond(double second) {}@Overridepublic void onDuration(double duration) {}@Overridepublic void logs(String log) {}}/*** 用于全屏显示的代码*/private WebChromeClient mWebChromeClient = new WebChromeClient(){@Overridepublic View getVideoLoadingProgressView() {if (mVideoProgressView == null) {LayoutInflater inflater = LayoutInflater.from(MainActivity.this);mVideoProgressView = inflater.inflate(R.layout.video_layout_loading, null);}return mVideoProgressView;}@Overridepublic void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {// if a view already exists then immediately terminate the new oneif (mCustomView != null) {onHideCustomView();return;}// 1. Stash the current statemCustomView = view;mOriginalSystemUiVisibility = MainActivity.this.getWindow().getDecorView().getSystemUiVisibility();mOriginalOrientation = MainActivity.this.getRequestedOrientation();Log.i("Alex","原来的屏幕方向是"+mOriginalOrientation);// 2. Stash the custom view callbackmCustomViewCallback = callback;// 3. Add the custom view to the view hierarchyFrameLayout 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 windowMainActivity.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);}@Overridepublic void onHideCustomView() {// 1. Remove the custom viewFrameLayout 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 formMainActivity.this.getWindow().getDecorView().setSystemUiVisibility(mOriginalSystemUiVisibility);MainActivity.this.setRequestedOrientation(mOriginalOrientation);// 3. Call the custom view callbackif(mCustomViewCallback!=null){mCustomViewCallback.onCustomViewHidden();mCustomViewCallback = null;}}};@Overridepublic void onPause() {//视频播放器当页面停止的时候所有的视频播放全部暂停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();}@Overridepublic 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;}@Overridepublic void onBackPressed() {Log.i("Alex", "进入onBackPressed方法");closeFullScreen();super.onBackPressed();}
}

在上面的代码中,我们创建一个类,是的子类YouTubeBaseActivity。这需要利用YouTubePlayerView。我们使用

YouTubePlayer.OnInitializedListener侦听初始化成功或失败。该接口有两个方法,一个名为onInitializationFailure()和

onInitializationSuccess() 。

例如,如果Yoube应用是不是安装在用户的设备上或已过期,对话将有一个提示,经确认后,将打开谷歌Play商店安装或相应

地更新它的用户。如果Yoube应用在设备上禁用,则该提示将打开系统设置为用户启用它。

当用户从错误恢复对话返回,的onActivityResult()被调用检查,查看是否用户执行的恢复操作。如果是这样,我们重试初始

化。

运行该应用程序,你应该能够发挥在代码中指定的视频。请注意,您将需要您的设备上的Yoube应用。该API客户端库与分布

的Yoube应用为Android平台的部分服务进行交互。用户需要运行移动版Yoube应用程式(或更高)的版本4.2.16使用API。

通常情况下,运行Android 2.2(升级Froyo)或更高版本有谷歌Play商店应用的设备应该能够运行向上的最新版本的Yoube应

用。

这意味着什么,除非你已经安装了谷歌Apps的虚拟设备,您将无法测试在模拟器上的代码。默认的Android模拟器不支持在设备

上安装谷歌企业应用套件,但如果你使用的模拟器像Genymotion,就可以使用了。即使在我的模拟器安装了谷歌企业应用套

件,我仍然无法播放视频。视频缩略图加载没关系的看法,但在攻播放按钮,加载指示灯会出现,但再装载会失败,“连接到服

务器丢失”的消息。您可能需要准备一个真正的设备。

结论

Android版的Yoube库提供了一个很好的API,你可以自定义此API,我们仅仅触及了它的边缘。要了解更多关于库,一定要通

过文档阅读并随附库下载示例应用程序。

你可以在这里下载完整的项目。记得放置在您的密钥Config.java文件。
IFrameAPI:https://github.com/gongzaijing/intelchange.git
AndroidAPI:https://github.com/gongzaijing/Android-VideoTube-master.git

在Android应用中集成YouTube视频播放功能相关推荐

  1. android 友盟统计功能,在Android工程中集成友盟统计

    在Android工程中集成友盟统计 首先需要在友盟官网注册账号并添加新应用,获取Appkey.具体步骤这里不进行叙述. 1.集成准备 首先需要集成友盟统计SDK 有两种方式: 1.下载SDK,并复制到 ...

  2. 深入了解Android系统中的音视频编解码器:MediaCodec

    Media内核源码 Media内核是Android系统中负责音视频处理的核心模块,包括音视频采集.编解码.传输.播放等功能.Media内核源码位于Android源码树的/frameworks/av目录 ...

  3. iOS中集成ijkplayer视频直播框架

    原文链接 ijkplayer 是一款做视频直播的框架, 基于ffmpeg, 支持 Android 和 iOS, 网上也有很多集成说明, 但是个人觉得还是不够详细, 在这里详细的讲一下在 iOS 中如何 ...

  4. Android项目中集成华为账号登录、支付

    最近项目中集成了华为账号登录与支付的功能,把踩过的坑和过程记录下来. 先看下支付效果图: 支付价格0.01请忽略,因为这是为了测试用的. 刚开始接到这个项目的时候我很奇怪,为什么要集成华为支付呢,原有 ...

  5. 在Android App中集成Google登录

    技术文章 来源:码农网 发布:2016-09-19 浏览:194 摘要:今天,几乎所有的web和移动app都自带谷歌和Facebook登录,这对app开发者和用户来说是一个非常有用的功能,因为几乎每个 ...

  6. android vitamio 函数,如何在Android Studio中集成Vitamio?

    我试图将Vitamio Bundle集成到我的Android Studio项目中,但这不适用于我的步骤 >我创建了一个新的Android项目"空白活动" >我选择文件& ...

  7. android支付宝支付微信支付封装,如何在Android App中集成支付宝和微信支付功能

    前言 本文主要介绍如何在 Android App 里集成支付宝和微信支付的功能,文中将实现的步骤一步步介绍的非常详细,对同样遇到这个问题的朋友相信会是一个很好的参考,下面话不多说了,来一起看看详细的介 ...

  8. ionic中的在线视频播放功能

    前言 在ionic中处理视频播放的功能在stackoverflow, ionic-forum以及ionic的github issue中都有提及,有很多相关讨论, 我们只针对在线视频播放功能进行下总结, ...

  9. 如何查找视频文件 android,如何扫描出android手机中所有的视频文件

    不说废话,直接上代码: public static List allVideoList = null;// 视频信息集合 allVideoList = new ArrayList(); getVide ...

  10. 如何扫描出android手机中所有的视频文件

    public static List<VideoInfo> allVideoList = null;// 视频信息集合 allVideoList = new ArrayList<Vi ...

最新文章

  1. docker-compos
  2. kotlin开发经验谈3
  3. 有了Windows Defender应用程序防护功能,再也不担心电脑免遭恶意***
  4. springboot+mybatis测试时遇到java.lang.NullPointerException
  5. codeblocks折叠区的颜色
  6. 解决 invalid input detected at ‘^’ marker的问题
  7. 下载 6g 概念及愿景白皮书_6G,到底有多6?6G概念及愿景白皮书正式发布!
  8. 不要打我,不要打我,不要打我啊啊
  9. java实现excel数据比对代码_java上传Excel文件并比对数据
  10. 体验不尽,进化不止,看视频云技术六大创新
  11. python notebook两个窗口_JupyterNotebook 输出窗口的显示效果调整实现
  12. 2016.11.03回顾 more excel交换两列
  13. Android上传图片的方式
  14. 区块链中的节点是什么意思?
  15. 概率论考点之相关系数
  16. 看漫画学python下载_Python爬虫实现漫画下载 - 『编程语言区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn...
  17. 计算机二本院校排名民办河北,2018河北二本大学排名
  18. 群晖 NAS + frp 最新端口
  19. 用python怎么赚钱-python怎么挣钱
  20. 【面试题】N阶台阶,每次走一步或两步,计算共有多少种走法,并将每种走法打印出来。

热门文章

  1. 顶级域名 一级域名 二级域名 三级域名什么区别?
  2. oracle中字符串长度计算,根据 oracle 标准计算超长字符串的长度
  3. pyenv管理虚拟环境
  4. 2022-05 - 英语语法 - 16种时态终极详解
  5. 汽车使用总结(七)--侧方停车
  6. 云计算机ppt模板,云服务云技术云计算PPT模板
  7. 服务器布线属于搬迁项目吗,弱电机房服务器搬迁建设整体规划与合理布局
  8. 前端xlsx导入与导出
  9. double转int方法为 去尾法
  10. 语音领域的波束形成Beamforming小结