为什么手机浏览器或者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
分享到:
相关推荐
本教程通过"Android和React Native混合开发Demo",将详细介绍如何在Android应用中集成React Native,实现原生代码与React Native组件之间的双向通信。 首先,Android原生加载RN页面是混合开发的基础。这涉及到在...
在Android项目中集成React Native页面是一项常见的开发任务,它允许开发者利用JavaScript和React库来创建原生移动应用的UI部分,同时保持与Android代码的交互。以下是对这个过程的详细解释: 1. **React Native简介...
ReactNative是一种由Facebook开发的开源框架,它允许开发者使用JavaScript和React库来构建原生的移动应用程序,同时兼容iOS和Android平台。ReactNative的核心理念是“Learn once, write anywhere”,这意味着开发者...
React Native Event Bridge是React Native框架中的一个重要组成部分,它允许JavaScript(JS)代码与原生iOS或Android代码之间进行通信,从而实现更高效、更复杂的交互。这个技术在混合移动开发中扮演着关键角色,...
在移动应用开发中,Android平台和JavaScript的交互是常见的需求,尤其在混合开发模式下,如Cordova或React Native。本文将深入探讨如何实现Android与JavaScript的双向交互,以达到充分利用两者的优势,提高开发效率...
通信数据模型在React-Native架构中扮演着至关重要的角色,因为它决定了JavaScript与原生平台(如Java for Android)之间如何高效、安全地交换数据。本文将深入探讨Android环境下React-Native的通信数据模型。 首先...
在React Native中,JavaScript和Native代码之间通过Bridge通信,这是一个异步过程,提高了应用的性能。开发者可以使用JavaScript处理业务逻辑和数据管理,而将视觉渲染和与硬件交互的任务留给原生模块。这使得React ...
在Android原生项目中集成最新版本的React Native是一项常见的任务,尤其对于希望利用React Native的JavaScript开发优势同时保持原生性能的应用来说。本教程将详细指导你如何将React Native逐步集成到你的Android应用...
4. **JavaScript Bridge**:React Native的JavaScript和Java/Kotlin之间的通信是通过JavaScript Bridge实现的。在这个场景下,桥接机制允许自定义的Android模块向JavaScript发送数据(如选中的文件路径),从而让...
React Native 是一个由Facebook开发的开源框架,它允许开发者使用JavaScript和React库来构建原生的iOS和Android应用程序。在某些场景下,尽管React Native提供了丰富的组件和功能,但为了实现特定的设备交互、优化...
React Native是一种使用JavaScript(通常配合TypeScript)编写原生移动应用的框架,它通过JavaScript Bridge与Android和iOS平台进行通信。但是,JavaScript环境并不支持长时间在后台运行的任务,因为当用户离开应用...
在移动应用开发领域,React Native 是一个非常流行的框架,它允许开发者使用JavaScript来构建原生的iOS和Android应用程序。在Android应用中集成支付宝支付功能,是很多开发者在处理电子商务或服务付费场景时需要解决...
在这个过程中,我们通常会创建一个Java或Kotlin类来封装原生API,然后通过React Native的Bridge机制暴露给JavaScript。 1. **创建Android原生模块** 要创建一个原生模块,首先在Android工程的`java`目录下创建一个...
- **WebViewBridge**:WebViewBridge是Android中用于通信的关键组件,它通常由两部分组成:JavaScript接口和Java接口。JavaScript接口暴露给H5,Java接口则在原生端实现具体功能。 - **调用方向**: - **H5调用...
综上所述,Android JS Bridge是Android开发中的一个重要工具,它使得Java和JavaScript的交互变得更加简单和高效,为混合应用开发提供了可能。通过合理的设计和实现,我们可以充分利用这一特性来提高应用的灵活性和可...
如果可以,那就需要一种在 JavaScript 和 Native 之间通信的桥梁(JavaScript Bridge),通过它,JavaScript 将请求信息传递给 Native,Native 完成真正的请求后再将结果数据传递给 JavaScript。 思路虽然简单,但...
首先,ReactNative(RN)是一个由Facebook开发的开源JavaScript框架,它允许开发者使用JavaScript和React编写原生移动应用。RN通过桥接机制与原生平台进行交互,提供了丰富的API和组件库。在处理横竖屏切换这样的...
2. **JavaScript与Native交互**:React Native允许JavaScript与原生平台之间进行通信,通过`Native Modules`和`Bridge`机制实现。理解这一过程对于定制或扩展组件至关重要。 3. **ListView组件**:深入理解ListView...