Android應用開發-------------WebView(一)之WebView與服務器端的Js交互

最近公司再添加功能的時候,有一部分功能是用的html,在一個瀏覽器或webview中展現出html便可。固然在這裏咱們固然用webview控件嘍

 

WebApp的好處:

在應用裏嵌套web的好處有這麼幾點,1,跨平臺,不只能夠在Android上運行,也能夠在iOS上運行,並且樣式什麼的絕對統一,由於都是加載的html,用的都是同一套html

2,修改靈活,容易更新版本。例如你們常看到的app裏面的廣告頁,大可能是嵌套的html,這樣只要後臺替換一下頁面的內容,手機端就會改變展示內容,跟新版本也是如此,由於界面什麼得成了在服務器端,因此要是想跟新界面什麼得,只須要在後臺修改在發佈便可,不須要用戶再從新下載app。這個好處我以爲對ios是有很大幫助的,哈哈,繞開蘋果審覈嘛,因爲html咱們能夠隨意替換,審覈時能夠把違規的部分隱藏,上線以後就能夠隨意改了,哈哈,大家懂得。

 

固然,開發webapp固然也有侷限,就是網速什麼的,這個咱沒法改變,這裏也不廢話。不過在開發中呢,若是隻是頁面之間的交互的話,咱們只需提供一個webview控件便可,

但是要是涉及到和手機設備或軟件交互的話(如打開相冊,攝像頭等等),這就須要咱們和頁面經行js交互,js交互能夠說是雙向的,一種是,咱們調用頁面的,就是調用服務端的js方法,另外一個呢則是服務端調用咱們Android裏面的代碼,調用其實很簡單,下面說一下怎樣調用。

固然咱們先等有一個WebView,先建立一個Activity,而後設置佈局,穿件WebView,佈局和Activity以下:

activity_webview.xml



[html] view plain copy print?在CODE上查看代碼片派生到個人代碼片
01.<?xml version="1.0" encoding="utf-8"?>  
02.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
03.    android:layout_width="match_parent"  
04.    android:layout_height="match_parent"  
05.    android:orientation="vertical" >  
06.    <WebView   
07.        android:id="@+id/webview"  
08.        android:layout_width="match_parent"  
09.        android:layout_height="match_parent"  
10.        />  
11.  
12.</LinearLayout>  




而後是activity,

WebViewActivity.activity



[java] view plain copy print?在CODE上查看代碼片派生到個人代碼片
01.import android.app.Activity;  
02.import android.os.Bundle;  
03.import android.webkit.WebSettings;  
04.import android.webkit.WebView;  
05.  
06.public class WebViewActivity extends Activity {  
07.    private static final String url = "http://192.168.30.199:8080/song/test.html";  
08.    private WebView mWebView;  
09.    @Override  
10.    protected void onCreate(Bundle savedInstanceState) {  
11.        super.onCreate(savedInstanceState);  
12.        setContentView(R.layout.activity_webviw);  
13.        initView();  
14.    }  
15.  
16.    private void initView() {  
17.        mWebView = (WebView) findViewById(R.id.webview);  
18.        //或的WebView的Setting  
19.        WebSettings settings = mWebView.getSettings();  
20.        //設置支持js,看方法名字就知道啥意思  
21.        settings.setJavaScriptEnabled(true);  
22.        //加載網頁路徑  
23.        mWebView.loadUrl(url);  
24.    }  
25.}  




上面就是一個簡單的webview,而後很常規的設置屬性,而後再加載要加載的頁面路徑,這樣通常就可在網頁裏面自由點擊跳轉了,可是要和手機交互的話須要咱們寫js交互的代碼了。

首先說怎樣調用服務器端的js方法,很簡單,和加載網頁路徑基本上同樣以下:



[java] view plain copy print?在CODE上查看代碼片派生到個人代碼片
01.mWebView.loadUrl("javascript:forSmallPhoto()");  




