1. 程式人生 > >【FastDev4Android框架開發】重寫WebView網頁載入以及JavaScript注入詳解(二十三)

【FastDev4Android框架開發】重寫WebView網頁載入以及JavaScript注入詳解(二十三)

轉載請標明出處: 

().前言:   

         【好訊息】個人網站已經上線執行,後面部落格以及技術乾貨等精彩文章會同步更新,請大家關注收藏:http://www.lcode.org

       今天我們來學習一下重寫WebView元件來實現網頁的載入,以及我們平時APP開發中經常使用的JS注入,js和java相互呼叫的問題來重點講解一下。如果大家都WebView載入還不是太熟悉的話,這邊我之前專門寫了一個WebView的專題,其他包含基本使用和js注入的問題。(點選進入WebView進階專題)

().重寫WebView:   

        2.1首先我們來看一下實現的效果:


 2.2.重寫

WebView:建立一個HTML5CustomWebView類整合自WebView,然後就是一下幾個步驟實現:

  • 佈局檔案
  • WebSettings初始化相關設定
  • 設定重寫WebChromeClient進行相關處理
  • 設定重寫WebViewClient進行相關處理即可

簡單的來說就是以上這幾步就可以了

2.3.WebView佈局檔案主要定義導航欄,網頁載入進度,以及WebView容器佈局,如下:

<?xmlversion="1.0" encoding="utf-8"?>
<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:background="@color/white">
    <RelativeLayout
       android:layout_width="fill_parent"
       android:layout_height="fill_parent">
        <FrameLayout
           android:id="@+id/fullscreen_custom_content"
           android:layout_width="fill_parent"
           android:layout_height="fill_parent"
           android:background="@color/white"
            android:visibility="gone"/>
        <LinearLayout
           android:layout_width="fill_parent"
           android:layout_height="fill_parent"
           android:orientation="vertical" >
            <!-- 自定義頂部導航功能條 -->
            <includelayout="@layout/common_top_bar_layout" />
            <!-- 中間顯示內容 -->
            <FrameLayout
               android:id="@+id/main_content"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent"
               android:visibility="gone" />
            <!-- 網頁載入進度顯示 -->
            <FrameLayout
               android:id="@+id/frame_progress"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent"
               android:visibility="visible" >
                <LinearLayout
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:layout_gravity="center"
                   android:orientation="vertical" >
 
                    <ProgressBar
                       style="@android:style/Widget.ProgressBar.Small"
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center_horizontal"
                       android:indeterminate="false"
                       android:indeterminateDrawable="@drawable/loading_small" />
 
                    <TextView
                       android:id="@+id/webview_tv_progress"
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_marginTop="3dip"
                       android:text="正在載入,已完成0%..."
                       android:textSize="12sp" />
                </LinearLayout>
            </FrameLayout>
        </LinearLayout>
    </RelativeLayout>
 
</FrameLayout>

   2.4.WebSettings初始化設定如下:

WebSettingswebSettings = this.getSettings();
webSettings.setJavaScriptEnabled(true);  //開啟javascript
webSettings.setDomStorageEnabled(true);  //開啟DOM
webSettings.setDefaultTextEncodingName("utf-8");//設定編碼
// // web頁面處理
webSettings.setAllowFileAccess(true);// 支援檔案流
// webSettings.setSupportZoom(true);// 支援縮放
// webSettings.setBuiltInZoomControls(true);// 支援縮放
webSettings.setUseWideViewPort(true);// 調整到適合webview大小
webSettings.setLoadWithOverviewMode(true);//調整到適合webview大小
webSettings.setDefaultZoom(ZoomDensity.FAR);//螢幕自適應網頁,如果沒有這個,在低解析度的手機上顯示可能會異常
webSettings.setRenderPriority(RenderPriority.HIGH);
//提高網頁載入速度,暫時阻塞圖片載入,然後網頁載入好了,在進行載入圖片
webSettings.setBlockNetworkImage(true);
//開啟快取機制
webSettings.setAppCacheEnabled(true);
//根據當前網頁連線狀態
 if(StrUtils.getAPNType(context)==StrUtils.WIFI){
 //設定無快取
 webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
 }else{
 //設定快取
 webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
 }
              

     2.5.WebChromeClient進行相關設定處理

