1. 程式人生 > >Android WebView Video完全詳解(第一篇)-Android開發人員

Android WebView Video完全詳解(第一篇)-Android開發人員

背景
最近公司某項功能需要WebView載入H5的Video,搜尋很多資料後發現很多問題,都是關鍵程式碼片段,因為每個專案每個人產生的問題不同,Video在webview中載入不出來原因很多,可能是客戶端少了引數,也可能是前端出了問題,經過研究後對Android WebView 載入H5Video標籤做此詳解。

需要注意的幾個點

  • video 播放有兩種狀態,在原來元件的位置直接播放,全屏播放。
  • IOS客戶端對H5 Video標籤做了特殊處理,即H5直接用video標籤即可,但是Android客戶端需要特殊JS處理,所以前端開發需要注意,在下面程式碼段會劃重點。
  • AndroidManifest.xml中Activity需要開加速,需要全屏設定需要設定configChanges
  • Video可以在Fragment中或者Activity中,但多個Fragment中共用一個Activity如果全屏播放建議考慮橫屏時生命週期,如果單開Activity載入WebView會更加清爽。

Anroid 客戶端畫重點

  • settings相關的設定
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private void setUpWebViewDefaults(WebView webView) {
        WebSettings settings = webView.getSettings();

        // Enable Javascript
settings.setJavaScriptEnabled(true); // Use WideViewport and Zoom out if there is no viewport defined settings.setUseWideViewPort(true); settings.setLoadWithOverviewMode(true); // Enable pinch to zoom without the zoom buttons settings.setBuiltInZoomControls(false
); // Allow use of Local Storage settings.setDomStorageEnabled(true); if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) { // Hide the zoom controls for HONEYCOMB+ settings.setDisplayZoomControls(false); } // Enable remote debugging via chrome://inspect if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { WebView.setWebContentsDebuggingEnabled(true); } webView.setWebViewClient(new WebViewClient()); }
  • WebChromeClient 相關設定
 void setChromeClient() {
        mWebView.setWebChromeClient(new WebChromeClient() {

            @Override
            public Bitmap getDefaultVideoPoster() {
                if (this == null) {
                    return null;
                }

                //這個地方是載入h5的視訊列表 預設圖   點選前的視訊圖
                return BitmapFactory.decodeResource(getApplicationContext().getResources(),
                        R.mipmap.ic_launcher);
            }

            @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 = getWindow().getDecorView().getSystemUiVisibility();
                mOriginalOrientation = getRequestedOrientation();

                // 2. Stash the custom view callback
                mCustomViewCallback = callback;

                // 3. Add the custom view to the view hierarchy
                FrameLayout decor = (FrameLayout) getWindow().getDecorView();
                decor.addView(mCustomView, new FrameLayout.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT));


                // 4. Change the state of the window
                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);
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }

            @Override
            public void onHideCustomView() {
                // 1. Remove the custom view
                FrameLayout decor = (FrameLayout) getWindow().getDecorView();
                decor.removeView(mCustomView);
                mCustomView = null;

                // 2. Restore the state to it's original form
                getWindow().getDecorView()
                        .setSystemUiVisibility(mOriginalSystemUiVisibility);
                setRequestedOrientation(mOriginalOrientation);

                // 3. Call the custom view callback
                mCustomViewCallback.onCustomViewHidden();
                mCustomViewCallback = null;

            }

        });
    }

如果是Activity中就三步走

initView(); //初始化webview
setUpWebViewDefaults(mWebView); //設定settings
setChromeClient(); //設定chromeClient
mWebView.loadUrl("file:///android_asset/www/index.html");

大功告成
這裡寫圖片描述

是啊只給程式碼段 ,我怎麼知道往哪裡拼~~~~
我喜歡直接拷貝啦~
走你~

package open.ppdai.com.webviewh5video;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;

/**
 * Email:[email protected]
 *
 * @data:17/1/12 上午11:16
 * @Description:${todo}
 *
 */
public class MainActivity extends Activity {

    private WebView mWebView;
    private View mCustomView;
    private int mOriginalSystemUiVisibility;
    private int mOriginalOrientation;
    private WebChromeClient.CustomViewCallback mCustomViewCallback;
    protected FrameLayout mFullscreenContainer;
    private Handler mHandler;

    public MainActivity() {
        mHandler = new Handler();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        setUpWebViewDefaults(mWebView);
        setChromeClient();
     mWebView.loadUrl("file:///android_asset/www/index.html"); //這個地方是本地的assets下的h5檔案
//android開發人員直接拿這個標準的檔案去看是否能從當前頁面播放,是否能全屏播放
    }

    private void initView() {
        mWebView = (WebView) findViewById(R.id.webview);
    }

