Android中JavaScript和Native之间的Bridge

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

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

[b](1)addJavascriptInterface/@JavascriptInterface[/b]
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();
});

[img]http://dl2.iteye.com/upload/attachment/0095/9619/ee1f6ed4-53a2-342d-86fa-5e65da202e70.png[/img]

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:
[img]http://dl2.iteye.com/upload/attachment/0095/9621/6b9d72a0-a9bd-398b-9018-1ecb43ea5d0f.png[/img]

[b](2)自定义URL[/b]

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';
});

[img]http://dl2.iteye.com/upload/attachment/0095/9623/9f068fbf-6cf4-3913-83b6-97dee83619a3.png[/img]

[b](3)JsAlert[/b]

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");
});

[img]http://dl2.iteye.com/upload/attachment/0095/9625/a7217c91-7717-3d57-be49-b92ecbe42070.png[/img]

[b](4)搭建本地HTTP服务器[/b]

[url=https://github.com/NanoHttpd/nanohttpd]NanoHttpd[/url] 是一个轻量级的可嵌入的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"/>


[img]http://dl2.iteye.com/upload/attachment/0095/9627/64c0f659-d220-3428-a8ca-0d5fd6639441.png[/img]
[img]http://dl2.iteye.com/upload/attachment/0095/9629/4f2f6de5-ce71-35b4-8afa-6d8a57de425e.png[/img]

[color=red]还有一种方法,通过URL的变更也能够实现,但是存在安全问题,基本不使用![/color]
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); // 截取参数处理
}
}
}


参考:
[url=http://www.buildinsider.net/mobile/bookhtml5hybrid]http://www.buildinsider.net/mobile/bookhtml5hybrid[/url]
React-Native系列Android——NativeJavascript通信原理(一) React-Native最核心的是NativeJavascript之间的通信,而且是双向通信,Native层到Javascript层,Javascript层到Native层,虽说是两个方向,但实现上大同小异,我们先从Native层入手,研究一下Native调用Javascript的过程。1、通信模型Android应用层的程序语言是Java,React-NativeNative端的框架实现用的也是 阅读详情

相关推荐

React-Native系列Android——NativeJavascript通信原理(三)

前面两篇博客,详细分析了NativeJavascript通信的过程,可以满足绝大部分场景下NativeJavascript的相互调用,但是仍然有不健全的情况。比如Native被动地向Javascript层通信了,本篇博客就来研究下这样一个被动回调的过程!

MegatronKings的博客 5444

WHAT - Hybrid App 详解系列(一)

Hybrid App 是一种移动应用程序类型,它结合了原生应用Web应用的元素。这些应用是使用HTML、CSSJavaScript等Web技术构建的,但它们被包装在一个原生容器中,允许它们像原生应用一样被安装移动设备上运行。开发 Hybrid app 有如下优势:跨平台兼容、访问设别功能、开发速度快、易于更新。

weixin_58540586的博客 2455

React Native Android 源码框架浅析(主流程及 Java 与 JS 双边通信)

}…try {//创建CoreModulesPackage(ReactPackage),RN framework的核心Module Package,主要通过createNativeModules、createJSModulescreateViewManagers等方法创建本地模块,JS模块及视图组件等。//CoreModulesPackage封装了通信、调试等核心类。CoreModulesPackage coreModulesPackage =new CoreModulesPackage(this, mB

2401_84874256的博客 954

webview 转义字符_Android WebView交互传递json字符串并解析的方法

前言我们大家都知道WebView交互中可以传递基本数据类型的数据值,比如常用的int,String.但是WebView也可以传递一种很重要很常用的数据格式-json数据.传递json传递String数据是一样的,关键就是HTML5端对json数据通过eval()函数进行解析传递过程中android端调用的最重要的一个函数就是:addJavascriptInterface(new MyObject...

weixin_39609407的博客 710

androidnative_bridge

开门见山。native_bridge就是让不同指令集能够运行。这里主要是在X86上跑ARM后续的均以android6.0为例在加载so文件的时候。最后调用到了art/runtime/java_vm_ext.cc当中的JavaVMExt::LoadNativeLibrary void* handle = dlopen(path_str, RTLD_NOW); bool needs_native...

groundhappy的专栏 5206

Android jsnative交互的两种方法

本博客解决的问题是Android本地方法webview中js方法交互,方法一是使用的是Android自身js注解,方法二是开源库jockeyjs。方法一:js注解先上js脚本(代码来自网络):<html> <head> <meta http-equiv="Content-Type" content="text/html;charset=gb2312"> <script type="text/

Ethan的博客 5150

JS Bridge实现,近期想跳槽的程序员必看

============== JS Bridge实际上就是一段JS代码,里面封装好H5访问原生的方法,原生访问H5的方法,即可作为一个“桥”架在 H5 原生 中间。 2 JS Bridge技术实现 要实现JS Bridge,我们需要按以下步骤进行: (注:本篇文章基于Android6以上,以阐述原理为主) 第一步:定义一个Native与JS交互的全局桥对象 第二步:JS调用Native 第三步:Native接收JS传递过来的参数 第四步:Native返回数据给JS 第五步:JS接收原生传递过来的参

m0_64319455的博客 972

React-Native系列Android——NativeJavascript通信原理(二)

前一篇博客分析了Native端向Javascript端通信的全流程,这次来研究下Javascript端向Native端通信的全流程,与前篇恰好构成一个基本完整的通信机制。

MegatronKings的博客 1万+

Android Smart WebView JS Bridge深度解析:如何实现JavaScript与原生Android的双向通信

Android Smart WebView 是一款内置 JS Bridge 双向通信机制的混合应用开发框架。它通过 `JSInterfacePlugin` 插件让 JavaScript 代码调用原生 Android 能力(剪贴板、定位、分享、生物识别等),同时支持原生侧向网页注入事件回调,真正实现 JavaScript 与原生 Android 的双向通信。本文带你完整拆解这套 JS Bridge

gitblog_00023的博客 1051

深入解析React Native通信机制:JS与Native双向通信原理完全指南

React Native作为跨平台移动应用开发框架,其核心优势在于JavaScript与原生平台之间的高效通信机制。本文将详细解析React Native通信机制原理,帮助开发者深入理解JS与Native之间的双向通信流程,掌握React Native核心工作原理,提升应用开发效率与性能优化能力。😊 ## 🔍 React Native通信机制概述 React Native的通信机制是整个框

gitblog_00670的博客 704

React Native混合开发终极指南:如何与原生Android/iOS代码高效交互

React Native混合开发移动应用开发中的重要技术,它允许开发者在JavaScript代码中调用原生AndroidiOS功能,实现跨平台开发的灵活性原生性能的完美结合。React Native与原生代码的交互机制通过桥接技术实现,让开发者能够充分利用原生平台的能力,同时保持React Native开发效率。 ## 🔗 React Native混合开发的核心概念 React Na

gitblog_00080的博客 1110

Capacitor Native Bridge详解:JavaScript与原生代码通信机制

在跨平台应用开发中,JavaScript(JS)与原生代码(Native Code)的通信是核心挑战。传统WebView仅能加载网页,而Capacitor通过**Native Bridge(原生桥接器)** 实现了JS与iOS/Android原生API的双向通信,让Web技术能调用摄像头、文件系统等设备能力。本文将深入解析Capacitor Native Bridge的架构设计、通信流程及关键技术...

gitblog_00897的博客 891

Electrode Native与原生应用通信指南:JS-Native交互最佳实践

Electrode Native是一个强大的移动平台,专为简化React Native功能在现有原生移动应用中的集成交付而设计。通过Electrode Native开发者可以轻松实现JavaScript与原生代码之间的无缝通信,构建高效、可维护的混合应用架构。本文将为您提供完整的Electrode Native通信指南,涵盖核心概念、最佳实践实用技巧,帮助您快速掌握JS-Native交互的关

gitblog_00231的博客 342

React Native Bridge原理详解:从异步通信到JSI新架构

在跨平台移动开发中,JavaScript与原生代码之间的通信机制始终是核心挑战。由于线程安全内存隔离的约束,JS与原生无法直接互相调用,必须依赖异步消息传递。React Native中的Bridge正是这一机制的经典实现,它通过消息队列与序列化完成跨运行时协作,但也由此带来了启动白屏性能瓶颈。为解决这些问题,新架构引入JSI与TurboModules,以共享引用替代消息复制,大幅降低通信开销。理解Bridge的设计原理与演进路径,不仅有助于应对React Native面试中的高频问题,更能为老项目性能优

weixin_33801856的博客 659

React Native 原生桥接开发的效率革命:react-native-create-bridge 技术深度解析

在 React Native 生态系统中,原生模块桥接一直是开发者必须面对的技术挑战。当我们需要集成第三方支付 SDK、访问硬件传感器或创建自定义原生 UI 组件时,传统的手动桥接方式往往成为开发流程中的瓶颈。react-native-create-bridge 正是为了解决这一痛点而生的 CLI 工具,它通过自动化代码生成,将原本需要数小时甚至数天的桥接工作简化为几分钟的交互式体验。 ## 传

gitblog_07884的博客 458

React Native WebView JavaScript Bridge 推荐文章

React Native WebView JavaScript Bridge 是一个强大的开源项目,旨在为 React Native 开发者提供一个安全、高效的桥梁,以便在 React Native 应用 WebView 之间进行通信。该项目自 React Native 0.20 版本起完全支持,并且已经过广泛的测试验证。 ## 项目技术分析 React Native WebView Ja...

gitblog_00453的博客 528

Ios Android Hybrid app 与 Js Bridge

移动开发中,我们必不可少需要使用Web来代替部分Native,也就是业内所说的Hybrid App。 一、基本信息介绍 Ios Android两种终端与Javascript的通信机制有些不同: 1. Ios 机制:  (1)Native可直接调用Js,并可直接获取Js的返回值(这点与Android不同)  (2)Js不能直接调用Native,但可以通过反向调用,流程就是先将消息临时

左手 4914
上一篇: Cordova 3.x 实用插件(4) -- Android的SEND、VIEW、CALL(WebIntent)
下一篇: Java 8 之 反编译Lambda表达式(CFR)
wayne_ren
博客等级 码龄21年 60粉丝 300原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值