当前位置:编程学习 > JAVA >>

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

今天调查一个线上Bug,发现是WebView中的一小段javascript,会直接调用到后台APK的一个Java事件,最后导致java中nullpointexception。
感兴趣的是,WebView中的javascript如何调用APK中的java方法。
 
一个例子:
        通过JS取得Android的GPS数据
 
第一步,WebKit的准备
首先,给与WebKit的javascript的执行许可
 
[java] 
public void onCreate(Bundle icicle) { 
  super.onCreate(icicle); 
  WebView wv = new WebView(this); 
  wv.getSettings().setJavaScriptEnabled(true);//JS利用OK 
  setContentView(wv); 

然后,塞入自己的javascript拦截器
[java] 
JsObj jo = new JsObj(this); 
wv.addJavascriptInterface(jo, "roid"); 

第二步,定义自己的javascript拦截器
 
[java] 
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] 
<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函数
 
最后,全部的代码
[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("www.zzzyk.com"); 
  } 
  
   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初期化的时候
[java] 
/* 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(); 
     } 
     } 

生成了显示用对象
mBrowserFrame
 
而此对象的所有操作事件,都会被
mEventHub截获
而mEventHub会将请求发送给真正需要处理的MessageStub。 通过messageName
[java] 
Transfer all messages to the newly created webcore thread handler. 
 
  private void  [More ...] transferMessages() { 
 
      mTid = Process.myTid(); 
 
      mSavedPriority = Process.getThre

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,