private classMyWebChromeClient extends WebChromeClient {
privateBitmap mDefaultVideoPoster;
@Override
publicvoid onShowCustomView(View view,
CustomViewCallbackcallback) {
super.onShowCustomView(view,callback);
HTML5CustomWebView.this.setVisibility(View.GONE);
if(mCustomView != null) {
callback.onCustomViewHidden();
return;
}
mCustomViewContainer.addView(view);
mCustomView= view;
mCustomViewCallback= callback;
mCustomViewContainer.setVisibility(View.VISIBLE);
}
 
@Override
publicvoid onHideCustomView() {
if(mCustomView == null) {
return;
}
mCustomView.setVisibility(View.GONE);
mCustomViewContainer.removeView(mCustomView);
mCustomView= null;
mCustomViewContainer.setVisibility(View.GONE);
mCustomViewCallback.onCustomViewHidden();
HTML5CustomWebView.this.setVisibility(View.VISIBLE);
super.onHideCustomView();
}
 
/**
 * 網頁載入標題回撥
 * @param view
 * @param title
 */
@Override
publicvoid onReceivedTitle(WebView view, String title) {
Log.d("zttjiangqq", "當前網頁標題為:" + title);
wv_tv_title.setText(title);
}
 
/**
 * 網頁載入進度回撥
 * @param view
 * @param newProgress
 */
@Override
publicvoid onProgressChanged(WebView view, int newProgress) {
// 設定進行進度
((Activity)mContext).getWindow().setFeatureInt(
Window.FEATURE_PROGRESS,newProgress * 100);
webview_tv_progress.setText("正在載入,已完成" +newProgress + "%...");
webview_tv_progress.postInvalidate(); //重新整理UI
Log.d("zttjiangqq", "進度為:" + newProgress);
}
 
@Override
publicboolean onJsAlert(WebView view, String url, String message,
JsResultresult) {
returnsuper.onJsAlert(view, url, message, result);
 
}
}

  2.6.WebViewClient進行相關設定處理

private classMyWebViewClient extends WebViewClient {
/**
 *載入過程中 攔截載入的地址url
 * @param view
 *@param url  被攔截的url
 * @return
 */
@Override
publicboolean shouldOverrideUrlLoading(WebView view, String url) {
Log.i("zttjiangqq","-------->shouldOverrideUrlLoading url:" + url);
//這邊因為考慮到之前專案的問題,這邊攔截的url過濾掉了zttmall://開頭的地址
//在其他專案中 大家可以根據實際情況選擇不攔截任何地址,或者有選擇性攔截
if(!url.startsWith("zttmall://")){
UrimUri = Uri.parse(url);
List<String>browerList = new ArrayList<String>();
browerList.add("http");
browerList.add("https");
browerList.add("about");
browerList.add("javascript");
if(browerList.contains(mUri.getScheme())) {
returnfalse;
}else {
Intentintent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.addCategory(Intent.CATEGORY_BROWSABLE);
//如果另外的應用程式WebView,我們可以進行重用
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Browser.EXTRA_APPLICATION_ID,
FDApplication.getInstance()
.getApplicationContext().getPackageName());
try{
FDApplication.getInstance().startActivity(intent);
returntrue;
}catch (ActivityNotFoundException ex) {
}
}
returnfalse;
}else{
returntrue;
}
}
/**
 * 頁面載入過程中,載入資源回撥的方法
 * @param view
 * @param url
 */
@Override
publicvoid onLoadResource(WebView view, String url) {
super.onLoadResource(view,url);
Log.i("zttjiangqq","-------->onLoadResource url:" + url);
}
/**
 * 頁面載入完成回撥的方法
 * @param view
 * @param url
 */
@Override
publicvoid onPageFinished(WebView view, String url) {
super.onPageFinished(view,url);
Log.i("zttjiangqq","-------->onPageFinished url:" + url);
if(isRefresh) {
isRefresh= false;
}
// 載入完成隱藏進度介面,顯示WebView內容
frame_progress.setVisibility(View.GONE);
mContentView.setVisibility(View.VISIBLE);
// 關閉圖片載入阻塞
view.getSettings().setBlockNetworkImage(false);
 
}
/**
 * 頁面開始載入呼叫的方法
 * @param view
 * @param url
 * @param favicon
 */
