今天主要總結兩點:一是使用js去調用用戶端公有方法,二是從用戶端調用js中的方法
一、js調用用戶端公有方法
上例子:(ps:不會寫js,就網上找了一段js代碼)
建立項目,在項目的assets檔案夾下建立一個test.html:
[html] 純文字檢視 複制代碼
<a target="_blank" href="http://www.apkbus.com/#">?</a>
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<code><</code><code>body</code><code>></code>
<code><</code><code>a</code><code>>web與js互動:點選我,來調用用戶端的show方法吧</</code><code>a</code><code>></code>
<code><</code><code>script</code><code>></code>
<code> </code><code>function funfromjs(){</code>
<code> </code><code>document.getelementbyid("helloweb").innerhtml="我是js裡的方法";</code>
<code> </code><code>}</code>
<code> </code><code>var atag = document.getelementsbytagname('a')[0];</code>
<code> </code><code>atag.addeventlistener('click', function(){</code>
<code> </code><code>//調用android本地方法</code>
<code> </code><code>appfunction.show("js調用show()方法成功!");</code>
<code> </code><code>return false;</code>
<code> </code><code>}, false);</code>
<code> </code><code></</code><code>script</code><code>></code>
<code><</code><code>p</code><code>></</code><code>p</code><code>></code>
<code><</code><code>div</code>
<code>id</code><code>=</code><code>"helloweb"</code><code>></code>
<code></</code><code>div</code><code>></code>
<code></</code><code>body</code><code>></code>
這段代碼有兩個重點,一是funfromjs()方法,該方法是js裡提供給用戶端去調用的方法。二是appfunction.show();show()方法是用戶端提供給js去調用的方法,appfunction是定義的接口名。底下是用戶端的實作:
[java] 純文字檢視 複制代碼
18
19
20
21
22
23
24
25
26
27
<code>package</code>
<code>com.aliao.web;</code>
<code>import</code>
<code>android.annotation.suppresslint;</code>
<code>android.support.v7.app.actionbaractivity;</code>
<code>android.os.bundle;</code>
<code>android.webkit.javascriptinterface;</code>
<code>android.webkit.webview;</code>
<code>android.widget.toast;</code>
<code>public</code>
<code>class</code> <code>mainactivity</code><code>extends</code>
<code>actionbaractivity {</code>
<code> </code><code>private</code>
<code>webview mwebview;</code>
<code> </code><code>@override</code>
<code> </code><code>protected</code>
<code>void</code> <code>oncreate(bundle savedinstancestate) {</code>
<code> </code><code>super</code><code>.oncreate(savedinstancestate);</code>
<code> </code><code>setcontentview(r.layout.activity_main);</code>
<code> </code><code>initviews();</code>
<code>void</code> <code>initviews() {</code>
<code> </code><code>mwebview = (webview) findviewbyid(r.id.webview);</code>
<code> </code><code>mwebview.getsettings().setjavascriptenabled(</code><code>true</code><code>);</code><code>//支援js</code>
<code> </code><code>mwebview.addjavascriptinterface(</code><code>this</code><code>,</code><code>"appfunction"</code><code>);</code>
<code> </code><code>mwebview.loadurl(url);</code>
<code> </code><code>@javascriptinterface</code>
<code> </code><code>public</code>
<code>void</code> <code>show(string msg){</code>
<code> </code><code>toast.maketext(</code><code>this</code><code>, msg, toast.length_short).show();</code>
<code>}</code>
這裡需要注意的是,在android4.2.2及之後的版本隻有帶有 javascriptinterface 注釋的public方法才能夠被js通路。是以要在show()方法前加:@javascriptinterface
具體檢視: webview addjavascriptinterface()(http://developer.android.com/reference/android/webkit/webview.html#addjavascriptinterface(java.lang.object,%20java.lang.string))
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 level jelly_bean_mr1 and
above, only public methods that are annotated with javascriptinterface can be accessed from javascript. for applications targeted to api level jelly_beanor
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:
<code>class</code>
<code>jsobject {[/backcolor] </code><code>@javascriptinterface</code>
<code>string tostring() {</code><code>return</code>
<code>"injectedobject"</code><code>; }</code>
<code>webview.addjavascriptinterface(</code><code>new</code>
<code>jsobject(),</code><code>"injectedobject"</code><code>);</code>
<code>webview.loaddata(</code><code>""</code><code>,</code><code>"text/html"</code><code>,</code><code>null</code><code>);</code>
<code>webview.loadurl(</code><code>"javascript:alert(injectedobject.tostring())"</code><code>);</code>
這段是說,注入提供的java對象到webview中。該對象以接口名的方式被注入到javascript的上下文環境中。這樣就可以在javascript中去通路該對象的方法。對于apl level在4.2及以上的應用,隻有帶有 javascriptinterface 注釋的的公有方法可以被javascript通路。對于api
level在4.1及以下的應用,所有的公有方法都可以被通路(包括繼承的方法),參見下面的重要的安全注意的影響。(系統版本在4.2以下要考慮的安全問題先mark下這個blog: android webview的js對象注入漏洞解決方案http://blog.csdn.net/leehong2005/article/details/11808557
)
這裡我把目前類的對象注入到webview中,命名為appfunction,這樣在javascript裡就可以通過appfunction直接通路mainactivity中定義的供js調用方法。
<code>mwebview.addjavascriptinterface(</code><code>this</code><code>,</code><code>"appfunction"</code><code>);</code>
也可以自定義一個類,例如上例中的
定義一個jsobject類,該類裡定義了提供給js調用的方法,将該對象命名為injectedonject,即接口名注入到js中。
運作後的結果:

二、js調用用戶端公有方法
前面寫過的test.html裡已經提供了一個供android用戶端調用的方法funfromjs(),那用戶端的代碼要怎麼寫?
在mainactivity的布局檔案中添加一個按鈕,點選該按鈕後,調用js中的funfromjs方法:
28
29
30
31
32
33
34
35
36
<code>android.view.view;</code>
<code>android.widget.button;</code>
<code>button mbtncalljsfun;</code>
<code> </code><code>mbtncalljsfun = (button) findviewbyid(r.id.btn_call_js_fun);</code>
<code> </code><code>mbtncalljsfun.setonclicklistener(</code><code>new</code>
<code>view.onclicklistener() {</code>
<code> </code><code>@override</code>
<code> </code><code>public</code>
<code>void</code> <code>onclick(view v) {</code>
<code> </code><code>mwebview.loadurl(</code><code>"javascript:funfromjs()"</code><code>);</code>
<code> </code><code>}</code>
<code> </code><code>});</code>
運作結果: