Android的Webview中,javascript如何调用java方法

今天调查一个线上Bug,发现是WebView中的一小段javascript,会直接调用到后台APK的一个Java事件,最后导致java中nullpointexception。

感兴趣的是,WebView中的javascript如何调用APK中的java方法。

 

一个例子:

        通过JS取得Android的GPS数据

 

第一步,WebKit的准备

首先,给与WebKit的javascript的执行许可

 

[java]  view plain copy print ?
  1. public void onCreate(Bundle icicle) {  
  2.   super.onCreate(icicle);  
  3.   WebView wv = new WebView(this);  
  4.   wv.getSettings().setJavaScriptEnabled(true);//JS利用OK  
  5.   setContentView(wv);  
  6. }  


然后,塞入自己的javascript拦截器

[java]  view plain copy print ?
  1. JsObj jo = new JsObj(this);  
  2. wv.addJavascriptInterface(jo, "roid");  


第二步,定义自己的javascript拦截器

 

[java]  view plain copy print ?
  1. class JsObj {  
  2.   private Context con;  
  3.    
  4.   public JsObj(Context con) {  
  5.     this.con = con;  
  6.   }  
  7.    
  8.   public String gps(String top, String end) {  
  9.     LocationManager locman = (LocationManager)   
  10.          con.getSystemService(Context.LOCATION_SERVICE);  
  11.     Location loc = locman.getCurrentLocation("gps");  
  12.     int lat = (int) (loc.getLatitude() * 1000000);  
  13.     int lon = (int) (loc.getLongitude() * 1000000);  
  14.     return top + "緯度:" + lat + ", 経度: " + lon + end;  
  15.   }  
  16. }  


第三步,定义一个可运行的html

[html]  view plain copy print ?
  1. <html>  
  2.   <head><title>JS calls Android Method</title></head>  
  3.   <body>  
  4.     <h1>JS on Android</h1>  
  5.     <script type="text/javascript">  
  6.       document.write(roid.gps("<i>", "</i>"));  
  7.     </script>  
  8.   </body>  
  9. </html>  

在这个代码里面,可以用roid.gps的方法调用第二步定义的java函数

 

最后,全部的代码

[java]  view plain copy print ?
  1. package com.adamrocker.android.web;  
  2.    
  3. import android.app.Activity;  
  4. import android.content.Context;  
  5. import android.location.Location;  
  6. import android.location.LocationManager;  
  7. import android.os.Bundle;  
  8. import android.webkit.WebView;  
  9.    
  10. public class WebkitTest extends Activity {  
  11.   /** Called when the activity is first created. */  
  12.   @Override  
  13.    public void onCreate(Bundle icicle) {  
  14.       super.onCreate(icicle);  
  15.       WebView wv = new WebView(this);  
  16.       wv.getSettings().setJavaScriptEnabled(true);  
  17.       JsObj jo = new JsObj(this);  
  18.       wv.addJavascriptInterface(jo, "roid");  
  19.       setContentView(wv);  
  20.       wv.loadUrl("http://www.adamrocker.com/android/js2android.html");  
  21.   }  
  22.    
  23.    class JsObj {  
  24.       private Context con;  
  25.    
  26.       public JsObj(Context con) {  
  27.          this.con = con;  
  28.       }  
  29.    
  30.       public String gps(String top, String end) {  
  31.          LocationManager locman = (LocationManager) con  
  32.               .getSystemService(Context.LOCATION_SERVICE);  
  33.          Location loc = locman.getCurrentLocation("gps");  
  34.          int lat = (int) (loc.getLatitude() * 1000000);  
  35.          int lon = (int) (loc.getLongitude() * 1000000);  
  36.          return top + "緯度:" + lat + ", 経度: " + lon + end;  
  37.       }  
  38.   }  
  39. }  


未完

我还想知道为什么,在webview里面定义一个JSObject,就可以连接javascript和后台函数

他们之间是如何通信的?

 我稍微调查了一下WebView的底层代码,webview初期化的时候

[java]  view plain copy print ?
  1. /* Initialize private data within the WebCore thread. 
  2.   */  
  3.  private void  [More ...] initialize() {  
  4.   
  5.      /* Initialize our private BrowserFrame class to handle all 
  6.       * frame-related functions. We need to create a new view which 
  7.    * in turn creates a C level FrameView and attaches it to the frame. 
  8.       */  
  9.      mBrowserFrame = new BrowserFrame(mContext, this, mCallbackProxy,  
  10.              mSettings, mJavascriptInterfaces);  
  11.      mJavascriptInterfaces = null;  
  12.      // Sync the native settings and also create the WebCore thread handler.  
  13.      mSettings.syncSettingsAndCreateHandler(mBrowserFrame);  
  14.      // Create the handler and transfer messages for the IconDatabase  
  15.      WebIconDatabase.getInstance().createHandler();  
  16.      // Create the handler for WebStorage  
  17.      WebStorage.getInstance().createHandler();  
  18.      // Create the handler for GeolocationPermissions.  
  19.      GeolocationPermissions.getInstance().createHandler();  
  20.      // The transferMessages call will transfer all pending messages to the  
  21.      // WebCore thread handler.  
  22.      mEventHub.transferMessages();  
  23.      // Send a message back to WebView to tell it that we have set up the  
  24.      // WebCore thread.  
  25.      if (mWebView != null) {  
  26.          Message.obtain(mWebView.mPrivateHandler,  
  27.                  WebView.WEBCORE_INITIALIZED_MSG_ID,  
  28.                  mNativeClass, 0).sendToTarget();  
  29.      }  
  30.      }  


生成了显示用对象

 

而此对象的所有操作事件,都会被

mEventHub截获

而mEventHub会将请求发送给真正需要处理的MessageStub。 通过messageName

[java]  view plain copy print ?
  1. Transfer all messages to the newly created webcore thread handler.  
  2.   
  3.   private void  [More ...] transferMessages() {  
  4.   
  5.       mTid = Process.myTid();  
  6.   
  7.       mSavedPriority = Process.getThreadPriority(mTid);  
  8.   
  9.       mHandler = new Handler() {  
  10.   
  11.           @Override  
  12.           public void  [More ...] handleMessage(Message msg) {  
  13.   
  14.               if (DebugFlags.WEB_VIEW_CORE) {  
  15.   
  16.                   Log.v(LOGTAG, (msg.what < REQUEST_LABEL  
  17.   
  18.                           || msg.what  
  19.   
  20.                           > VALID_NODE_BOUNDS ? Integer.toString(msg.what)  
  21.   
  22.                           : HandlerDebugString[msg.what  
  23.   
  24.                                   - REQUEST_LABEL])  
  25.   
  26.                           + " arg1=" + msg.arg1 + " arg2=" + msg.arg2  
  27.   
  28.                           + " obj=" + msg.obj);  
  29.   
  30.               }  
  31.   
  32.               switch (msg.what) {  
  33.   
  34.                   case WEBKIT_DRAW:  
  35.   
  36.                       webkitDraw();  


所以你要问我他们是怎么通信的

我只能说是线程间通信。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值