@Override
publicvoid onPageStarted(WebView view, String url, Bitmap favicon) {
Log.d("zttjiangqq","onPageStarted:-----------"+url);
super.onPageStarted(view,url, favicon);
}
 
@Override
publicvoid onReceivedError(WebView view, int errorCode,
Stringdescription, String failingUrl) {
super.onReceivedError(view,errorCode, description, failingUrl);
}
 
@Override
publicvoid onScaleChanged(WebView view, float oldScale, float newScale) {
super.onScaleChanged(view,oldScale, newScale);
HTML5CustomWebView.this.requestFocus();
HTML5CustomWebView.this.requestFocusFromTouch();
}
 
}

以上一般使用到得方法已經做了相關的註釋。

最後一步就是使用了,使用起來很簡單,建立一個Activity,然後把我們定義的WebView加入到佈局然後載入網頁即可。如下:

packagecom.chinaztt.fda.html5;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.content.res.Configuration;
importandroid.net.Uri;
importandroid.os.Bundle;
importandroid.view.KeyEvent;
importandroid.view.MotionEvent;
importandroid.webkit.DownloadListener;
importandroid.webkit.JavascriptInterface;
/**
 * 當前類註釋:
 * 專案名:FastDev4Android
 * 包名:com.chinaztt.fda.html5
 * 作者:江清清 on 15/11/06 08:59
 * 郵箱:[email protected]
 * QQ: 781931404
 * 公司:江蘇中天科技軟體技術有限公司
 */
importcom.chinaztt.fda.ui.base.BaseActivity;
 
