Android的Webview中,javascript如何调用java方法
6901 点击·0 回帖
![]() | ![]() | |
![]() | 今天调查一个线上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.atcpu.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.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(); 作者:nanjingjiangbiao | |
![]() | ![]() |