    void setChromeClient() {
        mWebView.setWebChromeClient(new WebChromeClient() {

            @Override
            public Bitmap getDefaultVideoPoster() {
                if (this == null) {
                    return null;
                }

                //這個地方是載入h5的視訊列表 預設圖   點選前的視訊圖
                return BitmapFactory.decodeResource(getApplicationContext().getResources(),
                        R.mipmap.ic_launcher);
            }

            @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 = getWindow().getDecorView().getSystemUiVisibility();
                mOriginalOrientation = getRequestedOrientation();

                // 2. Stash the custom view callback
                mCustomViewCallback = callback;

                // 3. Add the custom view to the view hierarchy
                FrameLayout decor = (FrameLayout) getWindow().getDecorView();
                decor.addView(mCustomView, new FrameLayout.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT));


                // 4. Change the state of the window
                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);
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }

            @Override
            public void onHideCustomView() {
                // 1. Remove the custom view
                FrameLayout decor = (FrameLayout) getWindow().getDecorView();
                decor.removeView(mCustomView);
                mCustomView = null;

                // 2. Restore the state to it's original form
                getWindow().getDecorView()
                        .setSystemUiVisibility(mOriginalSystemUiVisibility);
                setRequestedOrientation(mOriginalOrientation);

                // 3. Call the custom view callback
                mCustomViewCallback.onCustomViewHidden();
                mCustomViewCallback = null;

            }

        });
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private void setUpWebViewDefaults(WebView webView) {
        WebSettings settings = webView.getSettings();

        // Enable Javascript
        settings.setJavaScriptEnabled(true);

        // Use WideViewport and Zoom out if there is no viewport defined
        settings.setUseWideViewPort(true);
        settings.setLoadWithOverviewMode(true);

        // Enable pinch to zoom without the zoom buttons
        settings.setBuiltInZoomControls(false);

        // Allow use of Local Storage
        settings.setDomStorageEnabled(true);

        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
            // Hide the zoom controls for HONEYCOMB+
            settings.setDisplayZoomControls(false);
        }

        // Enable remote debugging via chrome://inspect
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WebView.setWebContentsDebuggingEnabled(true);
        }

        webView.setWebViewClient(new WebViewClient());
    }


}

佈局檔案裡面就一個webview 如果不想寫直接去下載程式碼嘮~

看到這裡 ,如果你的webview還是沒有加載出Video來,那你直接把這這個demo執行結果扔給前端,並且把第二篇文章給前端人員看好了

這裡寫圖片描述

相關推薦

Android WebView Video完全第一-Android開發人員

背景 最近公司某項功能需要WebView載入H5的Video,搜尋很多資料後發現很多問題,都是關鍵程式碼片段,因為每個專案每個人產生的問題不同,Video在webview中載入不出來原因很多,可能是客戶端少了引數,也可能是前端出了問題,經

jsp第一