public classHTML5WebViewCustomAD extends BaseActivity {
privateHTML5CustomWebView mWebView;
//http://www.zttmall.com/Wapshop/Topic.aspx?TopicId=18
privateString ad_url = "http://www.baidu.com/";
private String title="百度一下你就知道";
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mWebView= new HTML5CustomWebView(this, HTML5WebViewCustomAD.this,title,ad_url);
mWebView.setDownloadListener(newDownloadListener() {
@Override
publicvoid onDownloadStart(String url, String userAgent,
StringcontentDisposition, String mimetype,
longcontentLength) {
Uriuri = Uri.parse(url);
Intentintent = new Intent(Intent.ACTION_VIEW, uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
        //準備javascript注入
mWebView.addJavascriptInterface(
newJs2JavaInterface(),"Js2JavaInterface");
if(savedInstanceState != null) {
mWebView.restoreState(savedInstanceState);
}else {
if(ad_url != null) {
mWebView.loadUrl(ad_url);
}
}
setContentView(mWebView.getLayout());
 
}
@Override
publicvoid onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(mWebView != null) {
mWebView.saveState(outState);
}
}
 
@Override
protectedvoid onResume() {
super.onResume();
if(mWebView != null) {
mWebView.onResume();
}
}
 
@Override
publicvoid onStop() {
super.onStop();
if(mWebView != null) {
mWebView.stopLoading();
}
}
@Override
protectedvoid onPause() {
super.onPause();
if(mWebView != null) {
mWebView.onPause();
}
}
 
@Override
protectedvoid onDestroy() {
super.onDestroy();
if(mWebView != null) {
mWebView.doDestroy();
}
}
 
@Override
publicvoid onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
 
@Override
publicboolean onTouchEvent(MotionEvent event) {
returnsuper.onTouchEvent(event);
}
 
@Override
publicboolean onKeyDown(int keyCode, KeyEvent event) {
returnsuper.onKeyDown(keyCode, event);
}
@Override
publicvoid onBackPressed() {
if(mWebView != null) {
if(mWebView.canGoBack()){
mWebView.goBack();
}else{
mWebView.releaseCustomview();
}
}
super.onBackPressed();
}
/**
 * JavaScript注入回撥
 */
publicclass Js2JavaInterface {
privateContext context;
privateString TAG = "Js2JavaInterface";
@JavascriptInterface
publicvoid showProduct(String productId){
if(productId!=null){
//進行跳轉商品詳情
showToastMsgShort("點選的商品的ID為:" +productId);
}else{
showToastMsgShort("商品ID為空!");
}
}
}
}

().js注入方法

仔細檢視上面的程式碼可能大家會發現這樣兩塊地方:

mWebView.addJavascriptInterface(
newJs2JavaInterface(),"Js2JavaInterface");
public classJs2JavaInterface {
privateContext context;
privateString TAG = "Js2JavaInterface";
@JavascriptInterface
publicvoid showProduct(String productId){
if(productId!=null){
//進行跳轉商品詳情
showToastMsgShort("點選的商品的ID為:" +productId);
}else{
showToastMsgShort("商品ID為空!");
}
}
}

這邊就是js注入回撥處理的方法,在這邊的例項中是使用http://www.zttmall.com/Wapshop/Topic.aspx?TopicId=18這個地址進行載入網頁的時候才會生效,因為這邊點選網頁圖片的時候,html程式碼中載入js方法,

我們來看一下網頁的原始碼:


檢視原始碼我們就知道

mWebView.addJavascriptInterface(
newJs2JavaInterface(),"Js2JavaInterface");

中第二個引數就是在js方法中呼叫的物件名字,然後注入物件中回撥的方法和js方法中的方法一樣即可。這樣就完成了一次注入點選回撥工作,我們的html就可以和原生java程式碼發生互動了。使用這種方式非常有助於我們的混合開發。

好了到此重寫WebView實現以及js注入的基本使用就講完了,具體全部程式碼已經上傳到FastDev4Android專案中了。同時歡迎大家去Github站點進行clone或者下載瀏覽:

關注我的訂閱號(codedev123),每天分享移動開發技術(Android/IOS),專案管理以及部落格文章!第一時間獲取推送文章!


關注我的微博,可以獲得更多精彩內容


相關推薦

FastDev4Android框架開發重寫WebView網頁載入以及JavaScript注入(十三)

轉載請標明出處: (一).前言:            【好訊息】個人網站已經上線執行,後面部落格以及技術乾貨等精彩文章會同步更新,請大家關注收藏:http://www.lcode.org       今天我們來學習一下重寫WebView元件來實現網頁的載入,以及我們平時AP

FastDev4Android框架開發CardView完全解析與RecyclerView結合使用(三十)

轉載請標明出處:(一).前言:           【好訊息】個人網站已經上線執行,後面部落格以及技術乾貨等精彩文章會同步更新,請大家關注收藏:http://www.lcode.org作為Android L開始,Google更新的除了RecyclerView之外的另一控制元件

FastDev4Android框架開發RecyclerView完全解析之打造新版類Gallery效果(十九)

轉載請標明出處:(一).前言:              【好訊息】個人網站已經上線執行,後面部落格以及技術乾貨等精彩文章會同步更新,請大家關注收藏:http://www.lcode.org         話說RecyclerView已經面市很久,也在很多應用中得到廣泛的使

FastDev4Android框架開發HorizontalScrollView,Fragment,FragmentStatePagerAdapter打造網易新聞Tab及滑動頁面效果(三十六)

轉載請標明出處:(一).前言:            【好訊息】個人網站已經上線執行,後面部落格以及技術乾貨等精彩文章會同步更新,請大家關注收藏:http://www.lcode.org         仿36Kr客戶端開發過程中,因為他們網站上面的新聞文章分類比較多,所以我

FastDev4Android框架開發非常漂亮的進度指示器AVLoadingIndicatorView的使用講解(十八)

轉載請標明出處: (一).前言:          【好訊息】個人網站已經上線執行,後面部落格以及技術乾貨等精彩文章會同步更新,請大家關注收藏:http://www.lcode.org      今天我們的專案繼續更新,今天主要要加入一個非常漂亮的進度指示器AVLoading

FastDev4Android框架開發Volley完全解析之基礎使用(十六)

轉載請標明出處:(一).前言:             【好訊息】個人網站已經上線執行,後面部落格以及技術乾貨等精彩文章會同步更新,請大家關注收藏:http://www.lcode.org對於網路框架這

FastDev4Android框架開發訊息匯流排EventBus的基本使用(十)

轉載請標明出處: (一).前言:        【好訊息】個人網站已經上線執行,後面部落格以及技術乾貨等精彩文章會同步更新,請大家關注收藏:http://www.lcode.org      今天我們的

FastDev4Android框架開發AndroidAnnnotations注入框架使用之最佳實踐SharedPreferences(十七)

轉載請標明出處:  (一).前言:    前面我們已經對於AndroidAnnotations使用Adapters和lists做了講解,今天我們開始具體學習一下使用DI框架SharedPrefe

React Native開發React Native控制元件之RefreshControl元件(21)

轉載請標明出處:(一)前言         【好訊息】個人網站已經上線執行,後面部落格以及技術乾貨等精彩文章會同步更新,請大家關注收藏:http://www.lcode.org        今天我們一起來看一下RefreshControl下拉重新整理元件講解以及使用例項剛建立的React Native技術交

Unity3D遊戲開發基於NGUI的表情圖文混排解決方案 ()

使用unity3d也有兩年時間了,最近比較閒,有功夫梳理一下去年一年來學到以及用到的知識,分享給大家,順便方便自己查閱。如有錯誤以及不當的地方,歡迎各位指正。謝謝。     去年五月份的時候,剛加入專案不久,老大交給我一個關於聊天系統任務,期初覺得應該很容易,但是看了文

SSM框架開發專案--用到的註解記錄,及。(先記錄,後研究,再總結---未完)

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) //保證序列化json的時候,如果是null的物件,key也會消失 public c

WEB開發微信網頁授權第三方登入介面(WEB登入)

 本文連結至:http://blog.csdn.net/hxker/article/details/50260669 第一步:獲取AppID AppSecret(不做解釋,自己去微信公眾平臺申請) 第二步:生成掃描二維碼,獲取code https://open

大數據開發你知道大數據語言的工具與框架嗎?

新節點 java 學習曲線 定義 onf 團隊 工具 cal 儀表盤 為了解大數據的當前和未來狀態,我們采訪了來自28個組織的31位IT技術主管。我們問他們,“你在數據提取,分析和報告中使用的最流行的語言,工具和框架是什麽?” 以下的文章是他們告訴我們的記錄,經過總結如下。

iOS越獄開發怎樣將應用打包成.ipa文件

ria font 配置文件 例如 方法 col stat pack 應該 在項目開發中。我們經常須要將project文件打包成.ipa文件。提供給越獄的iphone安裝。 以下是一種方法: 1、首先應該給project安裝好配置文件(這裏不再敖述),在ios de

微信開發02.搭建一個屬於自己的微信公眾平臺

tro 投票 新浪 關系 blank 訂閱 logs name 開發者 閱讀目錄 【網站開發】在新浪SAE上搭建一個博客 概述   公司年會上同事開發了一個微信企業號,包含了投票,抽獎,祝福墻功能,還開了一個Session,跟我們講了下公司的企業號開發過程和抽獎中獎

Android 應用開發 ActionBar 樣式具體解釋 -- 樣式 主題 簡單介紹 Actionbar 的 icon logo 標題 菜單樣式改動

detail sub str 進度條 代碼分析 extc dst 模式 html 作者 : 萬境絕塵 ([email protected]/* */)轉載請著名出處 : http://blog.csdn.net/shulianghan/article/deta

React Native開發React Native控件之ProgressBarAndroid進度條解說(12)

ice 發現 來講 top 文章 func dev all ios 轉載請標明出處:http://blog.csdn.net/developer_jiangqq/article/details/50596367本文出自:【江清清的博客】(一)前言 【好消息】

微信開發-- 發送模板消息

use keyword 選擇 調用 一次 png exc style col 我們需要將一些行為的進展消息推送給用戶。除了短信,發送微信模板消息也是不錯的選擇。模板消息免費、精準到達、而且可以引導用戶回到網站上來。但它有兩個前提條件。1個是必須開通了微信支付功能,你才能選擇

Unity遊戲開發淺談Unity遊戲開發中的單元測試

可靠 屬於 sin 自定義類型 允許 ogr 兩個 階段 ast 一、單元測試的定義與作用   單元測試定義:單元測試在傳統軟件開發中是非常重要的工具,它是指對軟件中的最小可測試單元進行檢查和驗證,一般情況下就是對代碼中的一個函數去進行驗證,檢查它的正確性。一個單元測試是

ci框架基礎之部署百度編輯器

asc 點擊 class containe 壓縮版 合並 ueditor builder 插件 在ci框架下加載編輯器,現在復習下內容。我的框架文件名稱為ci 1.下載百度編輯器ueditor,http://ueditor.baidu.com/ 一般情況下下載ubuil