就這麼簡單的一句話你就能夠調用服務器端的js方法了,其中JavaScript:是固定寫法forSmallPhoto()則是服務端的js方法名字,這是一個無參數的方法,固然也能夠傳參,這須要咱們拼湊字符串,mWebView.loadUrl("javascript:forSmallPhoto('" + data + "')");其中data就是一個變量,也就是你要傳的參數值,固然也能夠支持多參數傳送,這得看你服務器端的js方法有幾個參數了,其實就是咱們調用一個方法同樣,只不過這個方法是在服務器端的。咱們調用服務器js,是爲了,當Android完成某些功能後,須要告訴服務器,則咱們能夠調用js來告訴他咱們完成了。

 

在一種就是,服務端調用咱們的Android代碼了,這裏Android中也是封裝好了接口

咱們能夠經過void android.webkit.WebView.addJavascriptInterface(Object object, String name)的方法來實現服務器端調用咱們的代碼,其中這個方法有兩個參數,一個是object,另外一個是String類型的; 只要webview調用了這個方法就能夠調用咱們的代碼了。而要調用的代碼咱們寫在Object裏面,首先咱們就先實現這個Object,咱們建立一個類,JavaScriptInterface。Android中APi Guides中提供的Demo中取得累的名字是JavaScriptInterface,那咱們也用這個名字把。而後實現它,而後隨便在裏面寫一個方法,以下面

JavaScriptInterface.Java類



[java] view plain copy print?在CODE上查看代碼片派生到個人代碼片
01.import java.util.HashMap;  
02.import java.util.Map;  
03.  
04.import android.content.Context;  
05.import android.os.Handler;  
06.import android.os.Message;  
07.import android.text.TextUtils;  
08.import android.util.Log;  
09.import android.webkit.JavascriptInterface;  
10.import android.widget.Toast;  
11.  
12./** 
13. *  
14. * Title: JavaScriptInterface.java Description: 
15. *  
16. * @author Liusong 
17. * @version V1.0 
18. */  
19.public class JavaScriptInterface {    
20.          
21.    /** Instantiate the interface and set the context */  
22.    public JavaScriptInterface() {  
23.    }  
24.  
25.    /** Show a toast from the web page */  
26.    @JavascriptInterface  
27.    public void showToast() {  
28.        Log.i("TAG", "調用成功==================》》》》》");  
29.  
30.    }  
31.  
32.}  





這樣就完成了一個簡單的JavaScriptInterface類,這個類的方法是本身隨便寫的,其中,先說一下這裏要注意的幾點,首先重要的@JavascriptInterface這個註解,你會發現去掉也不會報錯,可是這個是很早重要的,若是你想讓服務器端調用你的方法,你就要加上這個註解@JavascriptInterface。在4.4api中說道,必定要加這個註解,負責調用不會成功,其實我在開發中,用紅米1s,4.3的系統,就無法調用成功了,當時還納悶,由於當時手裏的文檔是4.2的,非常鬱悶。因此在這裏強掉,必定要在本身寫的方法前面加上@JavascriptInterface。

還有一個注意的是方法的參數,這裏是一個無參方法,固然這裏你也能夠寫一個有參方法,這裏先提一下,待會會配合html裏面的js說道,咱們先說void android.webkit.WebView.addJavascriptInterface(Object object, String name)這個方法裏面的第二個參數,第二個參數你能夠理解爲是標識符,就是服務器端調用你方法時,須要找到你,怎麼找到?就是經過這個標識符,標識符是本身隨便定的,可是,你要告訴後臺開發人員你的標識符是什麼,咱們這裏把這第二個參數設置爲「Android」。下面我給出我測試的html代碼結合着看你就明白了。

test.html



