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

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

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

一个例子:

通过JS取得Android的GPS数据

第一步,WebKit的准备

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

  1. publicvoidonCreate(Bundleicicle){
  2. super.onCreate(icicle);
  3. WebViewwv=newWebView(this);
  4. wv.getSettings().setJavaScriptEnabled(true);//JS利用OK
  5. setContentView(wv);
  6. }


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

  1. JsObjjo=newJsObj(this);
  2. wv.addJavascriptInterface(jo,"roid");


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

  1. classJsObj{
  2. privateContextcon;
  3. publicJsObj(Contextcon){
  4. this.con=con;
  5. }
  6. publicStringgps(Stringtop,Stringend){
  7. LocationManagerlocman=(LocationManager)
  8. con.getSystemService(Context.LOCATION_SERVICE);
  9. Locationloc=locman.getCurrentLocation("gps");
  10. intlat=(int)(loc.getLatitude()*1000000);
  11. intlon=(int)(loc.getLongitude()*1000000);
  12. returntop+"緯度:"+lat+",経度:"+lon+end;
  13. }
  14. }


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

  1. <html>
  2. <head><title>JScallsAndroidMethod</title></head>
  3. <body>
  4. <h1>JSonAndroid</h1>
  5. <scripttype="text/javascript">
  6. document.write(roid.gps("<i>","</i>"));
  7. </script>
  8. </body>
  9. </html>

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

最后,全部的代码

  1. packagecom.adamrocker.android.web;
  2. importandroid.app.Activity;
  3. importandroid.content.Context;
  4. importandroid.location.Location;
  5. importandroid.location.LocationManager;
  6. importandroid.os.Bundle;
  7. importandroid.webkit.WebView;
  8. publicclassWebkitTestextendsActivity{
  9. /**Calledwhentheactivityisfirstcreated.*/
  10. @Override
  11. publicvoidonCreate(Bundleicicle){
  12. super.onCreate(icicle);
  13. WebViewwv=newWebView(this);
  14. wv.getSettings().setJavaScriptEnabled(true);
  15. JsObjjo=newJsObj(this);
  16. wv.addJavascriptInterface(jo,"roid");
  17. setContentView(wv);
  18. wv.loadUrl("http://www.adamrocker.com/android/js2android.html");
  19. }
  20. classJsObj{
  21. privateContextcon;
  22. publicJsObj(Contextcon){
  23. this.con=con;
  24. }
  25. publicStringgps(Stringtop,Stringend){
  26. LocationManagerlocman=(LocationManager)con
  27. .getSystemService(Context.LOCATION_SERVICE);
  28. Locationloc=locman.getCurrentLocation("gps");
  29. intlat=(int)(loc.getLatitude()*1000000);
  30. intlon=(int)(loc.getLongitude()*1000000);
  31. returntop+"緯度:"+lat+",経度:"+lon+end;
  32. }
  33. }
  34. }


未完

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

他们之间是如何通信的?

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

  1. /*InitializeprivatedatawithintheWebCorethread.
  2. */
  3. privatevoid[More...]initialize(){
  4. /*InitializeourprivateBrowserFrameclasstohandleall
  5. *frame-relatedfunctions.Weneedtocreateanewviewwhich
  6. *inturncreatesaClevelFrameViewandattachesittotheframe.
  7. */
  8. mBrowserFrame=newBrowserFrame(mContext,this,mCallbackProxy,
  9. mSettings,mJavascriptInterfaces);
  10. mJavascriptInterfaces=null;
  11. //SyncthenativesettingsandalsocreatetheWebCorethreadhandler.
  12. mSettings.syncSettingsAndCreateHandler(mBrowserFrame);
  13. //CreatethehandlerandtransfermessagesfortheIconDatabase
  14. WebIconDatabase.getInstance().createHandler();
  15. //CreatethehandlerforWebStorage
  16. WebStorage.getInstance().createHandler();
  17. //CreatethehandlerforGeolocationPermissions.
  18. GeolocationPermissions.getInstance().createHandler();
  19. //ThetransferMessagescallwilltransferallpendingmessagestothe
  20. //WebCorethreadhandler.
  21. mEventHub.transferMessages();
  22. //SendamessagebacktoWebViewtotellitthatwehavesetupthe
  23. //WebCorethread.
  24. if(mWebView!=null){
  25. Message.obtain(mWebView.mPrivateHandler,
  26. WebView.WEBCORE_INITIALIZED_MSG_ID,
  27. mNativeClass,0).sendToTarget();
  28. }
  29. }


生成了显示用对象

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

mEventHub截获

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

  1. Transferallmessagestothenewlycreatedwebcorethreadhandler.
  2. privatevoid[More...]transferMessages(){
  3. mTid=Process.myTid();
  4. mSavedPriority=Process.getThreadPriority(mTid);
  5. mHandler=newHandler(){
  6. @Override
  7. publicvoid[More...]handleMessage(Messagemsg){
  8. if(DebugFlags.WEB_VIEW_CORE){
  9. Log.v(LOGTAG,(msg.what<REQUEST_LABEL
  10. ||msg.what
  11. >VALID_NODE_BOUNDS?Integer.toString(msg.what)
  12. :HandlerDebugString[msg.what
  13. -REQUEST_LABEL])
  14. +"arg1="+msg.arg1+"arg2="+msg.arg2
  15. +"obj="+msg.obj);
  16. }
  17. switch(msg.what){
  18. caseWEBKIT_DRAW:
  19. webkitDraw();


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

我只能说是线程间通信。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值