1. 程式人生 > >android原生webview中呼叫JS方法並傳遞引數給JS遇到的問題

android原生webview中呼叫JS方法並傳遞引數給JS遇到的問題

在使用webview時,需要給JS傳遞一個引數,之前前端同事把JS方法內容和html內容分離了,所以在使用下面的方法的時候一直顯示方法未定義[INFO:CONSOLE(1)] "Uncaught ReferenceError: load is not defined", source:  (1),後來把JS方法寫到html裡,這個方法就可以呼叫了,因為是第一次做這個問題,所以不知道有沒有直接呼叫單獨JS檔案裡的方法

webview不能夠正常載入JS的問題可以看我的另一篇文章 http://blog.csdn.net/weixue9/article/details/78324737,呼叫Js方法並傳遞引數的具體步驟如下:

通過 WebViewClient 的方法shouldOverrideUrlLoading ()回撥攔截 url

具體原理:
1.Android通過 WebViewClient 的回撥方法shouldOverrideUrlLoading ()攔截 url 
2.解析該 url 的協議 
3.如果檢測到是預先約定好的協議,就呼叫相應方法,即JS需要呼叫Android的方法

具體使用:
步驟1:在JS約定所需要的Url協議
JS程式碼:javascript.html,以.html格式放到src/main/assets資料夾裡

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title>Carson_Ho</title>

     <script>
         function callAndroid(){
            /*約定的url協議為:js://webview?arg1=111&arg2=222*/
            document.location = "js://webview?arg1=111&arg2=222";
         }
      </script>
</head>

<!-- 點選按鈕則呼叫callAndroid()方法  -->
   <body>
     <button type="button" id="button1" onclick="callAndroid()">點選呼叫Android程式碼</button>
   </body>
</html>

當該JS通過Android的mWebView.loadUrl("file:///android_asset/javascript.html")載入後,就會回撥shouldOverrideUrlLoading (),接下來繼續看步驟2:
步驟2:在Android通過WebViewClient複寫shouldOverrideUrlLoading()

public class MainActivity extends AppCompatActivity {
    WebView mWebView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mWebView = (WebView) findViewById(R.id.webview);
        WebSettings webSettings = mWebView.getSettings();
        // 設定與Js互動的許可權
        webSettings.setJavaScriptEnabled(true);
        // 設定允許JS彈窗
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        // 步驟1:載入JS程式碼
        // 格式規定為:file:///android_asset/檔名.html
        mWebView.loadUrl("file:///android_asset/javascript.html");
        // 複寫WebViewClient類的shouldOverrideUrlLoading方法
        mWebView.setWebViewClient(new WebViewClient() {
              @Override
              public boolean shouldOverrideUrlLoading(WebView view, String url) {
                  // 步驟2:根據協議的引數,判斷是否是所需要的url
                  // 一般根據scheme(協議格式) & authority(協議名)判斷(前兩個引數)
                  //假定傳入進來的 url = "js://webview?arg1=111&arg2=222"(同時也是約定好的需要攔截的)
                  Uri uri = Uri.parse(url);                                 
                  // 如果url的協議 = 預先約定的 js 協議
                  // 就解析往下解析引數
                  if ( uri.getScheme().equals("js")) {
                      // 如果 authority  = 預先約定協議裡的 webview,即代表都符合約定的協議
                      // 所以攔截url,下面JS開始呼叫Android需要的方法
                      if (uri.getAuthority().equals("webview")) {
                         //  步驟3:
                          // 執行JS所需要呼叫的邏輯
                          System.out.println("js呼叫了Android的方法");
                          // 可以在協議上帶有引數並傳遞到Android上
                          HashMap<String, String> params = new HashMap<>();
                          Set<String> collection = uri.getQueryParameterNames();
                      }
                      return true;
                  }
                  return super.shouldOverrideUrlLoading(view, url);
              }
          }

特點

優點:不存在JS程式碼呼叫一定要在 onPageFinished() 回撥之後才能呼叫,否則不會呼叫。;
缺點:JS獲取Android方法的返回值複雜。如果JS想要得到Android方法的返回值,只能通過WebView的loadUrl()去執行JS方法把返回值傳遞回去,相關的程式碼如下:

// Android:MainActivity.java
mWebView.loadUrl("javascript:returnResult(" + result + ")");

// JS:javascript.html
function returnResult(result){
    alert("result is" + result);
}

上面的方法是借鑑http://www.jianshu.com/p/345f4d8a5cfa的方法