1. 程式人生 > >WebView與Js交互

WebView與Js交互

hat bean length 暫時 cor pan ner port over

上周五,老大讓暫時搞一個評分app,倆頁面。第一個頁面顯示全部待評分的物業,第二個頁面是相應物業的評分頁面。評分頁面是表格樣式的,所以就讓web端的同學寫個html,我們通過Webview去展示。

這裏不不過展示就完了,web頁面須要知道我們點擊的哪個物業以及所填評委的名字並顯示在html上。所以client須要把這兩個值傳給html。當評委評分完後點擊html裏的提交button並提交成功後。client也須要進行響應。做法就是client提供接口,js代碼去調用來獲取值——JS調用Android本地代碼來實現。


今天主要總結兩點:一是使用Js去調用client公有方法。二是從client調用Js中的方法


一、JS調用client公有方法

上樣例:(PS:不會寫JS,就網上找了一段js代碼)

新建項目,在項目的assets目錄下創建一個test.html:

<body>
<a>Web與Js交互:點擊我,來調用client的show方法吧</a>
<script>
    function funFromjs(){
    	document.getElementById("helloweb").innerHTML="我是JS裏的方法";
    }
    var aTag = document.getElementsByTagName('a')[0];
    aTag.addEventListener('click', function(){
        //調用android本地方法
		AppFunction.show("Js調用show()方法成功。");
        return false;
    }, false);
    </script>
<p></p>
<div id="helloweb">
</div>
</body>

這段代碼有兩個重點。一是funFromjs()方法,該方法是js裏提供給client去調用的方法。二是AppFunction.show();show()方法是client提供給js去調用的方法,AppFunction是定義的接口名。

底下是client的實現:

package com.aliao.web;

import android.annotation.SuppressLint;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.widget.Toast;


public class MainActivity extends ActionBarActivity {

    private WebView mWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }


    private void initViews() {
        String url = "file:///android_asset/test.html";
        mWebView = (WebView) findViewById(R.id.webview);
        mWebView.getSettings().setJavaScriptEnabled(true);//支持js
        mWebView.addJavascriptInterface(this, "AppFunction");
        mWebView.loadUrl(url);
    }

    @JavascriptInterface
    public void show(String msg){
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

}

這裏須要註意的是,在Android4.2.2及之後的版本號僅僅有帶有JavascriptInterface凝視的public方法才可以被js訪問。所以要在show()方法前加:@JavascriptInterface

詳細查看:Webview addJavascriptInterface()

public void addJavascriptInterface (Object object, String name)

Added in API level 1

Injects the supplied Java object into this WebView. The object is injected into the JavaScript context of the main frame, using the supplied name. This allows the Java object‘s methods to be accessed from JavaScript. For applications targeted to API levelJELLY_BEAN_MR1 and above, only public methods that are annotated with JavascriptInterface can be accessed from JavaScript. For applications targeted to API level JELLY_BEAN or below, all public methods (including the inherited ones) can be accessed, see the important security note below for implications.

Note that injected objects will not appear in JavaScript until the page is next (re)loaded. For example:

 class JsObject {
    @JavascriptInterface
    public String toString() { return "injectedObject"; }
 }
 webView.addJavascriptInterface(new JsObject(), "injectedObject");
 webView.loadData("", "text/html", null);
 webView.loadUrl("javascript:alert(injectedObject.toString())");
這段是說,註入提供的java對象到WebView中。

該對象以接口名的方式被註入到Javascript的上下文環境中。這樣就能夠在JavaScript中去訪問該對象的方法。對於APl Level在4.2及以上的應用。僅僅有帶有JavascriptInterface凝視的的公有方法能夠被JavaScript訪問。對於Api Level在4.1及下面的應用。全部的公有方法都能夠被訪問(包含繼承的方法),參見下面的重要的安全註意的影響。

(系統版本號在4.2下面要考慮的安全問題先mark下這個blog:Android WebView的Js對象註入漏洞解決方式)

這裏我把當前類的對象註入到webview中,命名為AppFunction。這樣在JavaScript裏就能夠通過AppFunction直接訪問MainActivity中定義的供js調用方法。

   mWebView.addJavascriptInterface(this, "AppFunction");
也能夠自己定義一個類,比如上例中的

webView.addJavascriptInterface(new JsObject(), "injectedObject");
定義一個JsObject類。該類裏定義了提供給Js調用的方法,將該對象命名為injectedOnject。即接口名註入到js中。

執行後的結果:

技術分享


二、JS調用client公有方法

前面寫過的test.html裏已經提供了一個供Androidclient調用的方法funFromjs()。那client的代碼要怎麽寫?

在MainActivity的布局文件裏加入一個button,點擊該button後,調用js中的funFromjs方法:

package com.aliao.web;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.Toast;


public class MainActivity extends ActionBarActivity {

    private WebView mWebView;
    private Button mBtnCallJsFun;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }


    private void initViews() {
        String url = "file:///android_asset/test.html";
        mWebView = (WebView) findViewById(R.id.webview);
        mWebView.getSettings().setJavaScriptEnabled(true);//支持js
        mWebView.addJavascriptInterface(this, "AppFunction");
        mWebView.loadUrl(url);

        mBtnCallJsFun = (Button) findViewById(R.id.btn_call_js_fun);
        mBtnCallJsFun.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mWebView.loadUrl("javascript:funFromjs()");
            }
        });
    }

    @JavascriptInterface
    public void show(String msg){
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

}

執行結果:

技術分享




WebView與Js交互