通过一个月的Cordova学习, 我将知识点总结为三部分:
- 纯Cordova开发—不依赖原生平台
- 原生平台混合Cordova开发
- 插件开发
在进行Cordova开发之前, 先花点时间了解一下的Cordova的原理和Cordova的框架结构.
- Cordova是开发跨平台web App的工具, 使用前端技术来开发App, 可以节省成本和快速发布.
- Cordova的底层逻辑是:HTML+CSS搭建页面, 使用JS和原生平台交互来展示原生平台的功能.
- Cordova所有功能是建立在各种插件上的, 所以插件开发是Cordova开发的重点.
纯Cordova开发
这种开发模式不需要各原生平台开发人员参与, 只需要前端猿将开发好的web App放入到Cordova工程中, 然后使用Cordova-CLI(Cordova命令行界面)将web App和各种插件配种好后, 就可以build, run进行各平台的构建和调试了. 以下是纯Cordova开发的步骤:
- Cordova的安装
- 使用Cordova-CLI创建Cordova项目—-创建Cordova项目后, 前端猿就可以在
www/
进行开发, 今后的大部分工作都集中在这个文件下.- 添加平台
- 添加插件
- 构建Cordova项目
- 在各原生平台上运行Cordova App
- Cordova项目更新
一.Cordova的安装
CLI工具需要使用npm来安装, 因为它被发布到了npm.
按照下面步骤来按照CLI:
- 下载和安装Node.js.
- (可选)如果你的电脑没有安装Git的话, 下载和安装git client, 因为后续CLL需要使用git来下载git仓库中的资源. 各OS的安装方法自行百度.
- 使用Node.js中的
npm
来安装cordova
模块.cordova
模块会自动被npm
下载.-
在OS x和linux下
$ sudo npm install -g cordova
如果出现”xx/xx/xx(例如/usr/local/share) permission denyed”的错误,可以在
npm
命令前加上sudo
前缀. -
在window中
C:\>npm install -g cordova
上面的
-g
标志告诉npm
全局安装cordova
. 否则, 它将安装在当前工作目录的node_modules
子目录中.
-
安装之后, 你应该能够在命令行上运行cordova, 不需要参数, 它会打印帮助文本.
二.创建Cordova工程
1.使用CLI命令创建 create
cd到维护源代码的目录, 并创建一个cordova项目:
$ cordova create hello com.example.hello HelloWorld
这将为你的cordova应用程序创建所需的目录结构. 默认情况下, cordova create
脚本会生成一个基于Web的框架应用程序, 其主页是项目下www/目录中的index.html文件
打开Mac终端输入上面的命令, 创建一个Cordova项目, 得到项目目录结构如下:
上面的Create命令的解释:
- 保存项目的路径, 比如上面的”hello”, 该路径是缺省的.
- 项目的id, 默认值是
io.cordova.hellocordova
; 安卓中的Java包名, iOS的bundleID都需要用到这个, 所以最好不要缺省, 或者要好好对待这事, 该值以后可以修改. - 项目的name, 默认是
HelloCordova
, 该值也可以修改, 安卓平台可能会使用该值作为类名. - 上面
id
和name
的都会配到config.xml中
2.使用模板创建工程 –template
使用模板App中的代码可以快速搭建你的cordova-app.
-
首先你要去npm网站上, 使用关键字
cordova:template
来搜索可以用的template. 如下图所示: -
这里我使用第二template-
cordova-template-ngx-onsenui
来创建一个项目, 可以的命令有如下:
$ 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>
- 我选择第一个命令, 在我本地创建如下项目:
cordova create UseCordovaTemplate personal.zxx.cordovatemplate --template cordova-template-ngx-onsenui
无错执行完上面命令后, done! 使用模板生成了一个新项目.
我们来看下, 使用模板创建的项目的和不是模板创建的区别:
发现多了几个文件和一个src
文件夹.
- 接下来添加平台-iOS:
cedardeiMac-6:Desktop zhouxingxing$ cd UseCordovaTemplate/
cedardeiMac-6:UseCordovaTemplate zhouxingxing$ cordova platform add ios
添加成功后, 会在`platforms/`生成一个iOS项目:
- 然后我运行构建, 运行cordova项目
cordova build ios
cordova run ios
发现一个错误:
No target specified for emulator. Deploying to iPhone-X, 12.1 simulator
/Users/zhouxingxing/Desktop/UseCordovaTemplate/platforms/ios/build/emulator/HelloCordova.app/Info.plist file not found.
上网搜索, 发现是因为Xcode 10更新了构建系统, 但cordova并支持, 官方给出的解决方案是手动选择不适用系的构建系统:
# Cordova CLI
cordova run ios --buildFlag='-UseModernBuildSystem=0'
cordova build ios --buildFlag='-UseModernBuildSystem=0'
详细信息请参考:https://github.com/apache/cordova-ios/issues/407
下面的添加平台platform
/插件plugin
/构建build
/运行run
这些命令都需要你刚才创建项目的路径下工作, 比如刚才的*/hello/
.
3.添加平台 platform
- 下面的这些命令必须在上面创建项目的目录下运行, 或者子目录也行
$ cd hello
- 添加你App定位的平台. 我们将添加’ios’和’android’平台并确保它们保存到config.xml和package.json:
$ cordova platform add ios
添加完iOS后, 查看项目结构, 发现在platform
目录下多了一个ios/
, 里面的内容是一个iOS项目目录:
并且安装了一个叫cordova-plugin-whitelist
的插件, 在plugins/
也发现多了一个文件夹.
同样安装Android平台后, `platform`也会多一个安卓项目:
$ cordova platform add android
- 查看你添加的平台:
$ cordova platform ls
运行添加或删除平台的命令会影响项目platform
目录的内容, 其中每个指定的平台都显示为子目录
注意:使用CLI构建应用程序时, 你不应编辑/platforms/目录中的任何文件. Cordova在准备构建应用程序或重新安装插件时, 会定期自动覆盖此目录中的文件.
-
config.xml的变化
更多关于平台的操作(比如, 删除平台, 添加特定版本的平台, 从本地添加平台)请看参考Cordova-CLI参考
4.添加插件 plugin
插件的定义:
- 插件是指能够使Cordova WebView和相应原生平台就行交互的注入代码包. 插件给基于Web的App提供对原生设备和平台功能的访问.
- 本质上是一个js文件+原生类(比如Android的Java类,iOS的OC类), JavaScript接口供前端调用,这影藏了背后的各种native代码的实现.
插件添加和删除
- 插件添加可以通过插件id和Git repo的url来添加:
$ cordova plugin add cordova-plugin-xyprogress //通过插件id
$ cordova plugin add https://github.com/cheerszhou/CordovaPulginForTest.git //通过Git url添加
添加完插件后, 在项目目录的下plugins/
会显示你添加的插件:
而且config.xml中也会注册这些插件:
- 插件删除:
$ cordova plugin rm cordova-plugin-xyprogress
运行上面命令后, 在plugins/
和config.xml
也会删除相应的插件
- 插件更新,先删除,后在添加:
$ cordova plugin rm cordova-plugin-xxxx
$ cordova plugin add cordova-plugin-xxxx
- 列举安装的插件:
$ cordova plugin ls
更多关于如何管理(按版本添加, 插件冲突)插件的命令请参考Cordova-CLI参考
5.构建和运行
创建项目, 添加平台和插件后, 你可以进行构建App了. 在构建之前, 你需要检查你的开发环境是否搭建好了, 因为构建各个平台的App需要的环境是不一样的, 比如iOS你需要安装Mac系统, Xcode, xcode-select, ios-deploy.
- 检查各平台需要的环境要求:
$ cordova requirements
运行上面命令, 你从terminal中可以看到如下提示信息, 安装提示信息去搭建各平台需要的环境:
关于各平台的构建环境, 请看:
1. 安卓平台环境要求
2. iOS平台环境要求
3. Windows平台环境要求
- 使用
$ cordova build
构建所有平台项目, 也可以构建特定平台, 如iOS:
$ cordova build ios
更多关于build的命令请参考Cordova-CLI参考
- 使用
$ cordova run
来构建并运行所有平台, 也可使用下面带选项的命令:
- 在Android平台上,名为Nexus_5_API_23_x86模拟器上运行的当前cordova项目的发布版本. 运行时使用特定构建配置:
cordova run android --release --buildConfig=..\myBuildConfig.json --target=Nexus_5_API_23_x86
- 使用真机或模拟器(如果没有连接设备)在Android平台上运行当前cordova项目的调试版本. 跳过构建:
cordova run android --nobuild
- 在ios设备上运行当前cordova项目的调试版本:
cordova run ios --device
- 枚举可用于运行此应用程序的所有连接设备和可用模拟器的名称:
cordova run ios --list
- 或者模拟器中运行:
cordova emulate ios
//指定模拟器使用的模拟设备:
cordova emulate ios --target iPhone-6s
cordova emulate ios --target iPhone-6s-Plus
运行后, 默认显示的www
下的index.thml页面,下面是iOS和Android运行效果图:
6.调试和测试
-
调试一般通过
cordova run
命令运行各平台模拟上, 可以直观看到结果 -
Cordova创建的iOS/android平台项目是可以直接打开的. Xcode/Android Studio内置的调试/分析工具对你进行iOS/android插件开发时非常有用. 请注意, 在各平台IDE中打开项目时, 建议你不要在IDE中编辑代码. 这将会改变项目的
platform
文件夹(而不是www
)中的代码, 并且更改可能会被覆盖. 相反, 你应该编辑www
文件夹中的代码, 并通过运行cordova build
复制你的更改到各个平台. -
插件开发者如果要在native IDE中进行开发时, 可以用
--link
标志来将他们开发插件通过cordova plugin add
加入项目中. 这样插件链接的文件会相互影响—platform
中的插件文件改变会反映在插件的原文件中(反之亦然). -
使用Safari和Chrome进行调试
三.升级Cordova和项目
- 安装cordova工具后, 你始终可以通过运行以下命令将其更新到最新版本:
$ sudo npm update -g cordova
- 使用此语法安装特定版本:
$ sudo npm install -g cordova@3.1.0-0.2.0
- 运行
cordova -v
以查看当前正在运行的版本. 要查找最新发布的cordova版本, 你可以运行:
$ npm info cordova version
- 要更新你要定位的平台:
$ cordova platform update android --save
$ cordova platform update ios --save
...etc.
原生平台混合Cordova开发
可以在原生App使用Cordova中的web页面, 这节分为块内容, 分别是:
- iOS项目中混合Cordova
- Android项目中混合Cordova
在iOS项目中混合Cordova
一.将Cordova项目资源添加到Xcode项目中
-
首先你有一个iOS原生项目, 比如CordovaHybridByPod
-
你有一个Cordova项目, 如果没有使用
cordova create
创建一个, 并添加iOS平台, 因为后面需要用到cordova项目中的内容 -
打开你的iOS项目, 然后将cordova中的顶层config.xml文件复制到iOS项目下, 并且选择Create groups for any added folders
-
将
CordovaLib/CordovaLib.xcodeproj
复制到Xcode项目中 -
在Xcode项目导航栏中选择
CordovaLib.xcodeproj
, 然后在File Inspector中, 设置Location为Relative to Group -
选中Xcode项目的target, 然后在Build Settings中的Other Linker Flags中添加
-force_load
和-Objc
注:这里有个bug, 官网说添加
-force_load
和-Objc
, 发现添加-force_load
后, 原生buildbuild报错. 所以网上有人推荐添加-all_load
和-Objc
. -
打开Build Phases中的Link Binaries with Libraries, 将下面的库添加进去:
AssetsLibrary.framework
CoreLocation.framework
CoreGraphics.framework
MobileCoreServices.framework
-
打开Target Dependencies和Link Binaries with Libraries都加入
CordovaLib
build后的产物CordovaLib.a
, 如果看不到libCordova.a
, 可以在Cordova项目目录下运行cordova build
命令. -
在Build Settings中的Header Search Paths.加入下面这些值:
"$(TARGET_BUILD_DIR)/usr/local/lib/include"
"$(OBJROOT)/UninstalledProducts/include"
"$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include"
"$(BUILT_PRODUCTS_DIR)"
二.使用CDVViewController
- 添加下面的头文件:
#import<Cordova/CDVViewController.h>
- 创建一个新
CDVViewController
实例, 在其他地方使用时, 强引用它:
CDVViewController* viewController = [CDVViewController new];
- (可选)设置
wwwFolderName
属性, 默认为www
:
viewController.wwwFolderName = @"myfolder";
- (可选),在
config.xml
中<content>
标签中设置start page, 也可以是本地文件:
<content src="index.html"/>
…或者一个远程地址:
<content src="http://apache.org" />
- (可选),设置属性
useSplashScreen
, 默认值为NO
:
viewController.useSplashScreen = YES;
- 设置view frame, 总要设置为最新的值:
viewController.view.frame = CGRectMake(0,0,320,480);
- 添加Cleaver到view中:
[myView addSubview:viewController.view];
- 首先我将cordova中的包含
index.html
添加到Xcode项目, 然后在ViewController.m中使用CDVViewController
如下:
```
//
// ViewController.m
// CordovaHybridByPod
//
// Created by developer_zxx on 2018/12/13.
// Copyright © 2018 developer_zxx. All rights reserved.
//
#import "ViewController.h"
#import <Cordova/CDVViewController.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)showCordovaWebview:(UIButton *)sender {
CDVViewController * cordovaVC = [[CDVViewController alloc]init];
cordovaVC.wwwFolderName = @"www";
[self presentViewController:cordovaVC animated:YES completion:nil];
}
@end
```
-
运行结果:
-
之后Cordova中的webView就交给
www
下的前端资源来管理了
在Android项目中混合Cordova
-
首先你有一个Android原生项目, 比如NativeProjectForAndroid
-
你有一个Cordova项目, 如果没有使用
cordova create
创建一个, 并添加Android平台, 因为后面需要用到cordova项目中的内容 -
将Cordova项目中的
platforms/android/
下的res/config.xml
,assets/www/
下的文件添加到你安卓项目相应的目录下 -
将将Cordova项目中的
platforms/android/
下的CordovaLib
作为Android项目的moudle导入
-
将
cordova-plugin-whitelist
插件的Java实现类添加到Android项目,该类在platforms/android/src/java
中可以找到. -
此时你可以在Android原生项目中使用
CordovaActivity.java
, 该类显示www
下的资源, 在MainActivity.java
中跳转到Cordova Webview中. -
运行结果:
插件开发
Cordova项目中大量使用插件, 除了Cordova平台提供的核心插件外, 开发者需要针对一些额外需求自定义开发插件.
一. 插件工作的原理
- Cordova插件是通过JavaScript对外提供接口来访问native功能, 从而能让前端在web app中开发类似native的功能.
- 每个JavaScript对外提供的方法最终是通过调用Cordova提供的
cordova.exec
方法来调用native中的方法 - 插件中方法最终都是调用native方法, 所以需要相应的native方法实现
- 插件开发包含三个主要部分分别是:JavaScript接口, 原生类的实现, config.xml配置文件
二. 插件开发示例
下面按步骤讲解一个插件开发,该插件实现toast功能
A.搭建插件结构
- 当你打算去写一个插件时, 最好先去阅览一遍已存在的插件, 这样你就可以有的放矢, 并且可以去github看相应的源代码.
- 上面的插件结构你可以手动创建, 也可以使用plugman来帮你搭建, 最好使用plugman(如果没有安装, 可以使用
npm install -g plugman
)来搭建, plugman搭建如下:
命令:plugman create --name [插件名] --plugin_id [插件ID] --plugin_version [插件版本号]
例子:plugman create --name ZxxToast --plugin_id cordova-plugin-zxxToast --plugin_version 1.0.0
-
上面的插件文件结构边包含:
- www,里面是一个js文件,插件的JavaScript接口部分
- src,原生平台代码实现,可以包含Android,iOS,WP等,你要支持哪个平台,就在下面创建一个平台子文件夹,如某个已经发布的插件:
- config.xml, 该文件起配置作用,制定插件的关键信息,初始如下, 后面还需对其进行编辑:
B.创建JavaScript接口
接下来是创建给前端调用的js接口,这里需要一些前端知识。
-
打开插件目录下
www
中的ZxxToast.js文件,在ZxxToast.js中提供你想要的输出的接口function ZxxToast() { } ZxxToast.prototype.optionsBuilder = function () {//构建传给native的参数 // defaults var message = null; var duration = 1.0; var position = "center"; var addPixelsY = 0; return { withMessage: function(m) { message = m.toString(); return this; }, withDuration: function(d) { duration = d.toString(); return this; }, withPosition: function(p) { position = p; return this; }, withAddPixelsY: function(y) { addPixelsY = y; return this; }, build: function() { return { message: message, duration: duration, position: position, addPixelsY: addPixelsY }; } }; }; ZxxToast.prototype.showWithOptions = function (options, successCallback, errorCallback) { options.duration = (options.duration === undefined ? 'long' : options.duration.toString()); options.message = options.message.toString(); cordova.exec(successCallback, errorCallback, "Toast", "show", [options]);//调用原始api,Toast为原始类名 ,show为原始类提供的方法 }; //js 提供给外部的api ZxxToast.prototype.show = function (message, duration, position, successCallback, errorCallback) { this.showWithOptions( this.optionsBuilder() .withMessage(message) .withDuration(duration) .withPosition(position) .build(), successCallback, errorCallback); }; ZxxToast.install = function () { if (!window.plugins) { window.plugins = {}; } window.plugins.ZxxToast = new ZxxToast(