JavaScript與Android的數據交互,js與安卓數據交互WebView

本文思路:
1,webview介紹,
2,android中的書寫
3,js中的書寫,
4,出現的問題,一定要看完。不然。。。就出錯了





說道數據交互,首先要先說一下交互需要使用的控件WebView;

簡單的介紹下用法:

1,和正常控件一樣,聲明,初始化,

WebView myWebView = (WebView) findViewById(R.id.webview);

加載網絡的url

myWebView.loadUrl(“http://www.google.com“);

加載本地的url,在asset目錄下
myWebView.loadUrl(“file:///android_asset/XX.html“);


打開設置,添加js支持,纔可以進行與js交互。相當於許可證。

WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);


//在JSHook類裏實現javascript想調用的方法,並將其實例化傳入webview, "hello"這個字串告訴javascript調用哪個實例的方法

這是核心方法,

webView.addJavascriptInterface(new JSHook(), "hello"); 

定義一個類,將方法封裝,用來供js調用;

public class JSHook{
        public void javaMethod(String p){
            Log.d(tag , "JSHook.JavaMethod() called! + "+p);
        }
        
        public void showAndroid(){
            String info = "來自手機內的內容!!!";
            webView.loadUrl("javascript:show('"+info+"')");
        }
        
        public String getInfo(){
            return "獲取手機內的信息!!";
        }
    }

接下來就是在js腳本中的書寫,android中,重要的就這些使用方法,當然還有很多,直說傳遞用的方法。其他忽略




下面,一個完整的例子:


JavaScript中的書寫:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>調用Android組件測試</title>
<script type="text/javascript">
    function show(info){
        document.getElementById("shows").innerHTML = info;
    }
</script>
</head>

<body>
<b>測試</b>
<br />
<button onClick="window.hello.javaMethod('param')">啓動hello world Activity</button>
<br />
<hr  color="#99FF00"/>
<button onClick="window.hello.showAndroid()">顯示android內容</button>
<br />
<textarea id= "shows"  cols="20" rows="10"> 暫無記錄 </textarea>
<br />

</body>
</html>


安卓中的書寫:

public class MainActivity extends ActionBarActivity {


    //private static final String URL = "http://shouji.baidu.com/";
    private static final String URL = "file:///android_asset/helloworld.html";
    private WebView webView;
    public String tag = "MainActivity";
    private Context mContext;
    
    @SuppressLint("JavascriptInterface") 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        //this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        // 進行全屏


        mContext = this;
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        webView = (WebView) this.findViewById(R.id.wv);


        webView.loadUrl(URL);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.addJavascriptInterface(new JSHook(), "hello");
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                Log.d(tag, " url:"+url);
              view.loadUrl(url);// 當打開新鏈接時,使用當前的 WebView,不會使用系統其他瀏覽器
                return true;
            } 
        });
    }
  
    public class JSHook{
        @JavascriptInterface
        public void javaMethod(String p){
            Log.d(tag , "JSHook.JavaMethod() called! + "+p);
        }
        @JavascriptInterface
        public void showAndroid(){
            final String info = "來自手機內的內容!!!";
            MainActivity.this.runOnUiThread(new Runnable(){
                @Override
                public void run() {
                    webView.loadUrl("javascript:show('"+info+"')");
                }
            });
        }
        public String getInfo(){
            return "獲取手機內的信息!!";
        }
    }
    @Override 
    //設置回退  
    //覆蓋Activity類的onKeyDown(int keyCoder,KeyEvent event)方法  
    public boolean onKeyDown(int keyCode, KeyEvent event) {  
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {  
            webView.goBack(); //goBack()表示返回WebView的上一頁面 
            this.finish();
            return true;  
        }  
        return false;  }


}














public class JSHook{
        public void javaMethod(String p){
            Log.d(tag , "JSHook.JavaMethod() called! + "+p);
        }
        
        public void showAndroid(){
            String info = "來自手機內的內容!!!";
            webView.loadUrl("javascript:show('"+info+"')");
        }
        
        public String getInfo(){
            return "獲取手機內的信息!!";
        }
    }










注意的問題:!!!!!!!!!!!!!!!!!!!!

上面這段代碼在android4.4版本及之前是沒有問題的, 4.4之後就會出現以下兩個異常錯誤。 07-10 10:25:21.417: I/chromium(27333): [INFO:CONSOLE(19)] "Uncaught TypeError: Object [object Object] has no method 'showAndroid'", source: file:///android_asset/helloworld.html (19) 解決方法:在js調用方法上面加註解@JavascriptInterface 07-10 10:42:58.437: I/chromium(27621): [INFO:CONSOLE(19)] "Uncaught Error: Error calling method on NPObject.", source: file:///android_asset/helloworld.html (19) 解決方法:在對界面進行修改時必須在UI線程進行,即便它是Html的界面,因此在出現這個錯誤的時候可以用handler或runOnUiThread()方法去執行更新UI操作。 注:實例代碼是排除了在高版本中出現異常的最終代碼。 異常原因: webview允許JavaScript 控制宿主應用程序,這是個很強大的特性,但同時,在4.2的版本前存在重大安全隱患,因爲JavaScript 可以使用反射訪問注入webview的java對象的public fields,在一個包含不信任內容的WebView中使用這個方法,會允許攻擊者去篡改宿主應用程序,使用宿主應用程序的權限執行java代碼。因此4.2以後,任何爲JS暴露的接口,都需要加 @JavascriptInterface 註解,這樣,這個Java對象的fields 將不允許被JS訪問。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章