什么是 Cordova
- 一个移动应用开发框架
- 本质是 HTML、CSS、JavaScript 外面包装个原生的壳
- 出自于 Adobe 11 年收购的 PhoneGap,是驱动 PhoneGap 的核心引擎
- 是 Apache 的顶级开源项目
Cordova 提供了一系列设备相关的 API,通过这组 API,移动应用能够以 JavaScript 访问原生的设备功能,如摄像头、麦克风。
移动端开发分类
- 原生 App(Native App)
- Web App
- 混合 App(Hybrid App)
Cordova 在整个 App 领域中的位置
Cordova 的优缺点
优点:跨平台,便于移植,开发快速,成本低。
缺点:执行速度相对原生会慢一些,一次编写,要处处调试。
Cordova 的架构
- Web App:存放应用程序代码的地方,体现是你的具体业务逻辑模块。
- WebView:给应用提供完整的用户访问呈现。
- Cordova Plugins:提供了和原生组件通信的接口并绑定到了标准的设备 API,将来通过 JavaScript 来调用。
Cordova 环境配置
- Git 的安装
- Node.js 的安装
- 安装 Cordova Cli 下载并安装 Cordova 全局模块
- 安装 Java JDK
- 安装 Android Studio 安装 Android SDK
npm install -g cordova / cnpm install -g cordova
npm install -g cordova --registry=https://registry.npm.taobao.org
cnpm install -g cordova@8.1.2 // 安装指定版本
cordova --version // 查看 cordova 安装的版本
10.0.0
复制代码
构建 Cordova 项目
cordova create 项目名 com.公司名.项目名 类名(建议) // 创建一个空的Cordova项目
cordova create cordovademo02 com.itying.cordova Cordovademo
cordova create MyApp // 创建一个空的Cordova项目
cordova help create // 要获得完整的选项集,请运行
复制代码
cordova 创建项目报错解决方法:
卸载 cordova npm uninstall -g cordova
删掉 cordova 文件 npm\node_modules\cordova
npm install -g cordova --registry=https://registry.npm.taobao.org
复制代码
添加平台
cd MyApp
cordova platform add android // 添加平台
cordova platform // 获取完整的平台列表,请运行
复制代码
目录结构
- config.xml 配置页,配置起始页项目名称等基础内容
- hooks 存放一些自定义扩展功能
- platforms 存放添加的 platform 运行时
- plugins 存放引入的插件
- www 开发的 HTML5 目录
实际打包文件 platforms /android/app/src/main/assets/www
运行项目
cordova run android
复制代码
项目的 platforms 下 android目录 导入 android studio 进行运行调试 (或者运行 cordova run android)
创建项目的时候注意包名称:发布上线打包的时候用到包名称,注意
修改应用包名称参考:www.ionic.wang/article-ind…
1、修改 config.xml 里面的包名称
2、修改完成以后重新执行 cordova platform add android
修改项目后,运行 cordova prepare
实际编译 platforms \android\app\src\main\assets\www
编译项目
cordova build android
复制代码
打包报错
Checking Java JDK and Android SDK versions
ANDROID_SDK_ROOT=undefined (recommended setting)
ANDROID_HOME=F:\software\Android\Sdk (DEPRECATED)
Could not find an installed version of Gradle either in Android Studio,
or on your system to install the gradle wrapper. Please include gradle
in your path, or install Android Studio
复制代码
方法一:
用 Android Studio 打开 Android 目录 进项打包。
包所在的位置:android\app\build\outputs\apk\debug
方法二:
根据上面的报错信息可以得出 1、没有找到 Gradle 2、需要设置环境变量 ANDROID_SDK_ROOT 3、Android SDK 在 F:\software\Android\Sdk
如果不知道 Android SDK 在什么位置可以如下操作:
打开 Android Studio
环境变量配置如下
初次安装 Android Studio 时会安装 gradle
在上面路径基础上 + \wrapper\dists 你就会看到 gradle 的包了。 例如:C:\Users\86183.gradle + \wrapper\dists
在系统变量中 path 下添加 gradle/bin 的路径
例如:C:\Users\86183.gradle\wrapper\dists\gradle-5.6.4-all\ankdp27end7byghfw1q2sw75f\gradle-5.6.4\bin
再次打包
Checking Java JDK and Android SDK versions
ANDROID_SDK_ROOT=D:\software\Android\Sdk (recommended setting)
ANDROID_HOME=D:\software\Android\Sdk (DEPRECATED)
Subproject Path: CordovaLib
Subproject Path: app
FAILURE: Build failed with an exception.
* Where:
Build file 'D:\MyApp\platforms\android\app\build.gradle' line: 20
* What went wrong:
A problem occurred evaluating project ':app'.
> Failed to apply plugin [id 'com.android.internal.version-check']
> Minimum supported Gradle version is 5.6.4. Current version is 4.10.3. If using the gradle wrapper, try editing the distributionUrl in D:\MyApp\gradle\wrapper\gradle-wrapper.properties to gradle-5.6.4-all.zip
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 3s
D:\MyApp\platforms\android\gradlew: Command failed with exit code 1 Error output:
FAILURE: Build failed with an exception.
* Where:
Build file 'D:\MyApp\platforms\android\app\build.gradle' line: 20
* What went wrong:
A problem occurred evaluating project ':app'.
> Failed to apply plugin [id 'com.android.internal.version-check']
> Minimum supported Gradle version is 5.6.4. Current version is 4.10.3. If using the gradle wrapper, try editing the distributionUrl in D:\MyApp\gradle\wrapper\gradle-wrapper.properties to gradle-5.6.4-all.zip
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 3s
复制代码
根据报错手动修改了 项目中的 gradle 版本
项目\gradle\wrapper\gradle-wrapper.properties 中的 gradle-4.10.3-all.zip 修改为 gradle-5.6.4-all.zip
再次打包,还是报错,并且文件又被修改回去了。而且还下载了 gradle-4.10.3-all.zip 包。
不要用 Android Studio 打开 android 目录,Android Studio 很可能会更改 Cordova 配置。
应用程序功能改造
cordova 通过 document.addEventListener 来监听事件
// 当 Cordova 完全加载好 deviceready 事件会触发。这个事件对每一个应用程序都是必须的。他是 Cordova 设备 API 准备好并可以访问的信号。
// Cordova 由两个代码库组成:原生(native)和JavaScript。
document.addEventListener("deviceready", function() {});
复制代码
重写功能
源码:实现功能 让 .listening 隐藏 让 .received 显示
var app = {
initialize: function() {
// deviceready 等待设备 api 的加载
document.addEventListener(
"deviceready",
this.onDeviceReady.bind(this),
false
);
},
onDeviceReady: function() {
this.receivedEvent("deviceready");
},
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector(".listening");
var receivedElement = parentElement.querySelector(".received");
listeningElement.setAttribute("style", "display:none;");
receivedElement.setAttribute("style", "display:block;");
console.log("Received Event: " + id);
}
};
app.initialize();
复制代码
重写代码:
// 添加 deviceready 监听,等待设备 api 的加载
document.addEventListener("deviceready", function() {
console.log("设备 api 准备就绪");
// 让 listening 隐藏
// 让 received 显示
setTimeout(() => {
var listening = document.querySelector(".listening");
var received = document.querySelector(".received");
listening.style.display = "none";
received.style.display = "block";
}, 2000);
});
复制代码
Cordova 事件
Cordova 插件和事件说明
Cordova 对于设备功能的封装,都是以事件或插件体现的
插件即 plugin,封装了设备提供的功能,如摄像头、通讯录、GPS 等,他们是以自定义的 js 根对象或者覆盖标准对象的方式提供的,插件需要单独安装才能使用。
Cordova 事件概览
事件名称 | 说明 |
---|---|
deviceready | 当 Cordova 加载完成后该事件被触发 |
pause | 当应用程序被置于后台,则触发此事件 |
resume | 当应用程序从后台返回,则触发此事件 |
backbutton | 当按下后退按钮时,则触发此事件 |
…… | …… |
Cordova 事件的使用
所有的事件调用方式类似,通过 js 进行事件监听即可(addEventListener)
document.addEventListener("deviceready", onDeviceReady,false);
function onDeviceReady() {
document.addEventListener("pause", onPause, false);
document.addEventListener("resume", onResume, false);
document.addEventListener("menubutton", onMenuKeyDown, false);
//给其他事件添加类似的监听
}
复制代码
Cordova 应用启动流程
html 页面加载流程
- 原生代码启动
- splashscreen
- load html
- 顺序执行 JavaScript => cordova.js 也执行
- $(document).ready() 执行,cordova 中的事件不一定可用。
- 注册 deviceready 事件
代码示例:
/*
* Cordova 对于设备 api 的封装,都是以 插件 和 事件 的方式体现的
* Cordova 中对于事件的监听,都类似
*/
/*
* 1、deviceready 设备 api 准备就绪时,执行
* 基于设备 api 的一些底层事件 或方法,都要在 deviceready 事件调用完成后,执行
* 2、pause 当应用挂起进入后台时,调用执行
* 3、resume 当应用回到最前面时,调用执行
* 4、backbutton 当返回键被点击时,调用
*/
/*
* deviceready 设备 api 准备就绪时,调用
* 参数1:事件名
* 参数2:回调函数
* 参数3:是否在捕获阶段执行,默认 false(冒泡阶段执行),直接默认即可
*/
// 等待是底层 cordova 相关的一些设备代码的加载
document.addEventListener("deviceready", function() {
log("设备api准备就绪, 可以进行其他方法的调用 或者 事件的监听");
// 添加应用挂起监听
document.addEventListener("pause", function() {
log("应用程序被挂起了");
});
document.addEventListener("resume", function() {
log("应用程序回来了");
});
document.addEventListener("backbutton", function() {
log("返回键被点击了");
});
});
// 输出日志内容到屏幕body中
function log(msg) {
var p = document.createElement("p");
p.style.fontSize = "14px";
p.innerHTML = msg;
// 输出到 body 中
document.body.appendChild(p);
}
复制代码
插件
插件卸载
cordova plugin rm cordova-plugin-network-information
复制代码
Cordova 插件的使用
设备
安装插件
cordova plugin add cordova-plugin-device
复制代码
网络
安装插件
cordova plugin add cordova-plugin-network-information
复制代码
设备位置
安装插件
cordova plugin add cordova-plugin-geolocation
复制代码
文件
安装插件
cordova plugin add cordova-plugin-file-transfer // 文件传输插件
cordova plugin add cordova-plugin-file // 文件插件
复制代码
电池状态
1、 安装电池插件
cordova plugin add cordova-plugin-battery-status
复制代码
2、 添加事件监听
事件监听必须在 deviceready 调用完成后调用,且必须通过 window 添加监听
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
window.addEventListener("batterystatus", onBatteryStatus, false);
}
function onBatteryStatus(status) {
console.log(
"电池状态:Level: " + status.level + " isPlugged: " + status.isPlugged
);
}
复制代码
事件会返回一个 status 对象,有两个属性 level:当前电量的百分比值,范围(0-100)number 数值类型 isPlugged:标记当前手机是否在充电 boolean 类型
三个事件:
事件名称 | 事件说明 |
---|---|
batterystatus | 当电池发生 1%的变化时触发, 或者充电状态发生切换时触发 |
batterylow | 当电池电量百分比达到了较低的值时,则触发此事件。此值在不同的设备可能有所不同。 |
batterycritical | 当电池电量百分比达到临界值时,则触发此事件。此值在不同的设备可能有所不同。 |
代码示例:
// cordova 对于插件的使用, 需要先进行安装
// 1. 安装插件 cordova plugin add cordova-plugin-battery-status
// 2. 该插件可以用于监视设备电池的变化
// 全局提供了三个事件
// (1) batterystatus 表示电池状态发生改变 (至少1%电量变化) 或者 充电状态改变 触发
// (2) batterycritical 表示电池电量进入临界值, 快关机了
// (3) batterylow 表示电池电量比较低, 触发
// 注意点: 插件的事件监听以及插件方法的调用, 一定要在 deviceready 准备完成后调用
// 所有的事件, 都会返回一个 status 对象, 这个对象有两个属性
// (1) status.level 表示设备电池电量的百分比 (0-100) number
// (2) status.isPlugged 表示设备是否正在充电 boolean值 true 在充电, false 不在充电
// 等待 cordova 设备api的加载
document.addEventListener("deviceready", function() {
// cordova 设备api的加载完成, 可以添加事件监听
window.addEventListener("batterystatus", onBatterystatus);
window.addEventListener("batterycritical", onBatterycritical);
window.addEventListener("batterylow", onBatterylow);
});
function onBatterystatus(status) {
log("当前电量: " + status.level + "是否充电中: " + status.isPlugged);
}
function onBatterycritical(status) {
log(
"当前电量已经进入临界值, 当前电量: " +
status.level +
"是否充电中: " +
status.isPlugged
);
}
function onBatterylow(status) {
log(
"当前电量已经比较低了, 当前电量: " +
status.level +
"是否充电中: " +
status.isPlugged
);
}
// 输出日志内容到屏幕body中
function log(msg) {
var p = document.createElement("p");
p.style.fontSize = "14px";
p.innerHTML = msg;
// 输出到 body 中
document.body.appendChild(p);
}
复制代码
照相机
这个插件定义了一个全局的 navigator.camera
对象, 这个对象提供了用于拍照或者使用图库文件的 API
这个对象, 只在 deviceready
事件触发后, 才可用。
1、安装照相机插件
cordova plugin add cordova-plugin-camera
复制代码
2、拍照功能
注意:ios 拍照完成以后调用 navigator.camera.cleanup(onSuccess, onFail); 清除照片缓存
// 拍照功能
function takePicure() {
// 调用插件api提供的 navigator.camera 全局对象
navigator.camera.getPicture( onSuccess, onFail, {
quality: 50,
destinationType: Camera.DestinationType.DATA_URL
});
function onSuccess(imageData) {
var img = document.querySelector("img");
img.src = "data:image/jpeg;base64," + imageData;
}
function onFail(message) {
console.log( "failed because " + message );
}
}
复制代码
3、相册读取图片
// 选择照片功能
function selectPicure() {
navigator.camera.getPicture(onSuccess, onFail, {
quality: 50,
destinationType: Camera.DestinationType.NATIVE_URI,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY
});
function onSuccess(imageURL) {
var img = document.querySelector("img");
img.src = imageURL;
}
function onFail(message) {
console.log('Failed because: ' + message);
}
}
复制代码
参数名 | 配置值 |
---|---|
quality | 在 0-100 的范围内的图像质量。默认值是 50。 |
destinationType | DATA_URL 或 0 返回 base64 编码字符串 |
FILE_URI 或 1 返回图像文件 URI | |
NATIVE_URI 或 2 返回图像本地 URI | |
sourceType | PHOTOLIBRARY 或 0 打开照片库 |
CAMERA 或 1 打开机摄像头 | |
SAVEDPHOTOALBUM 或 2 打开保存相册 | |
allowEdit | 允许图像编辑 |
encodingType | JPEG 或 0 返回 JPEG 编码的图像 |
PNG 或 1 返回 PNG 编码的图像 | |
targetWidth | 图像中的像素缩放宽度 |
targetHeight | 图像中的像素比例的高度 |
cameraDirection | FRONT 或 0 前置摄像头 |
BACK 或 1 后置摄像头 |
代码示例:
// cordova中提供了, 可以调用摄像头设备的 api, 需要安装对应的插件
// 1. 添加插件 cordova plugin add cordova-plugin-camera
// 2. 这个插件提供了一个全局对象 navigator.camera 提供了一系列的api
// 这些api, 可以帮助我们拍照, 或者从相册中读取图片
// 注意: 需要在 deviceready 完成后, 才能获取 navigator.camera 对象
// 在 navigator.camera 对象中, 提供了一个方法, getPicture( success, error, options );
// getPicture 可以用于拍照 或者 从相册中读取图片
// options参数:
// (1) quality: 表示图片质量
// (2) destinationType: 表示返回的图片格式 (路径/还是base64格式的字符串)
// 默认值: FILE_URI 返回文件路径
// (3) sourceType: 设置使用摄像头, 还是从相册读取
// 默认值 CAMERA 使用摄像头
/*
需求:
1. 点击按钮, 拍摄照片, 显示在页面中
2. 点击按钮, 从相册中, 找到图片, 显示在页面中
*/
// 找对象
var btn1 = document.getElementById("btn1"); // 拍照
var btn2 = document.getElementById("btn2"); // 拍照-返回base64格式
var btn3 = document.getElementById("btn3"); // 从相册中选图片
var img = document.querySelector("img"); // 获取图片dom对象
document.addEventListener("deviceready", function() {
// 等待设备 api 的加载
// console.log( navigator.camera );
btn1.addEventListener("click", takePic);
btn2.addEventListener("click", takePicBase64);
btn3.addEventListener("click", getPic);
});
function takePic() {
// 调用 getPicture 方法, 可以拍照
// navigator.camera.getPicture( success, error, options );
navigator.camera.getPicture(success, error, {
quality: 50, // 表示图片的质量, 默认值 50 范围 0-100
destinationType: Camera.DestinationType.FILE_URI, // 表示显示时, 返回图片url
sourceType: Camera.PictureSourceType.CAMERA, // 默认值 CAMERA 表示通过相机进行拍照
targetWidth: 100, // 保持原有比例, 进行压缩显示
targetHeight: 100
});
function success(fileurl) {
console.log("拍照成功");
// 默认 success 返回的是 文件路径
img.src = fileurl;
}
function error() {
console.log("拍照失败");
}
}
function takePicBase64() {
// 调用 getPicture( success, error, options );
navigator.camera.getPicture(success, error, {
quality: 50, // 表示图片的质量
destinationType: Camera.DestinationType.DATA_URL, // 返回base64编码的字符串
sourceType: Camera.PictureSourceType.CAMERA // 默认值 CAMERA 表示通过相机进行拍照
});
function success(base64str) {
console.log(base64str);
console.log("拍照成功");
// 默认读取的base64编码后的图片, 是没有前面的格式说明的
img.src = "data:image/jpeg;base64," + base64str;
}
function error() {
console.log("拍照失败");
}
}
function getPic() {
navigator.camera.getPicture(success, error, {
quality: 50, // 表示图片的质量
destinationType: Camera.DestinationType.FILE_URI, // 返回的是图片路径
sourceType: Camera.PictureSourceType.PHOTOLIBRARY // 配置图片源 为相册
});
function success(fileurl) {
img.src = fileurl;
console.log("从相册中读取图片成功");
}
function error() {
console.log("从相册中读取图片失败");
}
}
复制代码
振动
1、安装振动插件
cordova plugin add cordova-plugin-vibration
复制代码
2、振动使用
navigator.vibrate(time);
navigator.vibrate([time]);
复制代码
// 停止震动
navigator.vibrate(0);
navigator.vibrate([]);
navigator.vibrate([0]);
复制代码
代码示例:
// 1. 安装插件 cordova plugin add cordova-plugin-vibration
// 2. 使用振动的 api
// 有一个全局的方法 navigator.vibrate 可以完成振动
// 注意点: 振动api, 需要在 deviceready 之后, 调用
// navigator.vibrate 两种调用方式
// 1. navigator.vibrate( 3000 ); 振动一次, 振动3秒, 最长只能 5s
// 2. navigator.vibrate( [ 3000, 1000, 3000, 1000 ] ); // 表示振动3秒, 停顿1秒, 再振动3秒, 再停1秒
// 让振动停止, 给方法, 传 0即可
// navigator.vibrate( 0 );
// navigator.vibrate( [] );
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var stop = document.getElementById("stop");
document.addEventListener("deviceready", function() {
// 设备 api 准备就绪, 可以调用 设备相关 api 了
btn1.addEventListener("click", function() {
navigator.vibrate(5000);
});
btn2.addEventListener("click", function() {
navigator.vibrate([3000, 1000, 3000, 1000]);
});
stop.addEventListener("click", function() {
navigator.vibrate(0);
});
});
复制代码
多媒体
1、安装插件
cordova plugin add cordova-plugin-media
复制代码
2、多媒体播放、暂停、停止
// 播放音频
function playAudio() {
var src = "https://juejin.cn/android_asset/www/video/bg.mp3"; // 指定音频的路径
if ( myMedia === null ) {
myMedia = new Media( src, onSuccess, onError );
function onSuccess() {
console.log("playAudio Success");
}
function onError(error) {
console.log("playAudio Error: " + error.code);
}
}
console.log("播放音乐");
// 播放音频
myMedia.play();
}
// 暂停功能
function pauseAudio() {
if ( myMedia ) {
console.log("暂停音乐");
myMedia.pause();
}
}
// 停止音频
function stopAudio() {
if ( myMedia ) {
myMedia.stop();
}
console.log("停止音频");
myMedia = null;
}
// 音量函数功能
var volumeValue = 0.5;
function volumeUp() {
if ( myMedia && volumeValue < 1 ) {
myMedia.setVolume( volumeValue += 0.1 );
}
console.log( "当前音量:" + volumeValue );
}
function volumeDown() {
if(myMedia && volumeValue > 0) {
myMedia.setVolume(volumeValue -= 0.1);
}
console.log( "当前音量:" + volumeValue );
}
复制代码
插件提供的方法表:
方法 | 说明 |
---|---|
getCurrentPosition | 返回音频的当前位置 |
getDuration | 返回一个音频的持续时间 |
play | 用于开始或恢复音频 |
pause | 用于暂停音频 |
release | 发布底层操作系统的音频资源 |
seekTo | 用于改变音频的位置 |
setVolume | 用于音频设置音量 |
startRecord | 开始录制音频文件 |
stopRecord | 停止录制音频文件 |
stop | 停止播放音频文件 |
Config.xml 配置
更改名称
<widget ...>
<name>HelloCordova</name>
</widget>
复制代码
更改描述
<widget ...>
<description>A sample Apache Cordova application</description>
</widget>
复制代码
更改图标
<widget ...>
<icon src="res/icon.png" />
</widget>
复制代码
cordova vue
把 vue 项目打包成 app:
1、npm run build (注意:图片 目录的路径)
2、把 vue 打包后的静态资源复制到 cordova 项目里面
3、运行 cordova prepare
注意:
vue init webpack-simple 项目名称
修改:webpack.config.js 里面 publicPath
把 publicPath:’/dist” 改为 publicPath:’dist/’
修改 index 里面引入 dist 的路径 去掉前面的 / (重要)
vue init webpack 项目名称
修改:config/index.js 把 assetsPublicPath: ‘/’, 修改成 assetsPublicPath: ‘./’
Vue 中调用原生的 api:
使用 vue-cordova (不推荐使用)
1、vue 项目安装 npm install –save vue-cordova
2、在 main.js 引入插件并 use 插件
import VueCordova from 'vue-cordova'
Vue.use(VueCordova)
复制代码
3、调用插件 注意在对应的组件需要引入
var Vue = require('vue');
Vue.cordova.camera.getPicture((imgeURL) => {
window.alert('Photo URL:' + imageURL)
},(message)=>{
window.alert('FAILED:' + message)
},{
quality:50,
destinationType:Vue.cordova.camera.DestinationType.FILE_URL
})
复制代码
4、注意需要在 vue 项目 index.html 引入 cordova
<script src="cordova.js"></script>
复制代码
使用 index.html 引入 cordova.js 并定义全局变量让 vue 组件里面直接使用 cordova 插件(推荐的使用方法)
1、在 vue index.html 引入 cordova.js (注意顺序 cordova.js 放在 build.js 上面)
2、直接可以在组件里面使用 cordova 的 api (注意 cordova 里面要安装 api 的插件)
相关资料