`
rensanning
  • 浏览: 3512756 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
Efef1dba-f7dd-3931-8a61-8e1c76c3e39f
使用Titanium Mo...
浏览量:37457
Bbab2146-6e1d-3c50-acd6-c8bae29e307d
Cordova 3.x入门...
浏览量:604220
C08766e7-8a33-3f9b-9155-654af05c3484
常用Java开源Libra...
浏览量:677887
77063fb3-0ee7-3bfa-9c72-2a0234ebf83e
搭建 CentOS 6 服...
浏览量:87192
E40e5e76-1f3b-398e-b6a6-dc9cfbb38156
Spring Boot 入...
浏览量:399741
Abe39461-b089-344f-99fa-cdfbddea0e18
基于Spring Secu...
浏览量:69042
66a41a70-fdf0-3dc9-aa31-19b7e8b24672
MQTT入门
浏览量:90419
社区版块
存档分类
最新评论

Android中JavaScript和Native之间的Bridge

 
阅读更多
为什么手机浏览器或者WebView中不能执行JavaScript调用本地API,而在HTML5混合式应用中却能执行?

JavaScript调用本地API大概有4种方法:

(1)addJavascriptInterface/@JavascriptInterface
Android的WebView类的标准接口。
webView.addJavascriptInterface(new JSHandler(this), "Bridge");

class JSHandler {
	public Context context;
	
	public JSHandler(Context c) {
		this.context = c;
	}

	public void doSomething() {
		Log.d("JSHandler", "doSomething@JSHandler");
		Toast.makeText(this.context, "doSomething@JSHandler", Toast.LENGTH_LONG).show();
	}
}

addJavascriptInterface()方法的第一个参数就是要暴露给JavaScript的Class对象,第二个参数是可以调动该Class方法的JavaScript的全局变量。

$(function() {
	Bridge.doSomething();
});


但是addJavascriptInterface()方法存在安全隐患,在JavaScript中可以反射调用到Class的任意属性,比如以下代码能够取到Activity的package名。
$(function() {  
	var klass = Bridge.getClass();
	var field = klass.getDeclaredField('context');
	field.setAccessible(true);
	var context = field.get(Bridge);
	document.getElementById('res').innerHTML = context.getPackageName();
});



Android 4.2 Jelly Bean以后版本,只有标示了@JavascriptInterface的方法JavaScript才能调到。
webView.addJavascriptInterface(new MyCustomHander(this), "Bridge");

class MyCustomHander {
	public Context context;
	
	public MyCustomHander(Context c) {
		this.context = c;
	}
	
	@JavascriptInterface
	public void doSomething() {
		Log.d("MyCustomHander", "doSomething@MyCustomHander");
		Toast.makeText(this.context, "doSomething@MyCustomHander", Toast.LENGTH_LONG).show();
	}
	
	public void doSomething2() {
		Log.d("MyCustomHander", "doSomething2@MyCustomHander");
		Toast.makeText(this.context, "doSomething2@MyCustomHander", Toast.LENGTH_LONG).show();
	}
}


Android 4.2以前版本看到的是:"doSomething2@MyCustomHander",而Android 4.2以后版本看到的是:"doSomething@MyCustomHander"。
比如Android 4.1:


(2)自定义URL

webView.setWebViewClient(new WebViewClient() {
	@Override
	public boolean shouldOverrideUrlLoading(WebView view, String url) {
		if (url.startsWith("apicall://")) {
			Log.d("MyWebViewClient", "doSomething@WebViewClient: " + url);
			Toast.makeText(getBaseContext(), "doSomething@WebViewClient: " + url, Toast.LENGTH_LONG).show();
			return true;
		}
		return false;
	}
});


$(function() {
  window.location = 'apicall:////some_api_name/exec?a=1&b=2';
});



(3)JsAlert

webView.setWebChromeClient(new WebChromeClient() {
	@Override
	public boolean onJsAlert(WebView view, String url,
			String message, JsResult result) {
		Log.d("MyWebChromeClient", "doSomething@WebChromeClient: " + message);
		Toast.makeText(getBaseContext(), "doSomething@WebChromeClient: " + message, Toast.LENGTH_LONG).show();
		// return super.onJsAlert(view, url, message, result);
		return true;
	}
});


$(function() {
  alert("123");
});



(4)搭建本地HTTP服务器

NanoHttpd 是一个轻量级的可嵌入的HTTP服务器。
public class APIHttpServer extends NanoHTTPD {

	public APIHttpServer() {
		super(4000);
	}

	@Override
	public Response serve(String uri, Method method,
			Map<String, String> headers, Map<String, String> params,
			Map<String, String> files) {

		String data = "uri=" + uri + ", params=" + params;
		Log.d("APIHttpServer", "doSomething@APIHttpServer: " + data);

		return new NanoHTTPD.Response(Status.OK, "application/json", "{msg:'nano'}");
	}
}

APIHttpServer server = new APIHttpServer();
server.start();


$(function() {
  $.getJSON("http://localhost:4000/some_api_name?a=1&b=2&c=3");
});


AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>





还有一种方法,通过URL的变更也能够实现,但是存在安全问题,基本不使用!
window.location = 'http://cdv_exec/' + service + '#' + action + '#' + callbackId + '#' + argsJson;

public class MyWebViewClient extends WebViewClient {
  public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (url.startsWith("http://cdv_exec/")) {
      handleExecUrl(url); // 截取参数处理
    }
  }
}


参考:
http://www.buildinsider.net/mobile/bookhtml5hybrid
  • 大小: 49.3 KB
  • 大小: 21.9 KB
  • 大小: 18.8 KB
  • 大小: 19.9 KB
  • 大小: 13.3 KB
  • 大小: 11 KB
  • 大小: 3 KB
分享到:
评论

相关推荐

    英文原版-Building Hybrid Android Apps with Java and JavaScript 1st Edition

    Applying Native Device APIsBuild HTML5-based hybrid applications for Android with a mix of native Java and JavaScript components, without using third-party libraries and wrappers such as PhoneGap or ...

    Android代码-DSBridge-Android

    &gt;Modern cross-platform JavaScript bridge, through which you can invoke each other's functions synchronously or asynchronously between JavaScript and native applications. Chinese documentation 中文文档...

    react-native-create-bridge:一个可轻松桥接React Native模块和UI组件的CLI工具

    如果您是写第一行本机代码JavaScript开发人员,或者是经验丰富的开发人员希望从React Native工作流程中消除样板,那么此工具非常适合您。 想要的贡献者 入门 npm install --save react-native-create-bridge或yarn ...

    react-native-the-native-parts-android:在Android平台上使用React Native的本机部分的示例用法

    React Native:原生部分(Android版) 一个演示应用程序,展示如何: 将React Native嵌入到现有应用程序中 实施自定义本机组件 从JavaScript调用本机方法 从本地触发JavaScript方法 如何运行 克隆存储库 git clone...

    腾讯x5webview和JS交互的三方库-Android开发

    X5Bridge X5Bridge Android本机和JavaScript之间的桥梁的库Google本机具有一组通信,实际上,它也可以完成回调交互i X5Bridge X5Bridge Android本机和JavaScript之间的桥梁的库一组通信,实际上,它也可以完成回调...

    Android React-Native通信数据模型分析

    无论是计算机领域还是日常生活中,我们所言的通信,其核心都是数据信息的交换,而...前面几篇博客我们详细分析过React-Native的通信机制,主要有两个方向: Java-&gt;Bridge-&gt;Javascript和Javascript-&gt;Bridge-&gt;Java。所

    noName:了解和监控React Native桥

    在android的情况下,该桥在JS和Java之间建立链接,在IOS的情况下,在JS和Swift之间建立链接。 在此网桥中导航的消息为JSON格式。 它们具有4个属性:类型,模块,方法和参数(args) 然后,该应用程序将允许您在...

    RNWebViewExample:React-native-webview

    ios# for androidreact - native run - androidWebView 和自定义导航来处理 WebView 中的导航如何将数据从 WebView 传递给 React Native如何将数据从 React Native 传递到 WebView更详细的解释

    JSBridge::rocket:适用于Android iOS的JSBridge

    JSBridge For Android / iOS,统一易用的Javascript bridge。 需配合及使用 安装 npm $ npm i --save @hackycy/jsbridge cdn &lt;!-- production --&gt; [removed][removed] 将${version}改为可用版本号 使用 异步...

    bridge:淘宝旅行客户端Hybrid桥协议

    Native2H5mClient协议约定及优先级梳理 v0.1OverviewH5 WebView特性方法客户端协议接口约定(握手通讯)客户端页面跳转及跳转拦截客户端唤醒(调研总结)降级方案(页面生存环境自适应)面向Android和iOS的JS调用...

    GCanvas:轻型跨平台图形渲染引擎。 (超轻量的跨平台图形引擎)https:alibaba.github.ioGCanvas

    GCanvas是由阿里巴巴开发的用于移动设备的跨平台渲染引擎。 它是使用基于OpenGL ES的C ++编写的,因此可以为JavaScript运行时提供高... 并且将不会进一步更新和支持Weex , ReactNative和JS bridge 。节点遵循 ,在No

    JavaScript的React Web库的理念剖析及基础上手指南

    React Web的目的及意义非常明确: 让React Native代码跑在Web上 让一套代码运行在各个移动终端,对前端及业务来说,这是开发效率中一个质的提升。在项目初期,我们也曾向 React团队咨询过类似的问题,他们团队的核心...

    java开源包1

    Pinyin4j是一个流行的Java库,支持中文字符和拼音之间的转换。拼音输出格式可以定制。 异步HTTP客户端开发包 HttpAsyncClient HttpAsyncClient 是一个异步的 HTTP 客户端开发包,基于 HttpCore NIO 和 HttpClient ...

    java开源包11

    Pinyin4j是一个流行的Java库,支持中文字符和拼音之间的转换。拼音输出格式可以定制。 异步HTTP客户端开发包 HttpAsyncClient HttpAsyncClient 是一个异步的 HTTP 客户端开发包,基于 HttpCore NIO 和 HttpClient ...

    java开源包2

    Pinyin4j是一个流行的Java库,支持中文字符和拼音之间的转换。拼音输出格式可以定制。 异步HTTP客户端开发包 HttpAsyncClient HttpAsyncClient 是一个异步的 HTTP 客户端开发包,基于 HttpCore NIO 和 HttpClient ...

    java开源包3

    Pinyin4j是一个流行的Java库,支持中文字符和拼音之间的转换。拼音输出格式可以定制。 异步HTTP客户端开发包 HttpAsyncClient HttpAsyncClient 是一个异步的 HTTP 客户端开发包,基于 HttpCore NIO 和 HttpClient ...

    java开源包6

    Pinyin4j是一个流行的Java库,支持中文字符和拼音之间的转换。拼音输出格式可以定制。 异步HTTP客户端开发包 HttpAsyncClient HttpAsyncClient 是一个异步的 HTTP 客户端开发包,基于 HttpCore NIO 和 HttpClient ...

    java开源包5

    Pinyin4j是一个流行的Java库,支持中文字符和拼音之间的转换。拼音输出格式可以定制。 异步HTTP客户端开发包 HttpAsyncClient HttpAsyncClient 是一个异步的 HTTP 客户端开发包,基于 HttpCore NIO 和 HttpClient ...

    java开源包10

    Pinyin4j是一个流行的Java库,支持中文字符和拼音之间的转换。拼音输出格式可以定制。 异步HTTP客户端开发包 HttpAsyncClient HttpAsyncClient 是一个异步的 HTTP 客户端开发包,基于 HttpCore NIO 和 HttpClient ...

Global site tag (gtag.js) - Google Analytics