android 中java和javascript交互

android的WebView是一個很是強大的控件,本文主要針對其簡單使用和筆者在使用時所遇到的問題作一些總結。javascript

本文參考了該博文:http://blog.csdn.net/zgjxwl/article/details/9627685html

目錄java

1、WebView中Java與javascript交互android

2、使用時碰見android版本兼容的問題web

3、關於代碼混淆致使JS和Java沒法交互的問題api

4、Android和IOS共同開發的小提示安全

 

1、WebView中Java與javascript交互app

1.這是要和js交互的注入接口類:ide

public final class JavascriptMethodClass1 {
     // 用Handler是保證交互執行在UI線程中
private Handler handler; public JavascriptMethodClass1(Handler handler) { this.handler = handler; }
     // 該註解主要是避免4.2以上的系統版本沒法交互的問題 @JavascriptInterface
public void test(final String teststr) { handler.post(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), teststr, Toast.LENGTH_LONG).show(); } }); } @JavascriptInterface public void test1() { handler.post(new Runnable() { @Override public void run() { // 調用js代碼 webView.loadUrl("javascript:testJavaCall('這是java調js的方法')"); } }); } }

 

2.這是交互的代碼,其中data裏的window.testObject.test('這是js掉java的Test方法')是調用java的代碼post

webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JavascriptInteerface(), "testObject");

// 測試的HTML代碼
String data ="<HTML><HEAD><script type=\"text/javascript\">function testJavaCall(str){alert(str);};</script></HEAD><BODY><H1>TEST1</H1></BODY><BR /><INPUT type=\"button\" value=\"js調用java\" onclick=\"window.testObject.test('這是js掉java的Test方法')\" /><INPUT type=\"button\" value=\"java調js\" onclick=\"window.testObject.test1()\" /></HTML>";

// 若是是網頁,直接用loadUrl(url)方法
webView.loadDataWithBaseURL(null, data, "text/html", "utf-8", null);

 

2、使用時碰見android版本兼容的問題

WebView存在android系統版本升級致使的兼容性問題。本文主要討論的是java和js的交互問題。4.2版本以前和4.2版本(包含)以後接入js是有所區別的。

在以前,筆者使用的注入交互接口類以下:

public final class JavascriptInteerface{
        public void test() {
            Toast.makeText(getApplicationContext(), "這是java代碼的Test方法", Toast.LENGTH_LONG).show();
        }
}

調用爲:

webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JavascriptInteerface(), "testObject");

按照上面的方法,在個人手機(android系統版本爲4.4.2)上運行沒有反應,查看log時顯示以下錯誤:

E/Web Console﹕ Uncaught TypeError: Object [object Object] has no method 'test' at about:blank:1

緣由:由於這個接口容許JavaScript 控制宿主應用程序,這是個很強大的特性,但同時,在4.2的版本前存在重大安全隱患,由於JavaScript 可使用反射訪問注入webview的java對象的public fields,在一個包含不信任內容的WebView中使用這個方法,會容許攻擊者去篡改宿主應用程序,使用宿主應用程序的權限執行java代碼。所以4.2之後,任何爲JS暴露的接口,都須要加@JavascriptInterface註釋,這樣,這個Java對象的fields 將不容許被JS訪問。

官網對於該問題大概描述以下:


 

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_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())");

IMPORTANT:

  • This method can be used to allow JavaScript to control the host application. This is a powerful feature, but also presents a security risk for apps targeting JELLY_BEAN or earlier. Apps that target a version later than JELLY_BEAN are still vulnerable if the app runs on a device running Android earlier than 4.2. The most secure way to use this method is to target JELLY_BEAN_MR1 and to ensure the method is called only when running on Android 4.2 or later. With these older versions, JavaScript could use reflection to access an injected object's public fields. Use of this method in a WebView containing untrusted content could allow an attacker to manipulate the host application in unintended ways, executing Java code with the permissions of the host application. Use extreme care when using this method in a WebView which could contain untrusted content.
  • JavaScript interacts with Java object on a private, background thread of this WebView. Care is therefore required to maintain thread safety.
  • The Java object's fields are not accessible.
  • For applications targeted to API level LOLLIPOP and above, methods of injected Java objects are enumerable from JavaScript.

 

因此,要解決上述問題:只須要在每一個Javascript要調用的Java接口中得每一個方法前加上這句@JavascriptInterface。例如我以前的代碼改成

public final class JavascriptInteerface{
        @JavascriptInterface
        public void test() {
            Toast.makeText(getApplicationContext(), "這是java代碼的Test方法", Toast.LENGTH_LONG).show();
        }
}

 

3、關於代碼混淆致使JS和Java沒法交互的問題

就在作好上面的全部事情後,覺得就沒事了,但是,上線的時候發現根本就沒法交互。緣由:在混淆以後注入的JAVA接口被重命名了,致使html裏的Js沒法匹配Java的接口名。

解決方法:(根據我「一」條目中得使用代碼來講明):在混淆文件中加入以下配置

-keepclassmembers class com.test.package.TestActivity$JavascriptMethodClass { public *; }
 # 如下兩行爲在Android4.2版本以上的手機必須加入的對註解進行處理的配置
-keepattributes *Annotation*
-keepattributes *JavascriptInterface*

 

4、Android和IOS共同開發的小提示

至此,該問題就獲得解決。除了該問題外,在作IOS和Android同時跟同一個HTML5中得JS交互時,也會遇到一個問題,主要是向注入js對象不同致使,這種解決方法最好是在IOS向HTML動態注入js代碼;也能夠在JS中判斷客戶端使用的設備,在此就很少作說明。

相關文章
相關標籤/搜索