Android中JavaScript和Native之間的Bridge
原文地址:http://rensanning.iteye.com/blog/2043049
為什麼手機瀏覽器或者WebView中不能執行JavaScript呼叫本地API,而在HTML5混合式應用中卻能執行?
JavaScript呼叫本地API大概有4種方法:
(1)addJavascriptInterface/@JavascriptInterface
Android的WebView類的標準介面。
Java程式碼
- webView.addJavascriptInterface(new JSHandler(this), "Bridge");
- class JSHandler {
-
public
- public JSHandler(Context c) {
- this.context = c;
- }
- public void doSomething() {
- Log.d("JSHandler", "[email protected]");
- Toast.makeText(this.context, "[email protected]", Toast.LENGTH_LONG).show();
- }
- }
addJavascriptInterface()方法的第一個引數就是要暴露給JavaScript的Class物件,第二個引數是可以調動該Class方法的JavaScript的全域性變數。
Js程式碼
- $(function() {
- Bridge.doSomething();
- });
但是addJavascriptInterface()方法存在安全隱患,在JavaScript中可以反射呼叫到Class的任意屬性,比如以下程式碼能夠取到Activity的package名。
Js程式碼
- $(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才能調到。
Java程式碼
- 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", "[email protected]");
- Toast.makeText(this.context, "[email protected]", Toast.LENGTH_LONG).show();
- }
- public void doSomething2() {
- Log.d("MyCustomHander", "[email protected]");
- Toast.makeText(this.context, "[email protected]", Toast.LENGTH_LONG).show();
- }
- }
Android 4.2以前版本看到的是:"[email protected]",而Android 4.2以後版本看到的是:"[email protected]"。
比如Android 4.1:
(2)自定義URL
Java程式碼
- webView.setWebViewClient(new WebViewClient() {
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- if (url.startsWith("apicall://")) {
- Log.d("MyWebViewClient", "[email protected]: " + url);
- Toast.makeText(getBaseContext(), "[email protected]: " + url, Toast.LENGTH_LONG).show();
- return true;
- }
- return false;
- }
- });
Js程式碼
- $(function() {
- window.location = 'apicall:////some_api_name/exec?a=1&b=2';
- });
(3)JsAlert
Java程式碼
- webView.setWebChromeClient(new WebChromeClient() {
- @Override
- public boolean onJsAlert(WebView view, String url,
- String message, JsResult result) {
- Log.d("MyWebChromeClient", "[email protected]: " + message);
- Toast.makeText(getBaseContext(), "[email protected]: " + message, Toast.LENGTH_LONG).show();
- // return super.onJsAlert(view, url, message, result);
- return true;
- }
- });
Js程式碼
- $(function() {
- alert("123");
- });
(4)搭建本地HTTP伺服器
NanoHttpd 是一個輕量級的可嵌入的HTTP伺服器。
Java程式碼
- 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", "[email protected]: " + data);
- return new NanoHTTPD.Response(Status.OK, "application/json", "{msg:'nano'}");
- }
- }
- APIHttpServer server = new APIHttpServer();
- server.start();
Js程式碼
- $(function() {
- $.getJSON("http://localhost:4000/some_api_name?a=1&b=2&c=3");
- });
AndroidManifest.xml
Xml程式碼
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
- <uses-permission android:name="android.permission.INTERNET"/>
還有一種方法,通過URL的變更也能夠實現,但是存在安全問題,基本不使用!
Js程式碼
- window.location = 'http://cdv_exec/' + service + '#' + action + '#' + callbackId + '#' + argsJson;
Java程式碼
- 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
相關推薦
Android中JavaScript和Native之間的Bridge
原文地址:http://rensanning.iteye.com/blog/2043049 為什麼手機瀏覽器或者WebView中不能執行JavaScript呼叫本地API,而在HTML5混合式應用中卻能執行? JavaScript呼叫本地API大概有4種方法: (1)
Android中dp和px之間進行轉換
在xml佈局檔案中,我們既可以設定px,也可以設定dp(或者dip)。一般情況下,我們都會選擇使用dp,這樣可以保證不同螢幕解析度的機器上佈局一致。但是在程式碼中,如何處理呢?很多控制元件的方法中都只提供了設定px的方法,例如setPadding,並沒有提供設定dp的方法。
Android 中Service 和Activity之間傳值。(涉及BroadCast的基本用法)
首先先建立一個Android工程(名字自定義)這裡我命名為MyActivity 包名為:package org.hm.myactivity; 再最後給自己的activity命名(名字自定義)此處我命名為MyTestActivity public class MyTestA
Android中Java和JavaScript互動 Android原生和html互動
1.WebView開啟JavaScript指令碼執行 WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); 2.WebView設定
Android中getDrawable和getColor過時的替代方法
this logs con 知識 log launcher 16px ase spa 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 前言 Android SDK 升級到 23 之後,getDrawable和getColor方法提示過時。 解決方案 getRe
Android 單位dp和px之間相互轉換
style pan static float logs ati col return roi public class DensityUtil { /** * 根據手機的分辨率從 dp 的單位 轉成為 px(像素) */
Android中 Bitmap和Drawable相互轉換的方法
canvas board null height .com factory oar tool pla 1、Drawable --> Bitmap [java] view plain copy Bitmap drawable2Bitmap(Drawabl
關於Toolbar中navigationIcon和title之間距離及展開
boolean ionic code sin block max change nav 希望 關於Toolbar中navigationIcon和title之間距離及展開 問題緣起 在進行Coolcode項目的MyclassActivity中,我發現navigationI
Android中兩個Activity之間簡單通信
idg tin test ide button ima 接收 9.png set 在Android中,一個界面被稱為一個activity,在兩個界面之間通信,采用的是使用一個中間傳話者(即Intent類)的模式,而不是直接通信。 下面演示如何實現兩個activity之間的通
Android中Gallery和ImageSwitcher同步自動(滾動)播放圖片庫
目標 art trac repl otto fin instance img com 本文主要內容是如何讓Gallery和ImageSwitcher控件能夠同步自動播放圖片集 ,看起來較難,然而,實現的方法非常簡單, 請跟我慢慢來。總的來說,本文要實現的效果如下圖:(截
【spring Boot】Spring中@Controller和@RestController之間的區別
處理 public 不同 esp 舉例 rest control tro adding spring Boot入手的第一天,看到例子中的@RestController ............. 相同點:都是用來表示Spring某個類的是否可以接收HTTP請求 不同點:@C
Android中RelativeLayout和LinearLayout性能分析
ant 顯示 二次 iou other comm 排列 vertica 簡單的 先看一些現象吧:用eclipse或者Android studio,新建一個Activity自動生成的布局文件都是RelativeLayout,或許你會認為這是IDE的默認設置問題,其實不然,
Android中Service和IntentService的差別
前言: ServiceTimeout(20 seconds)小概率型別Service在特定的時間內無法處理完成,會造成ANR — 應用程式無響應(ANR:Application Not Responding)的情況 ▲ 分析 : 避免ANR最核心的一點就是在主執行緒減少耗時操作。這時我們
30-python3 中 bytes 和 string 之間的互相轉換
轉自:http://www.jb51.net/article/105064.htm password = b'123456' 等價於: pw = '123456' password = pw.encode(encoding='utf-8') 前言
SpringMVC中@PathVariable和@RequestParam之間的區別
@PathVariable繫結URI模板變數值 @PathVariable是用來獲得請求url中的動態引數的 @PathVariable用於將請求URL中的模板變數對映到功能處理方法的引數上。//通俗來講配置url和方法的一個關係 @RequestMapping("/item/{item
Android中Serializable和Parcelable序列化物件詳解
學習內容: 1.序列化的目的 2.Android中序列化的兩種方式 3.Parcelable與Serializable的效能比較 4.Android中如何使用Parcelable進行序列化操作 5.Parcelable的工作原理 6.相關例項 1.序列化
java中String和date之間的互轉
1 Java時間格式轉換大全 2 3 import java.text.*; 4 import java.util.Calendar; 5 public class VeDate { 6 /** 7 * 獲取現在時間 8 * 9 * @ret
Unity中Sprite和Texture2D之間的關係。
Texture2D中包含多種型別的貼圖,比如normol map,default,sprite 等等。 當我們去切割精靈產生一張或多張資源的時候,就會產生sprite,如圖上面這個object的型別就是Texture2D,下面這個object就是sprite了,我們可以看 Selectio
Android 中src和background的區別
XML屬性中src和background的區別: src會存放原圖的大小,background會根據view的大小拉伸整張圖片。src是前景而background是背景。 可以使用scaleType屬性設定src(只對src起作用)的縮放方式。 詳細的scaleType說明: CEN
對於Qt中QString和char*之間的互相轉換問題(系列二)
對於Qt,雖說對C++全部相容,但是一旦涉及到和介面的資料的互動操作,難免涉及到char*和QString的轉換問題,轉換的過程很簡單,這裡總結了一下網上提供的最簡單的一個方法: 從char*轉成QString型別: 使用fromLocal8Bit方法進行轉換: char * te