導語
這篇文章主要介紹了如何在Android平臺上使用Cordova 的command-line interface (CLI)接口開發一個JS/HTML程序
Cordova 提供了一組設備相關的API,通過這組API,移動應用能夠以JavaScript訪問原生的設備功能,如攝像頭、麥克風等,還提供了一組統一的JavaScript類庫,以及為這些類庫所用的設備相關的原生后臺代碼。
Cordova支持如下移動操作系統:iOS, Android,ubuntu phone os, Blackberry, Windows Phone, Palm WebOS, Bada 和 Symbian。
一、安裝Cordova開發環境
Cordova命令行開發工具使用的是NPM開發工具包
NPM 是隨同NodeJS一起安裝的包管理工具,能解決NodeJS代碼部署上的很多問題
- 下載安裝Node.js ,這樣我們可以在終端執行npm命令。
- 下載安裝git Client ,這是可選的,如果以后需要使用git 連接添加一個Cordova 插件的話需要使用到。
- 在終端中使用如下命令安裝Cordova
$ sudo npm install -g cordova
完成以上步驟以后,我們就可以在終端使用Cordova命令,如果打印如下信息,則表示已經安裝成功:
Chans-MacBook-Pro:YuntxCient kevinchan$ cordova
Synopsis
cordova command [options]
Global Commands
create ............................. Create a project
help ............................... Get help for a command
telemetry .......................... Turn telemetry collection on or off
Project Commands
info ............................... Generate project information
requirements ....................... Checks and print out all the requirements
for platforms specified
platform ........................... Manage project platforms
plugin ............................. Manage project plugins
prepare ............................ Copy files into platform(s) for building
compile ............................ Build platform(s)
clean .............................. Cleanup project from build artifacts
run ................................ Run project
(including prepare && compile)
serve .............................. Run project with a local webserver
(including prepare)
查看當前系統安裝的Cordova版本:
Chans-MacBook-Pro:~ kevinchan$ cordova --v
6.4.0
安裝編譯工具
編譯和運行Cordova程序,需要在對應的平臺安裝SDK開發工具,但是如果你正在開發基于瀏覽器運行的程序則可以忽略,如下可以檢查當前開發環境是否滿足要求
Chans-MacBook-Pro:AvayaClient kevinchan$ cordova requirements
Requirements check results for android:
Java JDK: installed 1.8.0
Android SDK: installed true
Android target: installed android-16,android-18,android-19,android-21,android- 22,android-23,android-24,Google Inc.:Google APIs:16
Gradle: installed
這里可以查看到官網的支持文檔,分別為各個平臺所需要滿足的編譯環境
Cordova和Android版本支持對應關系
Cordova每個版本所支持Android最高的API有可能是不一樣的,目前Cordova最新的版本支持Android API為23,其他的版本支持對應關系可以參考如下:
cordova-android Version | Supported Android API-Levels |
---|---|
5.X.X | 14 - 23 |
4.1.X | 14 - 22 |
4.0.X | 10 - 22 |
3.7.X | 10 - 21 |
創建Cordova程序
選擇一個目錄作為工程的根目錄,使用Cordova創建命令創建Cordovac程序
Chans-MacBook-Pro:Android kevinchan$ cordova create YuntxCient com.yuntongxun.cordova.plugin YuntxSDK
Using detached cordova-create
Creating a new cordova project.
執行上面的創建命令后,會在本地文件下根目錄創建一個Cordova結構目錄,默認情況下Cordova會在當前目錄生成www文件夾,包含了web應用程序基本的html頁面,Cordova目錄結構如下:
YuntxClient/
|____config.xml
|____hooks
| |____README.md
|____platforms
|____plugins
|____www
| |____css
| | |____index.css
| |____img
| | |____logo.png
| |____index.html
| |____js
| | |____index.js
可以在Cordova查看當前創建命令的接口描述
以上我們僅僅創建了一個基本的Cordova程序,并且還沒有增加一個所支持的Native平臺,所以我么看到platforms是空的,所以我們可以根據Cordova提供的命令來為當前創建的Cordova程序增加一個平臺支持:
Chans-MacBook-Pro:Android kevinchan$ cd YuntxCient/
Chans-MacBook-Pro:YuntxCient kevinchan$ cordova platform add android --sava
Adding android project...
Creating Cordova project for the Android platform:
Path: platforms/android
Package: com.yuntongxun.cordova.plugin
Name: YuntxSDK
Activity: MainActivity
Android target: android-24
Subproject Path: CordovaLib
Android project created with cordova-android@6.0.0
Discovered plugin "cordova-plugin-whitelist" in config.xml. Adding it to the project
Fetching plugin "cordova-plugin-whitelist@1" via npm
Installing "cordova-plugin-whitelist" for android
使用Cordova命令增加一個平臺都會在platforms目錄下面增加一個以當前平臺相關的文件夾,如上使用命令增加了一個Android平臺。
注意:當使用CLI構建應用程序的時候,最好不要修改
/platforms/
目錄結構下的任意文件,因為當時用Cordova命令編譯程序的時候,該目錄會被新的編譯文件重新覆蓋生成最新的程序運行文件。
在我們添加Andorid支持平臺的時候,Cordova會為我們添加一個默認插件,也就是上面信息中所打印的cordova-plugin-whitelist
并且自動在config.xml
文件中已經幫我們配置
編譯并運行
在默認情況下,使用Cordova create
腳本命令會創建一個與Web相關的文件夾,里面包含了基于web應用程序運行所需要的html頁面和js文件,我們可以在這個web目錄下的www\js\index.js
文件里面處理Cordova SDK初始化完成事件
使用如下命令編譯所有的平臺文件,取決于/platforms/
目錄下增加了多少個平臺
$ cordova build
同樣我們也可以針對某一平臺進行編譯:
$ cordova build android
至此,我們可以使用真機/模擬器來運行我們編譯生成的apk,因為cordova
使用的編譯插件為gradle
,所以如果本機沒有安裝gradle
會先進行下載安裝,需要等待一定時間進行下載,也可以從gradle
官網下載自行配置環境變量。
二、創建自己的Cordova插件程序
一個cordova 插件可以允許Cordova 內置瀏覽器加載在任意支持平臺終端上運行,并且完成與終端原生功能進行訪問,一般使用者在web應用程序無法直接訪問平臺原生能力api的條件下進行間接訪問原生本地api接口,并且Cordova提供了大部分Android原生api的訪問插件,比如條形碼掃描、NFC通信、定制日歷等。
可以在Cordova Plugin Search page開發網站上獲取已經實現好的插件來集成到我們的應用中。
一個插件需要包含部分JavaScript接口提供插件框架調用,以及JavaScript接口本地代碼實現來完成js與本地原生功能之間進行通信。我們可以把每個平臺共用的接口單獨定義在一個js文件中,然后根據不同的平臺特有的功能提供針對當前平臺所支持的JavaScript接口,下面我們通過一個簡單的插件實現來完成web頁面調用 云通訊Android SDK 來進行SDK初始化。
我們在本地創建一個插件文件夾為cordova-plugin-yuntx
,并且增加src
和www
兩個目錄,目錄結構為:
cordova-plugin-yuntx
|____plugin.xml
|____src
| |____android
| | |____YuntxSDK.java
|____www
| |____android
| | |____yuntx.js
| |____yuntx.js
編寫本地實現文件
我們在andorid
目錄下新建一個以com.yuntongxun.cordova.plugin
為包名的java文件,繼承于CordovaPlugin
(所有自定義插件,都要繼承CordovaPlugin
),最后重寫execute方法。
execute有三個重載方法:
/**
* Executes the request.
*
* This method is called from the WebView thread. To do a non-trivial amount of work, use:
* cordova.getThreadPool().execute(runnable);
*
* To run on the UI thread, use:
* cordova.getActivity().runOnUiThread(runnable);
*
* @param action The action to execute.
* @param rawArgs The exec() arguments in JSON form.
* @param callbackContext The callback context used when calling back into JavaScript.
* @return Whether the action was valid.
*/
public boolean execute(String action, String rawArgs, CallbackContext callbackContext) throws JSONException {
JSONArray args = new JSONArray(rawArgs);
return execute(action, args, callbackContext);
}
/**
* Executes the request.
*
* This method is called from the WebView thread. To do a non-trivial amount of work, use:
* cordova.getThreadPool().execute(runnable);
*
* To run on the UI thread, use:
* cordova.getActivity().runOnUiThread(runnable);
*
* @param action The action to execute.
* @param args The exec() arguments.
* @param callbackContext The callback context used when calling back into JavaScript.
* @return Whether the action was valid.
*/
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
CordovaArgs cordovaArgs = new CordovaArgs(args);
return execute(action, cordovaArgs, callbackContext);
}
/**
* Executes the request.
*
* This method is called from the WebView thread. To do a non-trivial amount of work, use:
* cordova.getThreadPool().execute(runnable);
*
* To run on the UI thread, use:
* cordova.getActivity().runOnUiThread(runnable);
*
* @param action The action to execute.
* @param args The exec() arguments, wrapped with some Cordova helpers.
* @param callbackContext The callback context used when calling back into JavaScript.
* @return Whether the action was valid.
*/
public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
return false;
}
從源代碼可以看出,其中兩個方法都掉用了第三個方法CordovaArgs只是對JSONArray的一個封裝,方便操作json數據,所以可以根據自己的使用習慣來選擇重寫。
- String action:一個類里面可以提供多個功能,action就是指名了要調用哪個功能。
- CordovaArgs args:web以json的數據格式傳遞給Android native,CordovaArgs 是對JSONArray 的一個封裝。
- CallbackContext callbackContext:這個是回調給web,有success和error兩種回調方法
具體實現的注冊請求如下:
@Override
public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
if(action.equals("initSDK")) {
// 注冊SDK事件
String appKey = args.getString(0);
String appToken = args.getString(1);
String userName = args.getString(2);
String password = args.getString(3);
initYuntxSDK(appKey , appToken , userName , callbackContext);
return true;
}
return super.execute(action, args, callbackContext);
}
/**
* 注冊sdk請求
* @param appKey 應用id
* @param appToken 應用token
* @param userName 注冊id
*/
void initYuntxSDK(final String appKey, final String appToken, final String userName , final CallbackContext callbackContext) {
ECDevice.initial(this.cordova.getActivity(), new ECDevice.InitListener() {
@Override
public void onInitialized() {
ECDevice.setOnDeviceConnectListener(new ECDevice.OnECDeviceConnectListener() {
@Override
public void onConnectState(ECDevice.ECConnectState ecConnectState, ECError ecError) {
// 注冊結果
if(ecError.errorCode == SdkErrorCode.REQUEST_SUCCESS ) {
callbackContext.success("注冊成功");
} else if(ecError.errorCode == SdkErrorCode.CONNECTING ) {
callbackContext.success("注冊中...");
} else {
callbackContext.success("注冊失敗");
}
}
});
ECInitParams params = ECInitParams.createParams();
params.setAppKey(appKey);
params.setToken(appToken);
params.setAuthType(ECInitParams.LoginAuthType.NORMAL_AUTH);
params.setMode(ECInitParams.LoginMode.FORCE_LOGIN);
params.setUserid(userName);
ECDevice.login(params);
}
@Override
public void onError(Exception e) {
// 初始化失敗
}
});
}
如果我們的Web頁面中配置使用了當前注冊插件,調用注冊方法initSDK
, 這時候插件就會調用如上方法獲取到注冊參數信息,最終調用云平臺的Android SDK注冊方法進行注冊,并且將注冊結果返回給Web頁面進行顯示。
這里需要注意的是
execute
方法需要返回true,表示接口調用成功
編寫接口調用文件
在www
目錄下新建yuntx.js
文件,同樣我們也可以為Android平臺定義該平臺特有的一些接口文件放在android
目錄下作為跨平臺私有訪問接口
var exec = require('cordova/exec');
var platform = require('cordova/platform');
module.exports = {
/**
* 根據提供的帳號信息注冊sdk
*/
initSDK: function(appKey , token, userid , completeCallback , errorCallback) {
var _appKey = (typeof appKey === "string" ? appKey : "");
var _token = (typeof token === "string" ? token : "");
var _userid = (typeof userid === "string" ? userid : "");
exec(completeCallback, errorCallback, "YuntxSDK", "initSDK", [_appKey, _token, _userid]);
},
/**
* 根據提供的帳號發起呼叫
*
* @param {Function} resultCallback
* @param {String} calledParty
* @param {String} isVideoCall
*/
makeCall: function(resultCallback, number ,isVideoCall) {
var _isVideoCall = (typeof isVideoCall === "boolean" ? isVideoCall : false);
var _number = (typeof number === "string" ? number : "number");
exec(resultCallback, null, "YuntxSDK", "makeCall", [_number, isVideoCall]);
},
};
填寫plugin.xml配置文件
這里配置了插件的基本信息以及本地實現代碼路徑。
<?xml version="1.0" encoding="UTF-8"?>
<!-- 插件的Id,安裝后注冊的Id為此id加js-moudle的name屬性,即cordova_plugins.js里的id屬性 -->
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
id="cordova-plugin-yuntx"
version="1.0.0">
<!-- 插件名稱 -->
<name>YuntxSDK</name>
<!-- 插件描述 -->
<description>Cordova YuntxSDK Plugin</description>
<license>Apache 2.0</license>
<keywords>cordova,yuntx_android</keywords>
<issue>https://issues.apache.org/jira/browse/CB/component/12320642</issue>
<!-- js文件的地址,安裝后路徑為:plugins/插件Id/src屬性值 -->
<js-module src="www/yuntx.js" name="yuntx">
<merges target="android.yuntx" />
</js-module>
<!-- 這里對不同平臺的插件文件進行配置 -->
<!-- android -->
<platform name="android">
<!-- config-file中包含的這段會原封不動的插入到config.xml文件中 -->
<config-file target="res/xml/config.xml" parent="/*">
<feature name="YuntxSDK">
<param name="android-package" value="com.yuntongxun.cordova.plugin.YuntxSDK"/>
</feature>
</config-file>
<!-- 本地代碼,有多個文件就寫多個source-file,src對應本項目,target對應安裝后的目錄 -->
<source-file src="src/android/YuntxSDK.java" target-dir="src/com/yuntongxun/cordova/plugin" />
<!-- 這里可用配置針對Android的一些特殊apis -->
<js-module src="www/android/yuntx.js" name="yuntx_android">
<merges target="android.yuntx" />
</js-module>
</platform>
</plugin>
至此,我們已經完成了插件基本功能的配置和接口的編寫,現在我們需要調用Cordova
命令將我們編寫的插件增加到我們篇頭創建的Cordova
工程中。
增加自定義插件到插件工程中
之前我們提到過,我們不能直接在/platforms/
目錄下直接修改插件內容,因為調用安裝插件的命令后,Cordova
跟將我們指定的插件路徑將插件內容覆蓋到/platforms/
目錄下對應的插件目錄中,所以我們在這個目錄里面所做的修改就會全部被覆蓋了。
添加插件包的命令如下:
cordova plugins add <插件包路徑>
我們調用增加插件命令將我們編寫的插件集成到Cordova
項目中
Chans-MacBook-Pro:~ kevinchan$ cd Workspace/Android/YuntxCient/
Chans-MacBook-Pro:YuntxCient kevinchan$ cordova plugins add /Users/kevinchan/Workspace/Android/cordova-plugin-yuntx
Installing "cordova-plugin-yuntx" for android
ANDROID_HOME=/Users/kevinchan/Library/Android/sdk
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home
Subproject Path: CordovaLib
Starting a new Gradle Daemon for this build (subsequent builds will be faster).
Incremental java compilation is an incubating feature.
:clean
:CordovaLib:clean
BUILD SUCCESSFUL
Total time: 8.03 secs
我們在工程目錄查看生成的android項目目錄結構,如:/platforms/android/assets/
里面增加了我們自己寫的插件cordova-plugin-yuntx
assets
|____www
| |____cordova-js-src
| | |____android
| | | |____nativeapiprovider.js
| | | |____promptbasednativeapi.js
| | |____exec.js
| | |____platform.js
| | |____plugin
| | | |____android
| | | | |____app.js
| |____cordova.js
| |____cordova_plugins.js
| |____css
| | |____index.css
| |____img
| | |____logo.png
| |____index.html
| |____js
| | |____index.js
| |____plugins // 這里就是我們剛剛自己定義的插件
| | |____cordova-plugin-yuntx
| | | |____www
| | | | |____android
| | | | | |____yuntx.js
| | | | |____yuntx.js
并且在工程根目錄/res/xml/config.xml
中,Cordova為我們自動加入了yuntx插件的配置信息
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.yuntongxun.cordova.plugin" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>YuntxSDK</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
</description>
<author email="dev@cordova.apache.org" >
Apache Cordova Team
</author>
<content src="index.html" />
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<allow-intent href="market:*" />
<preference name="loglevel" value="DEBUG" />
// 云平臺SDK插件
<feature name="YuntxSDK">
<param name="android-package" value="com.yuntongxun.cordova.plugin.YuntxSDK" />
</feature>
</widget>
以及在www
根目錄會生成插件配置文件
cordova.define('cordova/plugin_list', function(require, exports, module) {
module.exports = [
{
"id": "cordova-plugin-yuntx.yuntx",
"file": "plugins/cordova-plugin-yuntx/www/yuntx.js",
"pluginId": "cordova-plugin-yuntx",
"merges": [
"android.yuntx"
]
},
{
"id": "cordova-plugin-yuntx.yuntx_android",
"file": "plugins/cordova-plugin-yuntx/www/android/yuntx.js",
"pluginId": "cordova-plugin-yuntx",
"merges": [
"android.yuntx"
]
}
];
module.exports.metadata =
// TOP OF METADATA
{
"cordova-plugin-yuntx": "1.0.0"
};
// BOTTOM OF METADATA
});
插件使用方法
我們打開www/js/index.js
文件,在index.js
的onDeviceReady
方法調用
onDeviceReady: function() {
this.receivedEvent('deviceready');
//注冊成功回調
function onSuccess(results) {
alert("注冊成功");
}
// 失敗回調
function onError(errCode) {
alert('注冊失敗 ' + errCode);
}
// 發起注冊請求
android.yuntx.initSDK(
'201002000000000000000000000000000002',
'adneojdowenneneofwifojweofjewo',
'yuntongxun.com',
onSuccess,
onError
);
/*android.yuntx.makeCall(
function onMakeCallResult() {
},
'm.yuntongxun.com' ,
false
);*/
},
Cordova生命周期
原生的Android App一般由多個Activity組成任務棧,而且從一個APP切換到另一個APP之后,當前與之交互的app就會退到后臺,根據每個Activity從前后退到后臺,或者從后臺切換到前臺的過程中,都會回調Activity的生命周期方法,我們可以根據這些生命周期方法來處理不同場景下的邏輯。
而相比于Cordova程序,因為所有的Cordova頁面都只使用到了Android系統的獨立一個Activity,并將自定義的WebView嵌入到當前的Activity中完成與用戶的交互動作,所以不能保證Cordova的生命周期和Android的Activity的生命周期保持一致,但是可以根據Activity的生命周期狀態來對數據做保存和恢復處理,Activity的生命周期方法和Cordova生命周期方法對應關系可以參考如下:
Cordova Event | Rough Android Equivalent | Meaning |
---|---|---|
deviceready |
onCreate() |
程序第一次運行(卻別于從后臺切到前臺) |
pause |
onPause() |
應用程序從前臺切換到后臺顯示 |
resume |
onResume() |
應用程序從后臺切換到前臺顯示 |
Android操作系統當手機可用內存很低的情況下會選擇性的結束一些后臺運行的程序來釋放內存資源,所以當我們的Cordova程序退到后臺的時候有可能會被系統結束,導致WebView結束運行,所以這個時候程序的運行狀態中所保存的數據就會丟失,當用戶從最近打開程序列表中選擇打開被結束的Cordova程序的時候,此時Activtiy 和WebView都會被沖洗創建,但是我們之前運行的時候所保留的運行數據已經丟失,所以可能你上一次是處于聊天界面,而現在打開程序的時候你卻有可能處于登錄界面,這會讓用戶感到迷惑,解決方法就是根據當前的Activity周期調用相對應的Cordovas事件通知機制來對用戶的訪問數據進行保存,等到Activtiy 和WebView重新創建的時候可以恢復到上一次離開的狀態。
比如用戶想上傳一張圖片到服務器中,這個時候會有如下的操作步驟:
- 點擊界面的圖片選擇按鈕跳轉到Android原生相機拍照界面(這個時候Cordova程序停止運行并且退到后臺)
- 用戶完成拍照并保存圖片
- Android系統保存完拍照圖片后關閉相機應用(這個時候系統會將Cordova程序推倒前臺顯示)
- 用戶回到上一次離開的界面
然而,以上的使用流程如果在一些內存很低的手機上的時候有可能會執行出錯(不完整),就比如系統把退到后臺的程序給結束了,這個時候就變成:
- 點擊界面的圖片選擇按鈕跳轉到Android原生相機拍照界面(這個時候Cordova程序停止運行并且退到后臺)
- 用戶完成拍照并保存圖片
- Android系統保存完拍照圖片后關閉相機應用(這個時候系統會將Cordova程序推倒前臺顯示)
- 程序重新運行回到登錄界面
所以針對上面的這種場景,Cordova增加了對插件的事件回調方法:
當程序退到后臺的時候/或者從后臺切換到前臺的時候,Cordova可以根據回調事件來判斷是否需要保存數據/恢復用戶數據
比如Cordova調用頁面重新加載的事件通知格式如下:
{
action: "resume",
pendingResult: {
pluginServiceName: string,
pluginStatus: string,
result: any
}
}
- pluginServiceName : 插件的名字(比如我們剛才定義的YuntxSDK),也就是我們在
plugin.xml
文件中的<name>
標簽中配置的值 - pluginStatus:插件的狀態
- result:
其中插件的狀態pluginStatus
值有如下幾種:
"OK"
插件是否調用成功"No Result"
插件調用結束并且無返回值"Error"
插件調用發生錯誤-
其他可能的錯誤
"Class not found"
"Illegal access"
"Instantiation error"
"Malformed url"
"IO error"
"Invalid action"
"JSON error"
所以我們按照上面的格式在Activity的生命周期方法中根據當前的Activity狀態來傳相對應的字符串,告訴Cordova我們當前的狀態,這樣Cordova就可以對插件的一些數據做保存,等到程序在后臺被結束的時候再次返回后可以恢復到離開狀態。
使用方法
下面是Cordova官方提供的示例代碼,告訴我們如何使用resume
和pause
事件來管理狀態,以及如何根據resume的返回值來回復當前的activity狀態。
// This state represents the state of our application and will be saved and
// restored by onResume() and onPause()
var appState = {
takingPicture: true,
imageUri: ""
};
var APP_STORAGE_KEY = "exampleAppState";
var app = {
initialize: function() {
this.bindEvents();
},
bindEvents: function() {
// Here we register our callbacks for the lifecycle events we care about
document.addEventListener('deviceready', this.onDeviceReady, false);
document.addEventListener('pause', this.onPause, false);
document.addEventListener('resume', this.onResume, false);
},
onDeviceReady: function() {
document.getElementById("take-picture-button").addEventListener("click", function() {
// Because the camera plugin method launches an external Activity,
// there is a chance that our application will be killed before the
// success or failure callbacks are called. See onPause() and
// onResume() where we save and restore our state to handle this case
appState.takingPicture = true;
navigator.camera.getPicture(cameraSuccessCallback, cameraFailureCallback,
{
sourceType: Camera.PictureSourceType.CAMERA,
destinationType: Camera.DestinationType.FILE_URI,
targetWidth: 250,
targetHeight: 250
}
);
});
},
onPause: function() {
// Here, we check to see if we are in the middle of taking a picture. If
// so, we want to save our state so that we can properly retrieve the
// plugin result in onResume(). We also save if we have already fetched
// an image URI
if(appState.takingPicture || appState.imageUri) {
window.localStorage.setItem(APP_STORAGE_KEY, JSON.stringify(appState));
}
},
onResume: function(event) {
// Here we check for stored state and restore it if necessary. In your
// application, it's up to you to keep track of where any pending plugin
// results are coming from (i.e. what part of your code made the call)
// and what arguments you provided to the plugin if relevant
var storedState = window.localStorage.getItem(APP_STORAGE_KEY);
if(storedState) {
appState = JSON.parse(storedState);
}
// Check to see if we need to restore an image we took
if(!appState.takingPicture && appState.imageUri) {
document.getElementById("get-picture-result").src = appState.imageUri;
}
// Now we can check if there is a plugin result in the event object.
// This requires cordova-android 5.1.0+
else if(appState.takingPicture && event.pendingResult) {
// Figure out whether or not the plugin call was successful and call
// the relevant callback. For the camera plugin, "OK" means a
// successful result and all other statuses mean error
if(event.pendingResult.pluginStatus === "OK") {
// The camera plugin places the same result in the resume object
// as it passes to the success callback passed to getPicture(),
// thus we can pass it to the same callback. Other plugins may
// return something else. Consult the documentation for
// whatever plugin you are using to learn how to interpret the
// result field
cameraSuccessCallback(event.pendingResult.result);
} else {
cameraFailureCallback(event.pendingResult.result);
}
}
}
}
// Here are the callbacks we pass to getPicture()
function cameraSuccessCallback(imageUri) {
appState.takingPicture = false;
appState.imageUri = imageUri;
document.getElementById("get-picture-result").src = imageUri;
}
function cameraFailureCallback(error) {
appState.takingPicture = false;
console.log(error);
}
app.initialize();
與之對應的HTML文件如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<link rel="stylesheet" type="text/css" href="css/index.css">
<title>Cordova Android Lifecycle Example</title>
</head>
<body>
<div class="app">
<div>
<img id="get-picture-result" />
</div>
<Button id="take-picture-button">Take Picture</button>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>
測試
Android系統設置/開發者選項/中提高了一些設置api來模擬低內存狀態,在開發者選項中,我們將不保留活動
設置為啟用狀態來模擬低內存的場景,這樣我們運行上面的程序打開系統相機界面的時候,等我們拍完照片返回的時候,系統已經將我們的插件程序結束并且重新初始化了。