[html] view plain copy print?在CODE上查看代碼片派生到個人代碼片
01.<!doctype html>  
02.<html>  
03.<head>  
04.    <meta name="viewport" content="width=device-width, initial-scale=1" charset="GBK">  
05.    <title>測試</title>  
06.</head>  
07.  
08.<body>  
09.  
10.<div data-role="page" >  
11.      
12.<script type="text/javascript">  
13.     function callAndroidAction(action) {  
14.        Android.showToast();        alert("我敢保證,你如今用的是演示一");  
15.    }  
16.     function forSmallPhoto(action) {  
17.        alert("我敢保證,你如今用的是演示一"+action);  
18.    }  
19.</script>  
20.  
21.    <div data-role="header">  
22.        <h1>調用圖庫</h1>  
23.        <!--   <a href="#" class="ui-btn">返回</a>-->  
24.    </div>  
25.  
26.    <div data-role="main" class="ui-content">  
27.  
28.        <div style="width: 98%;margin: 0 auto; text-align: center">  
29.            <a href="#" class=" ui-btn ui-btn-inline" onclick="callAndroidAction(0)">調用圖庫  </a>  
30.              
31.            <a href="#" class=" ui-btn ui-btn-inline" onclick="callAndroidAction('2')"> 充值  </a>  
32.          
33.        </div>  
34.  
35.  
36.    </div>  
37.  
38.     
39.</div>  
40.  
41.</body>  
42.  
43.  
44.</html>  





這個代碼有點亂,就將就這看吧,我是把這個頁面放在本身的tomcat上的,其中這個html中你們發現
 



[html] view plain copy print?在CODE上查看代碼片派生到個人代碼片
01.<script type="text/javascript">  
02.    function callAndroidAction(action) {  
03.        Android.showToast();  
04.        alert("我敢保證,你如今用的是演示一");  
05.    }  
06.   function forSmallPhoto(action) {  
07.        alert("我敢保證,你如今用的是演示一"+action);  
08.    }  
09.</script>  





  

這個js方法沒,看見裏面的Android標識符沒,沒錯,後臺就是這麼調用咱們代碼的,Android.showToast();就是這麼調用的,就是這麼簡單,不要想的太難,咱們就需按我上面說的那樣,把Object實現,把標識符寫好就ok了。飯後,後臺就會經過標識符和你Object的方法名字調用你的方法。這裏要說一下,你Object(即JavaScriptInterface,咱們上面已經實現)裏的方法的參數要和後臺調用你的方法的參數個數和類型一直,就像咱們平時調用方法是同樣的。這一點知道了就行了。

這樣就能夠了。

因此WebViewActivity裏面加上這一句就能夠了。



[java] view plain copy print?在CODE上查看代碼片派生到個人代碼片
01.view.addJavascriptInterface(new JavaScriptInterface(),"Android");  




 

這樣js就說完了。

模版

當後臺要調用咱們的代碼,咱們就寫一個方法,若是調用屢次咱們就寫多個,這樣太麻煩,因此咱們來寫一個通用的方法,就是不管後臺調用你代碼幹不一樣的事,都調用你這個方法,那怎麼區分不一樣的執行動做呢?用傳的參數,咱們在JavaScriptInterface裏面寫一個方法,這裏就叫callAndroidAction,我設計的是給這個方法三個參數,

public void callAndroidAction(String action, String url,String json),第一個參數action,即用來表示要執行的動做,第二個則是url,不論是服務其給的下載路徑仍是,訪問其餘頁面的路徑,在一個json就是其餘一些參數,因爲傳的參數不固定,咱們就用一個參數,一個參數時就傳過來,多個參數時能夠經過json字符串傳過來,就不必麻煩一個一個的寫參數了。

而後咱們在設計一個回調,讓操做的代碼拿出去,怎大致就是這樣了



