热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

androidjsjava,[转载]Android笔记(三十六)Android中js和java的互调(二)

20.4读取js全局变量或函数返回值借助现有接口技术,js可以执行原生java代码中的方法,可以得到方法的返回值,可以让原生java代码在

20.4读取js全局变量或函数返回值

借助现有接口技术,js可以执行原生java代码中的方法,可以得到方法的返回值,可以让原生java代码在主线程中动态的操作UI;但是借助该接口,原生java代码,采用webview.loadUrl("Javascript:

JsFunctionName"),只能做到执行js中的方法,如果想获取js中定义的全局变量,或者获取某个js函数的返回值,这种方式无法做到,webview也没有提供别的函数来可供使用。

为了实现该功能,我们分析application

framework的源代码发现,从webview类loadurl()方法一路追踪,最终在WebViewCore.java中找到如下代码:

private native void passToJs(int frame, int node, int x, int y,

int gen,

String currentText, int keyCode, int keyValue, boolean down,

boolean cap, boolean fn, boolean sym);

在BrowserFrame中,追踪到:

private native void nativeAddJavascriptInterface(int

nativeFramePointer,

Object obj, String interfaceName);

至此我们知道android的webview实现,使用的是开源的webkit浏览器内核,该内核是用c语言(webcore)和c++语言(jscore)实现的,android的webview底层实现最终是调用的webkit内核代码,如果该内核提供了直接读取js全局变量或者函数返回值的方法,那么我们可以使用JNI(Java

Native Interface)的方式来读取出来。

20.4.1反射读取方式

在android.webkit包中有个BrowserFrame私有类,该类中有个Native方法:

public native String

stringByEvaluatingJavascriptFromString(String script);

这个和苹果中的类似:

Public NSString stringByEvaluatingJavascriptFromString(NSString

script);

虽然该类是私有的,但是我们可以利用反射技术来执行这个方法,从而取得js全局变量和函数返回值;

步骤:

1、 扩展WebView,派生出MyWebView类,添加

public String

stringByEvaluatingJavascriptFromString(String

script)方法,该方法体中最终利用反射技术实现;

2、 修改布局中的WebView为com.appeon.test.MyWebView类型;

3、  在页面load完成的情况下,编码取得JS变量或函数返回值;

MyWebView.java:

package com.appeon.test;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import android.content.Context;

import android.util.AttributeSet;

import android.webkit.WebView;

public class MyWebView extends WebView

{

public MyWebView(Context context) {

super(context);

// TODO Auto-generated constructor stub

}

public MyWebView(Context context, AttributeSet attrs) {

super(context, attrs);

// TODO Auto-generated constructor stub

}

public MyWebView(Context context, AttributeSet attrs,

int defStyle) {

super(context, attrs, defStyle);

// TODO Auto-generated constructor stub

}

public String stringByEvaluatingJavascriptFromString(String

script) {

try {

//由webview取到webviewcore

Field field_webviewcore =

WebView.class.getDeclaredField("mWebViewCore");

field_webviewcore.setAccessible(true);

Object obj_webviewcore = field_webviewcore.get(this);

//由webviewcore取到BrowserFrame

Field field_BrowserFrame =

obj_webviewcore.getClass().getDeclaredField("mBrowserFrame");

field_BrowserFrame.setAccessible(true);

Object obj_frame =

field_BrowserFrame.get(obj_webviewcore);

//获取BrowserFrame对象的stringByEvaluatingJavascriptFromString方法

Method method_stringByEvaluatingJavascriptFromString =

obj_frame.getClass().getMethod("stringByEvaluatingJavascriptFromString",

String.class);

//执行stringByEvaluatingJavascriptFromString方法

Object obj_value =

method_stringByEvaluatingJavascriptFromString.invoke(obj_frame,

script);

//返回执行结果

return String.valueOf(obj_value);

} catch (SecurityException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (NoSuchFieldException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalArgumentExceptione) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalAccessException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (NoSuchMethodException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (InvocationTargetException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return null;

}

}

Layout:

encoding="utf-8"?>

xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

android:id="@+id/button1"

android:layout_width="wrap_content"

android:layout_height="wrap_content">

android:id="@+id/webView1"

android:layout_width="fill_parent"

android:layout_height="fill_parent">

com.appeon.test.MyWebView>

被测试js:

var myvalue = "jjjjj";

function fun1() {

return "function return test";

}

测试代码:

class WebViewListener extends WebViewClient

{

@Override

public void onPageFinished(WebView view ,String url)

{

//页面内容载入完成时执行

Toast.makeText(AndroidSampleActivity.this,web.stringByEvaluatingJavascriptFromString("myvalue"),Toast.LENGTH_SHORT).show();

}

}

代码中的web为MyWebView的对象:

web = (MyWebView)this.findViewById(R.id.webView1);

除了采用反射方式能访问到私有类BrowserFrame中的stringByEvaluatingJavascriptFromString方法之外,采用JNI技术,也能做到;下面我们采用JNI技术来实现20.4.1中的MyWebView类。

原理:java->C->java,具体到这里就是mywebview.java调用bridge.c,bridge.c再调用BrowserFrame.java

MyWebView.java:

package com.example.hellojni;

import android.content.Context;

import android.util.AttributeSet;

import android.webkit.WebView;

public class MyWebView extends WebView {

public MyWebView(Context context) {

super(context);

// TODO Auto-generated constructor stub

}

public MyWebView(Context context, AttributeSet attrs) {

super(context, attrs);

// TODO Auto-generated constructor stub

}

public MyWebView(Context context, AttributeSet attrs, int defStyle)

{

super(context, attrs, defStyle);

// TODO Auto-generated constructor stub

}

public native String stringByEvaluatingJavascriptFromString(String

script);

static {

System.loadLibrary("bridge");

}

}

bridge.c:

#include

#include

#include

jstring

Java_com_example_hellojni_MyWebView_stringByEvaluatingJavascriptFromString(

JNIEnv* env,jobject thiz,jstring script )

{

//---------------------c调用java测试------------------------------------

jstring

str = NULL;

//由webview获取webviewcore

jclass

class_webview = (*env)->GetObjectClass(env,

thiz);

jfieldID

fid_WebViewCore = (*env)->GetFieldID(env,

class_webview, "mWebViewCore",

"Landroid/webkit/WebViewCore;");

jobject

obj_WebViewCore = (*env)->GetObjectField(env,thiz,

fid_WebViewCore);

//由webviewcore获取webframe

jclass

class_webviewcore = (*env)->FindClass(env,

"android/webkit/WebViewCore");

jfieldID

fid_frame = (*env)->GetFieldID(env,

class_webviewcore, "mBrowserFrame",

"Landroid/webkit/BrowserFrame;");

jobject

obj_frame =

(*env)->GetObjectField(env,obj_WebViewCore,

fid_frame);

//获取webframe的stringByEvaluatingJavascriptFromString方法ID

jclass

class_webframe = (*env)->FindClass(env,

"android/webkit/BrowserFrame");

jmethodID

mid = (*env)->GetMethodID(env, class_webframe,

"stringByEvaluatingJavascriptFromString",

"(Ljava/lang/String;)Ljava/lang/String;");

if

(mid) {

//执行webframe对象的stringByEvaluatingJavascriptFromString方法

str = (*env)->CallObjectMethod(env, obj_frame, mid,

script);

}

//返回执行结果

return

str;//(*env)->NewStringUTF(env,

str);

//------------------------------------------------------------

}

Android.mk添加如下代码:

#-----------------------定义bridge共享库的编译(c)------------------

LOCAL_CPP_EXTENSION := .c

include $(CLEAR_VARS)

LOCAL_MODULE := bridge

LOCAL_SRC_FILES := bridge.c

include $(BUILD_SHARED_LIBRARY)

*****************************************************************

至此,我们实现了mywebview,并为mywebview定义了本地方法和该本地方法的c语言实现,在c语言的具体实现时,又采用jni技术,调用了private类型的BrowserFrame对象中的native类型的stringByEvaluatingJavascriptFromString方法。

剩下的就是如何使用mywebview定义布局了(静态或动态),具体实现和20.4.1一样。

注意:jni的实现,可以借助NDK框架来简化开发,具体实现参看22节《JNI和NDK》,本例中采用的就是NDK框架,如果不采用NDK也可实现,但原理不变。

在bridge.c中,注意方法的命名,必须是包名+类名+方法名,类名和包名分别对应定义native方法的类和所在的包名称。

*****************************************************************

20.4.3扩展webkit方式

researching

直接扩展WebCore,扩展JSBridge,实现JS的数据类型到JAVA数据类型的转换,确切的说是相互转换,这里面JAVA部分可以用反射机制来做到。

Researching

采用插件的方式实现。



推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • OO第一单元自白:简单多项式导函数的设计与bug分析
    本文介绍了作者在学习OO的第一次作业中所遇到的问题及其解决方案。作者通过建立Multinomial和Monomial两个类来实现多项式和单项式,并通过append方法将单项式组合为多项式,并在此过程中合并同类项。作者还介绍了单项式和多项式的求导方法,并解释了如何利用正则表达式提取各个单项式并进行求导。同时,作者还对自己在输入合法性判断上的不足进行了bug分析,指出了自己在处理指数情况时出现的问题,并总结了被hack的原因。 ... [详细]
  • 利用空间换时间减少时间复杂度以及以C语言字符串处理为例减少空间复杂度
    在处理字符串的过程当中,通常情况下都会逐个遍历整个字符串数组,在多个字符串的处理中,处理不同,时间复杂度不同,这里通过利用空间换时间等不同方法,以字符串处理为例来讨论几种情况:1: ... [详细]
  • 初探PLC 的ST 语言转换成C++ 的方法
    自动控制软件绕不开ST(StructureText)语言。它是IEC61131-3标准中唯一的一个高级语言。目前,大多数PLC产品支持ST ... [详细]
author-avatar
卖火柴的杜拉拉
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有