安卓混合開發例項——JS與Java的互動
今天說說安卓混合開發。
曾經有一個話題是web終會一統app,然後我們看到隨著時間的推移。web越來越強大(H5啊,JS各種框架啊),但同時原生app也在不斷髮展。
或許在將來還會再有這種話題論戰,但目前,混合開發,結合web和原生app二者各自的優勢,已經是眾望所歸了。
其中最常見的一種方式,在安卓的webview中巢狀web,通過各類設計,讓二者進行互動。使得使用者體驗上幾乎無法分辨出究竟是否純原生。
這種方式最值得深入研究的就是,安卓中的java程式碼與web端的javascript程式碼進行相互互動呼叫。
簡單介紹一下背景知識:(Java和JavaScript)
說到java,作為目前(以及此前這麼多年來)最受青睞最有用武之地的語言,就不多介紹了。貼百科:
Java具有簡單性、面向物件、分散式、健壯性、安全性、平臺獨立與可移植性、多執行緒、動態性等特點[2] 。Java可以編寫桌面應用程式、Web應用程式、分散式系統和嵌入式系統應用程式等[3] 。
說到javascript。貼百科:JavaScript一種直譯式指令碼語言,是一種動態型別、弱型別、基於原型的語言,內建支援型別。它的直譯器被稱為JavaScript引擎,為瀏覽器的一部分,廣泛用於客戶端的指令碼語言,最早是在HTML(標準通用標記語言下的一個應用)網頁上使用,用來給HTML網頁增加動態功能。
這麼晦澀難懂? 那就簡單一句話,其實java和JavaScript,完全是兩碼事。前者是面向物件,後者是內建物件。且後者借鑑了前者,但二者並沒有關係.
好了,來到正題吧,先上效果圖。
圖中,
上半部分(藍色背景)是安卓中實現的簡單佈局
下半部分(白色背景)是一個webview,裡面的內容自然就是一個網頁。
但是我們看到,點選上半部分安卓中的檢視,能夠改變webview中網頁的檢視。
同樣,點選下半部分網頁中的Button,能夠呼叫安卓的Toast對話方塊。
這就是簡單的一個android與web互動,目前在安卓界普遍稱為JS互動
理論的東西講完了,接下來上程式碼:
今天的主角其實是兩方面:安卓和web,
但我們分為4個類:
1.index.html,這是一個簡單的web頁面。
2.activity_main.xml 安卓的佈局
3.MainActivity 安卓的主介面,同時也是本例的入口
4.JsInterface,這個類其實算幫助類,只是為了程式碼好看才抽出來
1.首先是index.html: web的佈局及函式 (注意,這個檔案要放在安卓的assets檔案下
<html>
<!-- 簡單寫,就省略了head -->
<body>
<script language="javascript">
//這個方法是與java事先商定的方法,讓java來呼叫
function java_call_Js(param) {
var x = document.getElementById('test');
x.innerHTML = "Hello , New text form java ! ------------>" + param;
}
//Html自身Button的方法,去呼叫Java
function btn_js() {
jsInterface.js_call_java();
}
</script>
<input type="button" onClick="btn_js()"
style="height: 60px; width: 240px; margin-top: 40px ; margin-bottom: 10px"
value="(JS call Java)I'm a Button in html">
<div id="test">
<font color="#FF0000">this is the old text</font>
</div>
</body>
2.其次是activity_main: 安卓的佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#336699"
android:gravity="center_vertical"
android:orientation="vertical" >
<EditText
android:id="@+id/text_edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入你想在html顯示的數字(不輸入引數會報空指標)"
android:inputType="number"
android:maxLength="7"
android:textColor="#ffffff" />
<Button
android:id="@+id/btn_java"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="java call js(I'm a Button in Android" />
</LinearLayout>
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
3.其三是MainActivity: 主要的邏輯程式碼
public class MainActivity extends Activity {
private EditText mEditText;
private Button mButton;
private WebView webview;
private JsInterface jsInterface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEditText = (EditText) findViewById(R.id.text_edit);
mButton = (Button) findViewById(R.id.btn_java);
webview = (WebView) findViewById(R.id.webview);
// 例項化介面JsInterface
jsInterface = new JsInterface(webview);
// 初始化WebSetting
initWebSetting();
webview.loadUrl("file:///android_asset/index.html");
}
@SuppressLint("SetJavaScriptEnabled")
private void initWebSetting() {
// 允許JS互動
webview.getSettings().setJavaScriptEnabled(true);
// 設定JS的介面
webview.addJavascriptInterface(jsInterface, "jsInterface");
webview.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int param = Integer.parseInt(mEditText.getText().toString());
jsInterface.java_call_Js(param);
param = 0;
}
});
}
});
}
}
4.最後是JsInterface,封裝了兩個函式
//雖然命名為Interface,其實是偽介面,主要是為了方便理解及以後做抽象處理
public class JsInterface {
private WebView mWebView;
// 構造方法,傳入一個引數WebView
public JsInterface(WebView webView) {
this.mWebView = webView;
}
// 這個方法是js呼叫java
@JavascriptInterface
public void js_call_java() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// 主執行緒更新UI
Toast.makeText(mWebView.getContext(), "I'm a function in java", Toast.LENGTH_SHORT).show();
}
});
}
// 這個方法 是java呼叫js
public void java_call_Js(int param) {
// 這裡呼叫html中的js程式碼的 java_call_Js 方法
mWebView.loadUrl(String.format("javascript:java_call_Js(" + param + ")"));
}
}
註釋都有,就不多說了。
在模擬器上執行程式碼,就會看到如上的效果圖
這裡主要看互動的雙方(安卓和html):
都保留著兩個方法(一個用來被對方呼叫,一個去呼叫對方)。
所有,做JS的前提是,要達成一種約定。要明確了對方的什麼物件的什麼方法可以被呼叫,才能如魚得水。
另外這個地方值得注意:
// 允許JS互動 ------>意味著可能會被JS注入等攻擊,安全問題需要考慮//
webview.getSettings().setJavaScriptEnabled(true);
// 設定JS的介面--------->第二個引數"jsInterface" 定義了給html中使用的物件就叫jsInterface
webview.addJavascriptInterface(jsInterface, "jsInterface")
//html中使用這個物件的程式碼就是: jsInterface.js_call_java();