JSP入門 1 JSP概述 1.1什麼是JSP JSP(Java Server Pages)是JavaWeb伺服器端的動態資源。它與html頁面的作用是相同的,顯示資料和獲取資料。 1.2 JSP的組成 JSP=html+Java指令碼(

Mysql主從配置第一,共五

使用Docker容器搭建MySql主從複製 使用Docker容器搭建MySql主從複製 檢視容器ip命令為docker inspect 96fd[id前四位] Master_mysql_ip_172.17.0.4 slave_mysql_ip_172.17.0.5

Android Studio中Git和GitHub使用

一、Git和GitHub簡述 1.Git 分散式版本控制系統,最先使用於Linux社群,是一個開源免費的版本控制系統,功能類似於SVN和CVS。Git與其他版本管理工具最大的區別點和優點就是分散式; git是採用分散式版本庫機制,不需要每次都將檔案推送到版本控制伺服

阿里巴巴的Vlayout框架原始碼原理第一流程分析

先看一下阿里對這個框架留下的Demo的效果: 看效果大體的可以猜測這個框架給我們提供了很多佈局規則,據說淘寶首頁就是用這個框架做的。原始碼地址 好接下來我們就沿著這個Demo這條線開始分析實現原理,從而學習人家的架構搭建方式 先看佈局程式碼 <FrameLayo

Android Mvp模式Kotlin

mvp簡介與Mvc對比: 相信大家對MVC都是比較熟悉了:M-Model-模型、V-View-檢視、C-Controller-控制器,MVP作為MVC的演化版本,那麼類似的MVP所對應的意義:M-Mo

Android USB Host 使用U盤

首先說一下為什麼要寫關於Android USB Host通訊的介紹,對於Android程式原來說不懂硬體做USB通訊確實開頭比較難,但是Google API介紹還是很詳細的,而且網上也有很多例子,不過網上的基本把介紹和例子分開,光介紹不給例子,給個例子又不知道它是幹什麼的或

Python高階程式設計——裝飾器Decorator(絕對是我見過最詳細的的教程,沒有之一哦)

一、先從一種情況開始看起 1、裝飾器decorator的由來 裝飾器的定義很是抽象,我們來看一個小例子。 先定義一個簡單的函式: def myfunc:     print('我是函式myfunc') myfunc() #呼叫函式 然後呢,我想看看

“全棧2019”Java第二十八章:陣列

難度 初級 學習時間 10分鐘 適合人群 零基礎 開發語言 Java 開發環境 JDK v11 IntelliJ IDEA v2018.3 文章原文連結 “全棧2019”Java第二十八章:陣列詳解(上篇) 下一章 “全棧2019”Java第二十九章:陣列詳解(中篇)

史上最簡單MySQL教程基礎之多表聯合查詢

常用術語 內連線 外連線 左外連線 右外連線 注意事項: 自連線 子查詢 在上篇文章史上最簡單MySQL教程詳解(基礎篇)之資料庫設計正規化及應用舉例我們介紹過,在關係型資料庫中,我們通常為了減少資料的冗餘量將對資料表進行規範,將

TCP協議理論

1.    與UDP不同的是,TCP提供了一種面向連線的、可靠的位元組流服務。面向連線比較好理解,就是連線雙方在通訊前需要預先建立一條連線,這猶如實際生活中的打電話。助於可靠性,TCP協議中涉及了諸多規則來保障通訊鏈路的可靠性,總結起來,主要有以下幾點:       (1

React Native未來導航者:react-navigation 使用基礎

剛建立的React Native 微信公眾號,歡迎微信掃描關注訂閱號,每天定期會分享react native 技術文章,移動技術乾貨,精彩文章技術推送。同時可以掃描我的微信加入react-native技術交流微信群。歡迎各位大牛,React Native技術愛好者加入交流!上

事件驅動模型例項Java

這個按鈕的時候,按鈕物件會直接把這次點選感覺傳遞給ButtonEventHandler的actionPerformed方法處理,為養成較好的程式設計習慣,我們中心並不建議學員直接在該委託方法中編寫程式碼,而是需要將該事件處理再次轉發給窗體中的某個方法來處理,這個方法的命名也必須是有規則的,就是事件源名+下劃線

Ping命令引數

Ping命令詳解對於Windows下ping命令相信大家已經再熟悉不過了,但是能把ping的功能發揮到最大的人卻並不是很多,當然我也並不是說我可以讓ping發揮最大的功能,我也只不過經常用ping這個工具,也總結了一些小經驗,現在和大家分享一下。現在我就參照ping命令的幫助說明來給大家說說我使用ping時會

hadoop之mapreduce基礎

本篇文章主要從mapreduce執行作業的過程,shuffle,以及mapreduce作業失敗的容錯幾個方面進行詳解。 一、mapreduce作業執行過程 1.1、mapreduce介紹      MapReduce是一種程式設計模型,用於大規模資料集(大於1TB)的並行運

hadoop之mapreduce優化

一、概述      優化前我們需要知道hadoop適合幹什麼活,適合什麼場景,在工作中,我們要知道業務是怎樣的,能才結合平臺資源達到最有優化。除了這些我們當然還要知道mapreduce的執行過程,比如從檔案的讀取,map處理,shuffle過程,reduce處理,檔案的輸出或者

用ant的build.xml構建自動化打包android apk 完全打包系列教程之二

打包系列教程目錄: 通過上一篇文章內容的學習,我們基本已經明白了android打包簽名apk的主要操作與流程,那麼這一篇文章我們就將上一篇文章的打包內容轉化成ant的build.xml檔案進行自動化打包,這樣可以避免我們上一篇文章的敲打命令列的繁瑣操作,從而

python3多線程應用第一卷:線程的本質概念

本質 函數 解釋 style height auto 進行 mage pla 之前我用過多線程的方式執行了爬蟲程序,爬取了糗事百科的數據可以看到速率非常之快,就像正常一個人他要完一個漢堡,再吃喝一瓶水才能走,結果他邊吃漢堡邊喝水,速率一下加快了一樣。首先我們看看什麽是線程:

Android EventBus3.x 使用

led AC target 分解 感覺 div activit .org android事 ?(^∇^*) 五一假期在家無事,新項目中用的是RxJava2+EventBus感覺還不錯,趁這閑暇總結下EventBus 一、概要簡述   EventBus

Android應用程式啟動從原始碼瞭解App的啟動過程

本文承接《Android應用程式啟動詳解(一)》繼續來學習應用程式的啟動的那些事。上文提到startActivity()方法啟動一個app後經過一翻過程就到了app的入口方法ActivityThread.main()。其實我們在之前的文章中《Android的訊息機制(二)之L