Cordova入门
标签:Cordova
名词 | 链接 | 描述 |
---|---|---|
Cordova | http://cordova.apache.org/ | Hybrid App中间件 |
ios-deploy | https://github.com/phonegap/ios-deploy | 使用命令行部署iOS项目 |
PhoneGap | https://phonegap.com/ | 使用Web快速开发、打包Hybrid APP |
Node.js | https://nodejs.org/en/ | 基于 Chrome V8 引擎的 JavaScript 运行环境。 |
npm | https://www.npmjs.com/ | Node.js的包管理器 |
Git | https://git-scm.com/ | 分布式版本控制库 |
ionic | http://ionicframework.com/ | 基于Angular的H5框架 |
Angular | https://angularjs.org/ | 优秀的前端JS框架 |
PhoneGap100 | http://www.phonegap100.com/ | Hybrid App社区 |
1 概述
1.1 移动端的开发模式
Native App
传统的原生APP开发模式,Android基于Java语言,底层调用Google的API;iOS基于OC或者Swift语言,底层调用Apple官方提供的API。体验最好。Web App
移动端的网站,将页面部署在服务器上,然后用户使用各大浏览器访问。一般泛指SPA(SinglePageApplication)模式开发出的网站。体验最差。Hybrid App
混合开发,由Native通过JSBridge等方法提供统一的API,然后用Html5+JS来写实际的逻辑,调用API,这种模式下,由于Android,iOS的API一般有一致性,而且最终的页面也是在webview中显示,具有跨平台效果。React Native App
Facebook开源的一套新的APP开发方案,使用JS+部分原生语法来实现功能。初次学习成本较高,但是在入门后,经过良好的封装也能够实现大部分的跨平台。而且体验很好。
React Native不属于Hybrid 开发。虽然同样是一处编写,处处运行,但是 Hybrid是 HTML 和原生代码混合实现,而React Native只不过是以 JavaScript 的形式告诉 Objective-C 该执行什么代码。
1.2 Cordova基本介绍
Cordova前身是PhoneGap,而PhoneGap是Nitobi软件公司2008年推出的一个框架,旨在弥补web和iOS之间的不足,使得web和iPhone SDK之间的交互更容易,后来又陆续加入了更多的平台。
2011年被Adobe收购,同年晚些时候,该项目核心代码被捐赠给Apache软件基金会(ASF),以保持透明和开放的发展,而Apache将其更名为Cordova。
- Cordova提供了一组设备相关的API,通过这组API,移动应用能够以 JavaScript 访问原生的设备功能,如摄像头、麦克风等。
- Cordova还提供了一组统一的 JavaScript 类库,以及为这些类库所用的设备相关的原生后台代码。
- Cordova支持如下移动操作系统:iOS, Android,ubuntu phone os, Blackberry, Windows Phone, Palm WebOS, Bada 和 Symbian。
现在,Adobe PhoneGap™提供了其他Adobe服务的附加工具,包括PhoneGap Developer App,PhoneGap Desktop App,PhoneGap Build和PhoneGap Enterprise等工具。
但是Apache Cordova依然是支持Adobe PhoneGap™的引擎,类似于WebKit为Chrome或Safari提供引擎。可以理解为Adobe PhoneGap™是Apache Cordova™的应用发行版。
原理图如下
2 Cordova安装(Mac环境)
2.1 安装Node.js
要安装Cordova,需要先安装Node.js。在[Node.js官网][2]上下载并安装即可。
运行命令 正常输出信息则安装成功
node -v
npm -v
2.2 安装git
macOS和linux都自带git,使用命令
git --version
检查git,如果没有安装可以到[git官网][3]下载安装一个git客户端。
2.3 安装Cordova
在终端执行
sudo npm install -g cordova
等待一段时间即可安装完毕,使用
cordova -v
查看安装是否成功。
此外还有更新Cordova的命令
sudo npm update cordova -g
Cordova更新完成后,还需要更新平台(比如更新ios)
cordova platform update ios
3 创建Cordova 工程
3.1 创建项目
在终端中切换目录到工作目录下,执行以下命令
cordova create hello com.example.hello HelloWorld
参数说明:
名称 | 必填 | 描述 |
---|---|---|
hello | 必填 | 工程的文件夹名,会创建一个同名文件夹 |
com.example.hello | 可选 | 应用程序的id名,与Xcode中类似,可以在 config.xml 中修改,如果不指定的话默认为 io.cordova.hellocordova |
HelloWorld | 可选 | App的名称,也可在 config.xml 中修改 |
同时我们也可以通过npm平台在本地创建模板工程,可以在这里寻找.
找到想使用的模板后,使用该模板创建项目,方法是–template在create命令中指定标志,然后指定模板源。
从NPM,Git存储库或本地路径创建一个cordova项目:
$ cordova create hello com.example.hello HelloWorld --template <npm-package-name>
$ cordova create hello com.example.hello HelloWorld --template <git-remote-url>
$ cordova create hello com.example.hello HelloWorld --template <path-to-template>
3.2 添加平台
然后我们需要为我们的项目添加运行的平台,比如我们添加iOS和安卓,就可以执行以下命令:(下列命令都是在项目根目录下执行,cd到hello
)
cordova platform add ios
cordova platform add android
同时,我们也可以使用下面的命令查看Cordova 支持的平台和项目已经添加的平台:
cordova platforms ls
3.3 目录说明
项目已经创建完毕, 展现出来的目录结构如下图所示:
同时官方给出的目录结构是这样的:
myapp/
|– config.xml
|– hooks/
|– merges/
| | |– android/
| | |– windows/
| | |– ios/
|– www/
|– platforms/
| |– android/
| |– windows/
| |– ios/
|– plugins/
|–cordova-plugin-camera/
名称 | 描述 |
---|---|
config.xml | cordova的配置文件 |
hooks | 存放自定义Cordova命令的脚本文件。每个project命令都可以定义before和after的Hook,比如:before_build、after_build |
platforms | 各个平台的项目,不要手动修改,因为在build的时候会被覆盖。 |
plugins | 插件目录(Cordova提供的原生API也是以插件的形式提供的) |
www | 源代码目录,在Cordova prepare的时候会被copy到各个平台工程的assets\www目录中。 其中index.html为应用的入口文件。 |
node_modules | npm的依赖文件 |
merges目录 4+的版本取消了这个文件夹
存放各个平台特殊的文件,会和www进行合并编译,相同的文件merges下的文件优先。 比如:
merges/
|– ios/
| |– app.js
|– android/
| |– android.js
www/
| |– app.js
编译成iOS应用的话,包含merges/ios/app.js;而Android应用的话,包含www/app.js、merges/android/android.js
3 开发项目
3.1 工程目录和Cordova的生命周期
使用xcode打开platforms/ios/HelloWorld.xcworkspace 来打开项目,默认的Cordova工程看起来是这个样子:
可以看到 Staging 文件夹下面有个 www 文件夹和一个 config.xml 文件(黄色标注)。
而在 Staging 文件夹外也有个 www 文件夹和一个 config.xml 文件(红色标注的)。
实际上Staging 外的www文件夹就是cordova/hello下的, Staging 下的www文件夹是在platforms/ios里的, Staging 下的config.xml 金仅作用于iOS平台,主要是配置插件。
也就是说每次Cordova编译的时候,或者更新工程、安装插件时都会重新把红色里的文件覆盖到各个平台下的文件(黄色标注的)。而且如果同时只编辑单个平台工程文件夹下的html页面,也不符合一次编写,同时编译发布多平台的跨平台应用开发思想。
所以一般都是编辑外面的(红色标注)www文件夹里的文件,然后重新 build 工程。
初始工程在模拟器中运行效果如下:
Cordova提供APP状态的监测(iOS),包括:
名称 | 描述 |
---|---|
deviceready | 当Cordova加载完成会触发 |
pause | 当应用程序进入到后台会触发 |
resumes | 应用程序从后台进入到前台会触发 |
详细的事件以及支持列表如下:
我们将index页面修改为如下内容,展示APP的状态监测:
<!DOCTYPE html>
<html>
<head>
<title>Pause Example</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">
//页面加载后添加各事件监听
function onLoad() {
document.addEventListener("deviceready", onDeviceReady, false);
document.addEventListener("resume", onResume, false);
document.addEventListener("pause", onPause, false);
}
//Cordova加载完毕
function onDeviceReady() {
alert("Cordova加载完毕!");
}
//进入后台
function onPause() {
console.log("应用进入到后台!");
}
//恢复到前台
function onResume() {
alert("应用回到前台运行!");
}
</script>
</head>
<body onload="onLoad()">
</body>
</html>
3.2 Cordova build
在开发完页面以后,我们需要构建项目将新的修改部署到各平台的项目中。
如果我们向使用命令行构建和运行iOS APP需要先安装 ios-deploy
android需要安装JDK和androidSDK。
安装xcode命令行工具:
xcode-select --install
执行下列命令安装 ios-deploy:
sudo npm install -g ios-deploy
//如果安装失败可以使用
sudo npm install -g ios-deploy --unsafe-perm=true
xcodebuild
安装后我们就可以运行以下命令为所有平台构建项目:
cordova build
也可以构建特定的平台 如“ios”:
cordova build ios
利用 ios-deploy我们可以直接使用命令:
cordova run ios
或在模拟器中运行:
cordova emulate ios
//指定模拟器使用的模拟设备:
cordova emulate ios --target iPhone-6s
cordova emulate ios --target iPhone-6s-Plus
APP运行后就可以接收到状态监听如下图:
3.3 浏览器访问和调试
我们也可以启动Cordova自带的服务器,通过浏览器来访问程序页面
(1) 运行如下命令输出访问地址:
cordova server
在浏览器中即可打开
(2) 在Safari 中调试
打开 Safari 的“偏好设置”-> “高级” -> “在菜单栏中显示开发菜单”
在Safari菜单项“开发” -> “Simulator”中选择对应的html页面:
在调试器中可以添加断点跟踪调试:
在“控制台”中就可以看到输出的调试信息:
最新的Cordova 中,iOS平台自动集成了一些开发插件,比如控制台输出,所以在Xcode的控制台我们也可以看到console.log的输出。
4 Cordova插件
4.1 使用核心插件
Cordova插件使的微博APP得到了调用设备功能的能力,插件通常托管在npm上,我们可以在插件搜索页面上搜索。
同事一些关键的API由Apache Cordova提供开源项目,这些API被称为核心插件API。
我们可以使用CLI命令打开搜索页面:
cordova plugin search camera
使用plugin add
命令添加插件:
cordova plugin add example
使用下面的命令来查看当前使用的插件:
cordova plugin ls
下面我们使用相机插件来实现拍照功能
执行下面命令来添加相机插件:
cordova plugin add cordova-plugin-camera
可以看到在hello/plugin目录下成功添加了相机插件
同时在iOS工程下的Plugins组下也多了相机相关的代码文件
修改index.html 修改为以下内容:
<!DOCTYPE html>
<html>
<head>
<title>Capture Photo</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">
var destinationType;
document.addEventListener("deviceready",onDeviceReady,false);
//Cordova加载完成会触发
function onDeviceReady() {
destinationType=navigator.camera.DestinationType;
}
//拍照并编辑
function capturePhotoEdit() {
//拍照并获取Base64编码的图像(quality : 存储图像的质量,范围是[0,100])
//allowEdit: true 拍照完毕后允许简单编辑
//correctOrientation: true 自动旋转照片 保证照片方向正确
//saveToPhotoAlbum: true 拍摄后保存到相册
//cameraDirection: Camera.Direction.FRONT 打开前置摄像头
//cameraDirection: Camera.Direction.BACK 默认值 后置摄像头
navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 20,
allowEdit: true,
destinationType: destinationType.DATA_URL });
}
//拍照成功
function onPhotoDataSuccess(imageData) {
console.log(imageData);
var smallImage = document.getElementById('smallImage');
smallImage.style.display = 'block';
smallImage.src = "data:image/jpeg;base64," + imageData;
}
//拍照失败
function onFail(message) {
alert('拍照失败: ' + message);
}
</script>
</head>
<body style="padding-top:50px">
<button style="font-size:23px;" onclick="capturePhotoEdit();">拍照并编辑</button> <br>
<img style="display:none;width:240px;height:240px;" id="smallImage" src="" />
</body>
</html>
在iOS10 下,调用相机需要进行权限提示,需要在info.plist中添加
NSCameraUsageDescription
值,否则会出现crash。
相册权限值为NSPhotoLibraryUsageDescription
4.2 实现自定义插件
插件包括一个JavaScript接口以及相应的本地代码,用于支持不同的平台,同时还需要实现配置文件。
Cordova通过JavaScript 接口来调用插件的本地原生代码,其中最核心的就是cordova.exec
cordova.exec(function(winParam) {},
function(error) {},
"service",
"action",
["firstArgument", "secondArgument", 42, false]);
以下是每个参数的描述:
名称 | 描述 |
---|---|
function(winParam) {} | 成功回调函数。假设你的 exec调用成功完成,这个函数和你传递给它的参数一起执行。 |
function(error) {} | 错误回调函数。如果操作未成功完成,则此函数使用可选的错误参数执行。 |
service | 在本机平台调用的服务名称,对应于本地的同名类。 |
action | 在本机端调用的方法名称。这通常对应于上述类的同名方法。 |
[/* arguments */] | 传入本地环境的参数数组。 |
在Plugins
文件夹下创建 IPaynowTestPlugin
类,继承自CDVPlugin
,同时要引入CDVPlugin.h
。
代码如下:
//
// IPaynowTestPlugin.h
// HelloWorld
//
// Created by Chuck on 2017/11/22.
//
#import <Cordova/CDVPlugin.h>
@interface IPaynowTestPlugin : CDVPlugin
- (void)verifyPassword:(CDVInvokedUrlCommand*)command;
@end
//
// IPaynowTestPlugin.m
// HelloWorld
//
// Created by Chuck on 2017/11/22.
//
#import "IPaynowTestPlugin.h"
@implementation IPaynowTestPlugin
- (void)verifyPassword:(CDVInvokedUrlCommand *)command{
//插件回调
CDVPluginResult* pluginResult = nil;
NSString* code = @"";
//取参
if(command.arguments.count > 0){
code = [command.arguments objectAtIndex:0];
}
//验证
if(code .length<3){
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"密码格式错误"];
}else if([code isEqualToString:@"ipaynow"]){
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
}else{
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"密码错误"];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
@end
在Staging
目录下的config.xml
配置文件的widget
节点下添加如下内容:
<feature name="iPaynowTestPlugin">
<param name="ios-package" value="IPaynowTestPlugin" />
<param name="onload" value="true" />
</feature>
修改index.html 代码如下:
<!DOCTYPE html>
<html>
<head>
<title>密码验证</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">
function verify() {
//获取输入的字符
var password = document.getElementById("pwd").value;
//调用自定义的插件
Cordova.exec(successFunction, failFunction, "iPaynowTestPlugin",
"verifyPassword", [password]);
}
//验证成功
function successFunction(){
alert("密码验证成功!");
}
//验证失败
function failFunction(message){
alert("验证失败:"+message);
}
</script>
<style> * { font-size:1em; } </style>
</head>
<body style="padding-top:50px;">
<input type="text" id="pwd" >
<button onclick="verify();">验证</button>
</body>
</html>
运行效果如下
4.3 封装多平台插件
上面的密码验证仅是iOS平台下的插件,根据一处编写多处运行的优点,我们应该将其封装为多平台通用。
(1)安装plugman
使用版本命令检查安装:
plugman -v
执行以下命令安装:
//sudo 是为获取 `/usr/local/lib/node_modules` 的写入权限
sudo npm install -g plugman
plugman的相关命令如下
Create A Plugin
---------------
$ plugman create --name <pluginName> --plugin_id <pluginID> --plugin_version <version> [--path <directory>] [--variable NAME=VALUE]
Parameters:
- <pluginName>: The name of the plugin
- <pluginID>: An ID for the plugin, ex: org.bar.foo
- <version>: A version for the plugin, ex: 0.0.1
- <directory>: An absolute or relative path for the directory where the plugin project will be created
- variable NAME=VALUE: Extra variables such as description or Author
Add a Package.JSON file to plugin
---------------------------------
Creates a package.json file in the plugin based on values from plugin.xml.
$ plugman createpackagejson <directory>
Add a Platform to a Plugin
--------------------------
$ plugman platform add --platform_name <platform>
Parameters:
- <platform>: One of android, ios
Remove a Platform from a Plugin
-------------------------------
$ plugman platform remove --platform_name <platform>
Parameters:
- <platform>: One of android, ios
(2)创建一个插件
命令格式如下:
$ plugman create --name <pluginName> --plugin_id <pluginID> --plugin_version <version> [--path <directory>] [--variable NAME=VALUE]
名称 | 描述 |
---|---|
pluginName | 插件的名称 |
pluginID | 插件的ID |
version | 插件的版本 |
directory | 一个绝对或相对路径的目录,该目录将创建插件项目,缺省的话将在当前目录下创建一个插件名称的文件夹 |
variable NAME=VALUE | 额外的描述,如作者信息和相关描述 |
示例:
plugman create --name iPaynowTestPlugin --plugin_id iPaynowTestPlugin --plugin_version 1.0.0
为插件添加支持的平台,这里添加iOS和android
cd到插件的根目录下执行:
plugman platform add --platform_name android
plugman platform add --platform_name ios
执行完毕后的目录是这样的:
(3)将我们的iOS 源码文件拷贝到src/ios/
路径下
修改plugin.xml
内容如下:
<?xml version='1.0' encoding='utf-8'?>
<plugin id="iPaynowTestPlugin" version="1.0.0" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
<name>iPaynowTestPlugin</name>
<description>This plugin use to verify password</description>
<js-module name="iPaynowTestPlugin" src="www/iPaynowTestPlugin.js">
<clobbers target="cordova.plugins.iPaynowTestPlugin" />
</js-module>
<!-- iOS -->
<platform name="ios">
<config-file parent="/*" target="config.xml">
<feature name="iPaynowTestPlugin">
<param name="ios-package" value="IPaynowTestPlugin" />
</feature>
</config-file>
<header-file src="src/ios/IPaynowTestPlugin.h" />
<source-file src="src/ios/IPaynowTestPlugin.m" />
</platform>
<!-- android -->
<platform name="android">
<config-file parent="/*" target="res/xml/config.xml">
<feature name="iPaynowTestPlugin">
<param name="android-package" value="iPaynowTestPlugin.iPaynowTestPlugin" />
</feature>
</config-file>
<config-file parent="/*" target="AndroidManifest.xml">
</config-file>
<source-file src="src/android/iPaynowTestPlugin.java" target-dir="src/iPaynowTestPlugin/iPaynowTestPlugin" />
</platform>
</plugin>
修改iPaynowTestPlugin.js
内容如下:
'use strict';
var exec = require('cordova/exec');
var iPaynowTestPlugin = {
verifyPassword: function(sendMsg, onSuccess, onFail) {
return exec(onSuccess, onFail, 'iPaynowTestPlugin', 'verifyPassword', [sendMsg]);
}
};
module.exports = iPaynowTestPlugin;;
关于Node.js 的 module
可以查看这里
(4)配置基本完成,但是我们还需要创建一个 package.json
文件。package.json
是npm的一个描述文件,用于管理等等,
如果没有这个文件在我们添加插件的时候,可能会出现needs a valid package.json
错误而无法安装插件。
生成该文件的命令如下
plugman createpackagejson <directory>
但是目前可能是由于保留字冲突的bug,这个命令无法正常使用,总是提示pkg is not defined
,详细信息在这里。
不过我们可以使用下面的命令生成,开发时按提示常规填写信息即可,发布到npm平台可以再行编辑,在这里查看示例
npm init
到此插件基本配置完成,效果如下
(5)现在我们将本地的插件添加到项目中,我们新建一个项目 pluginTest
,添加iOS和android平台
cordova create pluginTest com.example.pluginTest pluguinTest
cordova platform add ios
cordova platform add android
进入项目的根目录执行命令:
cordova plugin add /Users/liuning1/Playground/iPaynowTestPlugin
卸载拆件使用
cordova plugin rm iPaynowTestPlugin
我们可以看到 在pluginTest/plugins 目录下以及iOS、android工程下都添加了我们自定义的插件。
(6)我们使用iOS项目演示插件的使用。
我们依然可以使用之前使用的代码来调用插件:
cordova.exec(successFunction, failFunction, "iPaynowTestPlugin",
"verifyPassword", [password]);
不过我们已经对插件进行了封装,可以使用更插件名称.插件方法()
来调用插件了:
cordova.plugins.iPaynowTestPlugin.verifyPassword(password, successFunction, failFunction);
其中 cordova.plugins.iPaynowTestPlugin
对应在插件的 plugin.xml
配置文件中的 <clobbers target="cordova.plugins.iPaynowTestPlugin" />
。
再进行进步一的优化,使用匿名函数处理回调,添加插件验证,代码如下:
<!DOCTYPE html>
<html>
<head>
<title>密码验证</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">
function verify() {
//获取输入的字符
var password = document.getElementById("pwd").value;
//调用自定义的验证插件
if (cordova.plugins.iPaynowTestPlugin) {
cordova.plugins.iPaynowTestPlugin.verifyPassword(password,
function() { alert("密码验证成功!");},
function(message){
alert("验证失败:"+message);
});
}else{
alert("未安装插件!");
}
}
</script>
<style> * { font-size:1em; } </style>
</head>
<body style="padding-top:50px;">
<input type="text" id="pwd" >
<button onclick="verify();">验证</button>
</body>
</html>
(7)上传插件到npm平台
上面我们都是在本地进行开发使用,如果想共享和远程安装,就需要上传到npm平台。
现将插件上传到github,然后完善package.json
文件内容,同时需要npm账户,如果没有注册用户,先执行:
npm addUser
已有用户执行登录操作:
npm login
最后执行发布:
npm publish
然后在npm中就可以找到自己上传的包,便可以通过cordova plugin add **
进行插件的安装了。
5 现有项目嵌入Cordova模块
上面的例子中我们都是在 Cordova 创建的iOS 项目中演示,但是当我在现有的 iOS 项目中也是可以嵌入Cordova模块的。
5.1 添加文件
首先需要创建一个新的Cordova项目并添加 iOS 平台。
进入新建Cordova项目的/platforms/ios
文件夹,将cordova、CordovaLib、platform_www、www
以及config.xml
文件复制到新建Xcode项目的根路径中。
将 Cordova/platforms/ios/HelloCordova 目录下的 config.xml,拷贝到 XcodeProject/XcodeProject 目录下:
右键 Add Files to … ,将 CordovaLib.xcodeproj 添加进来
同样 Add Files to … ,将 config.xml 添加进来
把前面拷贝过来的 www 文件夹拖到工程中来(注意选择不复制文件,保持目录结构)
5.2 添加配置
在配置页的 Build Settings -> Other Linker Flags 中添加”-ObjC -all_load”
(5)在配置页的 Build Phases 标签中添加如下两个库
Target Dependencies -> CordovaLib
Link Binary With Libraries -> libCordova.a
点击配置页的 Build Phases 标签坐上角的加号,添加一个 Run Script
名字改成:Copy www directory
去掉 show environment variables in build log 勾选
Shell脚本的内容如下:
NODEJS_PATH=/usr/local/bin; NVM_NODE_PATH=~/.nvm/versions/node/`nvm version 2>/dev/null`/bin; N_NODE_PATH=`find /usr/local/n/versions/node/* -maxdepth 0 -type d 2>/dev/null | tail -1`/bin; XCODE_NODE_PATH=`xcode-select --print-path`/usr/share/xcs/Node/bin; PATH=$NODEJS_PATH:$NVM_NODE_PATH:$N_NODE_PATH:$XCODE_NODE_PATH:$PATH && node cordova/lib/copy-www-build-step.js
5.3 使用CDVViewController
#import <Cordova/CDVViewController.h>
#import <Cordova/CDVCommandDelegateImpl.h>
#import <Cordova/CDVCommandQueue.h>
#import <Cordova/CDVPlugin.h>
- (IBAction)click:(UIButton *)sender {
CDVViewController*cdvController = [[CDVViewController alloc]init];
[self presentViewController:cdvController animated:YES completion:^{
}];
}
6 Ionic/Angular和Cordova
6.1 三者的关系
目前比较流行的一个开发方案是Ionic+Cordova。
Ionic是一个基于谷歌angualr的HTML5框架,它提供了很多 UI 组件和本地原生应用组件,基于PhoneGap/Cordova的编译平台来帮助开发者快速创建跨平台的移动应用。
Ionic是Angular的衍生品,Angular是单独的js库,和jQuery一样能够独立用于开发应用,而Ionic只是对Angular进行了扩展,利用Angular实现了很多符合移动端应用的组件,并搭建了很完善的样式库,是对Angular最成功的应用样例。
即使不使用Ionic,Angular也可与任意样式库,如Bootstrap、Foundation等搭配使用,得到想要的页面效果。
它们在混合开发中扮演的是不同的角色–Ionic/Angular负责页面的实现,而Cordova负责将实现的页面包装成原生应用(Android:apk;iOS:ipa)。
6.1 ioniccreator
一个可视化编辑工具,生成 ionic 项目
点击这里
7 问题解决
7.1 Error: spawn EACCES
ANDROID_HOME=/Users/Chuck/Library/Android/sdk
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
Error: spawn EACCES
原因是cordova中的android项目下可执行文件没有权限执行,解决办法
cd platforms/android/cordova
chmod 777 build log run clean version
或者使用下面命令输出错误的文件路径
cordova build --release --verbose android
//输出
Command finished with error code 0: /usr/libexec/java_home
ANDROID_HOME=/Users/Chuck/Library/Android/sdk
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
Running command: "/Applications/Android Studio.app/Contents/gradle/gradle-4.1/bin/gradle" -p /Users/Chuck/Playground/1124/hello/platforms/android wrapper -b /Users/Chuck/Playground/1124/hello/platforms/android/wrapper.gradle
Error: spawn EACCES
最终解决(空格需要转义)
$ sudo chmod -R 777 /Applications/Android\ Studio.app/Contents/gradle
7.2 npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules
$ npm install -g ios-deploy
npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules
npm ERR! path /usr/local/lib/node_modules
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall access
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR! { Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR! stack: 'Error: EACCES: permission denied, access \'/usr/local/lib/node_modules\'',
npm ERR! errno: -13,
npm ERR! code: 'EACCES',
npm ERR! syscall: 'access',
npm ERR! path: '/usr/local/lib/node_modules' }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/Chuck/.npm/_logs/2017-11-24T07_53_38_901Z-debug.log
** BUILD FAILED **
The following build commands failed:
Check dependencies
Write auxiliary files
(2 failures)
npm ERR! code ELIFECYCLE
npm ERR! errno 65
npm ERR! ios-deploy@1.9.2 preinstall: `./src/scripts/check_reqs.js && xcodebuild`
npm ERR! Exit status 65
npm ERR!
npm ERR! Failed at the ios-deploy@1.9.2 preinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/Chuck/.npm/_logs/2017-11-24T07_55_03_125Z-debug.log
解决办法,使用
sudo npm install -g ios-deploy --unsafe-perm=true
7.3 ARCHIVE FAILED
** ARCHIVE FAILED **
The following build commands failed:
Check dependencies
(1 failure)
Error: Error code 65 for command: xcodebuild with args: -xcconfig,/Users/Chuck/Playground/1124/hello/platforms/ios/cordova/build-debug.xcconfig,-workspace,HelloWorld.xcworkspace,-scheme,HelloWorld,-configuration,Debug,-destination,generic/platform=iOS,-archivePath,HelloWorld.xcarchive,archive,CONFIGURATION_BUILD_DIR=/Users/Chuck/Playground/1124/hello/platforms/ios/build/device,SHARED_PRECOMPS_DIR=/Users/Chuck/Playground/1124/hello/platforms/ios/build/sharedpch
原因是开发者证书没有配置,打开Xcode,配置 signing 即可。