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

PS:另外推荐下面这篇文章《用注解和pojo支撑起来的轻量级REST框架--T2

http://blog.csdn.net/nanjingjiangbiao/article/details/7680702

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

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

一个例子:

通过JS取得Android的GPS数据

第一步,WebKit的准备

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

public void onCreate(Bundle icicle) {
  super.onCreate(icicle);
  WebView wv = new WebView(this);
  wv.getSettings().setJavaScriptEnabled(true);//JS利用OK
  setContentView(wv);
}


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

JsObj jo = new JsObj(this);
wv.addJavascriptInterface(jo, "roid");


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

class JsObj {
  private Context con;
 
  public JsObj(Context con) {
    this.con = con;
  }
 
  public String gps(String top, String end) {
    LocationManager locman = (LocationManager) 
         con.getSystemService(Context.LOCATION_SERVICE);
    Location loc = locman.getCurrentLocation("gps");
    int lat = (int) (loc.getLatitude() * 1000000);
    int lon = (int) (loc.getLongitude() * 1000000);
    return top + "緯度:" + lat + ", 経度: " + lon + end;
  }
}


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

<html>
  <head><title>JS calls Android Method</title></head>
  <body>
    <h1>JS on Android</h1>
    <script type="text/javascript">
      document.write(roid.gps("<i>", "</i>"));
    </script>
  </body>
</html>

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

最后,全部的代码

package com.adamrocker.android.web;
 
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.webkit.WebView;
 
public class WebkitTest extends Activity {
  /** Called when the activity is first created. */
  @Override
   public void onCreate(Bundle icicle) {
      super.onCreate(icicle);
      WebView wv = new WebView(this);
      wv.getSettings().setJavaScriptEnabled(true);
      JsObj jo = new JsObj(this);
      wv.addJavascriptInterface(jo, "roid");
      setContentView(wv);
      wv.loadUrl("http://www.adamrocker.com/android/js2android.html");
  }
 
   class JsObj {
      private Context con;
 
      public JsObj(Context con) {
         this.con = con;
      }
 
      public String gps(String top, String end) {
         LocationManager locman = (LocationManager) con
              .getSystemService(Context.LOCATION_SERVICE);
         Location loc = locman.getCurrentLocation("gps");
         int lat = (int) (loc.getLatitude() * 1000000);
         int lon = (int) (loc.getLongitude() * 1000000);
         return top + "緯度:" + lat + ", 経度: " + lon + end;
      }
  }
}


未完

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

他们之间是如何通信的?

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

/* Initialize private data within the WebCore thread.
  */
 private void  [More ...] initialize() {

     /* Initialize our private BrowserFrame class to handle all
      * frame-related functions. We need to create a new view which
   * in turn creates a C level FrameView and attaches it to the frame.
      */
     mBrowserFrame = new BrowserFrame(mContext, this, mCallbackProxy,
             mSettings, mJavascriptInterfaces);
     mJavascriptInterfaces = null;
     // Sync the native settings and also create the WebCore thread handler.
     mSettings.syncSettingsAndCreateHandler(mBrowserFrame);
     // Create the handler and transfer messages for the IconDatabase
     WebIconDatabase.getInstance().createHandler();
     // Create the handler for WebStorage
     WebStorage.getInstance().createHandler();
     // Create the handler for GeolocationPermissions.
     GeolocationPermissions.getInstance().createHandler();
     // The transferMessages call will transfer all pending messages to the
     // WebCore thread handler.
     mEventHub.transferMessages();
     // Send a message back to WebView to tell it that we have set up the
     // WebCore thread.
     if (mWebView != null) {
         Message.obtain(mWebView.mPrivateHandler,
                 WebView.WEBCORE_INITIALIZED_MSG_ID,
                 mNativeClass, 0).sendToTarget();
     }
     }


生成了显示用对象

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

mEventHub截获

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

Transfer all messages to the newly created webcore thread handler.

  private void  [More ...] transferMessages() {

      mTid = Process.myTid();

      mSavedPriority = Process.getThreadPriority(mTid);

      mHandler = new Handler() {

          @Override
          public void  [More ...] handleMessage(Message msg) {

              if (DebugFlags.WEB_VIEW_CORE) {

                  Log.v(LOGTAG, (msg.what < REQUEST_LABEL

                          || msg.what

                          > VALID_NODE_BOUNDS ? Integer.toString(msg.what)

                          : HandlerDebugString[msg.what

                                  - REQUEST_LABEL])

                          + " arg1=" + msg.arg1 + " arg2=" + msg.arg2

                          + " obj=" + msg.obj);

              }

              switch (msg.what) {

                  case WEBKIT_DRAW:

                      webkitDraw();


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

我只能说是线程间通信。

#以上#


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值