[java] view plain copy print?在CODE上查看代碼片派生到個人代碼片
01.import java.util.HashMap;  
02.import java.util.Map;  
03.  
04.import android.content.Context;  
05.import android.os.Handler;  
06.import android.os.Message;  
07.import android.text.TextUtils;  
08.import android.util.Log;  
09.import android.webkit.JavascriptInterface;  
10.import android.widget.Toast;  
11.  
12./** 
13. *  
14. * Title: JavaScriptInterface.java Description: 
15. *  
16. * @author Liusong 
17. * @version V1.0 
18. */  
19.public class JavaScriptInterface {  
20.      
21.    private Handler mHandler;  
22.      
23.    /** Instantiate the interface and set the context */  
24.    public JavaScriptInterface(Handler handler) {  
25.        mHandler = handler;  
26.    }  
27.  
28.    /** Show a toast from the web page */  
29.    @JavascriptInterface  
30.    public void showToast(final String toast) {  
31.        Log.i("TAG", "調用成功==================》》》》》");  
32.    }  
33.  
34.    @JavascriptInterface  
35.    public void callAndroidAction(String action, String url,String json) {  
36.        Map<String, String> params = new HashMap<String, String>();  
37.        if(!TextUtils.isEmpty(url)){  
38.            params.put("url", url);  
39.        }  
40.        if(!TextUtils.isEmpty(json)){  
41.            params.put("json", json);  
42.        }  
43.        Message msg = Message.obtain();  
44.        msg.what = Integer.valueOf(action);  
45.        msg.obj = params;  
46.        mHandler.sendMessage(msg);  
47.    }  
48.}  





這樣咱們就從服務其拿到的參數都給Handler了,則WebViewActivity裏面就要這樣寫了



[java] view plain copy print?在CODE上查看代碼片派生到個人代碼片
01.import java.util.HashMap;  
02.import java.util.Map;  
03.  
04.import android.app.Activity;  
05.import android.os.Bundle;  
06.import android.os.Handler;  
07.import android.os.Message;  
08.import android.webkit.WebSettings;  
09.import android.webkit.WebView;  
10.  
11.public class WebViewActivity extends Activity {  
12.    private static final String url = "http://192.168.30.199:8080/song/test.html";  
13.      
14.    //執行動做  
15.    public static final int SELECT_IMAGE = 0;// 打開圖庫  
16.    public static final int OPEN_PAGE = 1;// 跳轉其餘特定頁面  
17.    public static final int CLOSE_OR_BACK = 2;// 關閉或  
18.      
19.    private WebView mWebView;  
20.    @Override  
21.    protected void onCreate(Bundle savedInstanceState) {  
22.        super.onCreate(savedInstanceState);  
23.        setContentView(R.layout.activity_webviw);  
24.        initView();  
25.    }  
26.   <p>  
27.     private void getIntentDatas() {  
28.          // TODO Auto-generated method stub  
29.        url = getIntent().getStringExtra("url");  
30.   }</p><p> </p>    private void initView() {  
31.        mWebView = (WebView) findViewById(R.id.webview);  
32.        //或的WebView的Setting  
33.        WebSettings settings = mWebView.getSettings();  
34.        //設置支持js,看方法名字就知道啥意思  
35.        settings.setJavaScriptEnabled(true);  
36.        mWebView.addJavascriptInterface(new JavaScriptInterface(handler), "Android");  
37.        //加載網頁路徑  
38.        mWebView.loadUrl(url);  
39.    }  
40.      
41.    private Handler handler = new Handler(){  
42.        public void handleMessage(Message msg) {  
43.            switch (msg.what) {  
44.            case SELECT_IMAGE://執行打開圖庫,  
45.                  
46.                //若是有參數,取服務端傳過來的參數(url,json)  
47.                Map<String, String> params = (HashMap<String, String>)msg.obj;  
48.                break;  
49.                  
50.            //其餘功能,可隨着本身功能的增長,在這裏增長,只需和後臺商量好動做的action值便可  
51.            default:  
52.                break;  
53.            }  
54.        };  
55.    };  
56.}  




最後再讓WebViewActivity通用,就是經過傳url參數



[java] view plain copy print?在CODE上查看代碼片派生到個人代碼片
01.private void getIntentDatas() {  
02. // TODO Auto-generated method stub  
03. url = getIntent().getStringExtra("url");  
04.}  
相關文章
相關標籤/搜索