iOS-Cordova集成开发,已有项目集成cordova

iOS-Cordova集成开发,已有项目集成cordova

项目组准备开发一个APP,要求Android和iOS端页面彻底一致,除了一个页面跟业务相关的不一样,其余界面基本一致,所以,萌生一个想法,关于webAPP的想法。因而乎苦逼的咱们开始调研可行性以及总体的方案流程。为了达到除了业务数据页面用web,其余页面全是原生APP的做用。其中,关于业务的web页面须要调用原生的相机,相册,地理位置,麦克风,扬声器,扫描二维码等一系列功能,这就涉及到js与原生交互的问题了。
咱们iOS端提出的方案是直接用WebView或者用WKWebView嵌套在实现web与原生的交互就能够了,不过安卓同事说安卓由于其平台多样性和特殊性这个就不兼容并且可行性交差,列出了集中方案,最终肯定双方都用Cordova实现该功能。而后,开始了iOS端关于Cordova的学习之路(若是已经集成,请下翻到5节)javascript

1 Cordova简介

Cordova前身是phonegap,而PhoneGap是Nitobi软件公司2008年推出的一个框架,旨在弥补web和iOS之间的不足,使得web和iPhone SDK之间的交互更容易。后来又加入了Android SDK 和BlackBerry SDK,再而后又陆续加入了更多的平台。可是在2011年,Nitobi公司被Adobe收购,PhoneGap也被提交到Apache Incubator。因为Adobe如今拥有PhoneGap商标,PhoneGap v2.0版产品就改名为Apache Cordova。css

听说Cordova是Nitobi团队当时坐落的街道名称,用此名来记念Nitobi团队的贡献。Apache Cordova是从PhoneGap中抽出的核心代码,是驱动PhoneGap的核心引擎。html

1.2 Cordova的工程结构

有下图能够看出,关于Cordova的工程结构以及与Native API之间的关系:java


 
cordova机构图.png

由上图能够看出,其实Cordova的使用分为上面几个框架结构,在Native与web之间交互。node

2 Cordova安装

2.1 准备工做

由于本人从事iOS工做,因此只阐述在Mac端安装Cordova的步骤及解释,至于windows下安装Cordova的步骤,这里再也不赘述。
(1)首先,你要有一台Mac电脑,若是没有,那么,你就把这篇文章关了吧,看了也没什么用。
(2)而后你须要安装xcode,固然,你要开发,这一点必不可少。
(3)你须要申请证书,而后在xcode中设置配置文件开发者帐号...(可后面再作)。
(4)好了,你能够开始安装Cordova了。jquery

2.1 安装Node.js

要安装Cordova,须要先安装Node.js在Node.js官网,上下载并安装,下载好之后,一步一步点击下去就好。若是你实在不会,能够参考文章Mac下安装Node.jslinux

 
nodejs.png

 

2.2 安装git

git通常不用安装,osx和linux都自带git,能够在命令行输入git --version检查一下。若是没有git,须要到git官网下载安装一个git客户端。ios

 
git.png

 

2.3 使用node.js的依赖包管理工具npm来进行cordova安装

接下来,在终端输入命令:git

sudo npm install -g cordova

 

 

过程可能稍微有点枯燥和漫长,请耐心等待,其实须要输入的安装命令只有npm install -g cordova,之因此输入sodu,是由于有点Mac直接输入前一句代码是安装不起的,安装效果以下图:
 
install.png

为了写文章因此第二次安装,第一次安装的效果不记得了,哈哈~github

3 建立你的第一个Cordova工程

3.1 新建项目

继续,打开终端,cmd切换目录到工做目录下,输入如下命令,一样,可能须要点时间来完成

cordova create Demo com.cordova.demo.hello HelloWorld 

参数描述:
Demo(参数是必填):将为你的项目生成一个Demo目录 www子目录是应用程序的主页,以及各类资源(css,js,img),遵循共同的web开发文件命名规范。这些资源将存储在设备上的本地文件系统,而不是远程服务。config.xml文件包含重要的须要生成和分发应用程序的元数据。
com.cordova.demo.hello(参数可选):App ID,若是不填写这个参数,第三个参数就要省略,默认值是 io.cordova.hellocordova,但建议你填写一个适当的值。
HelloWorld(参数可选):应用程序的项目名 这个参数的默认值是 HelloCordova,但建议你填写一个适当的值。

3.2 添加平台支持

全部后续命令在项目的目录中进行,可在该项目任何子目录中,cmd切换到项目目录下:

cd Demo 

在构建项目以前,你须要指定一组目标平台。你可以运行这些命令取决于您的机器是否支持每个SDK,合理是否已安装SDK。在MAC上运行命令:

cordova platform add ios

若是须要查看Cordova支持平台以及已经添加的平台,终端输入命令:

cordova platforms ls

3.3 添加插件

根据项目具体功能须要,可添加插件以简单方便调用原生接口,如需添加插件,能够去Cordova插件库搜索须要的插件:

cordova plugin add com.phonegap.plugins.barcodescanner cordova plugin add org.apache.cordova.file-transfer cordova plugin ls 

并不是全部的插件都是全平台支持的,有些可能只支持安卓,也有的可能同时支持安卓和iOS,因此在多平台开发时,请慎重选择插件。我的建议,可自定义插件类,可参考官网Cordova自定义插件

3.4 迭代项目

// 在工程目录下运行下面的命令来构建项目: cordova build // 或者,指定生成iOS平台代码项目: cordova platform add iosiOS_Cordova 

4 运行项目

4.1 打开工程

步骤走完第三章,那么,一个简单的Cordova项目就已经搭建完成了,如今,咱们运行下咱们工程。打开目录下

/Users/****/Desktop/测试cordova/Demo/platforms/ios 

为了不引发混淆,建议移除掉下图中两个文件/文件夹引用(应用哦):

 
config.png

4.2 EventsCordova生命周期事件

生命周期函数 释义
deviceready 当Cordova加载完成会触发
pause 当应用程序进入到后台时触发
resume 应用程序从后台进入到前台会触发

4.3 Plugin APIs自定义Plugin方法

这里看Api就能够的。

到此cordova环境的搭建集成基本完成了。有一些项目已经完成了忽然要集成cordova,该怎么办呢?往下看。

5 将Cordova本地相关文件copy到已存的项目中

5.1 找到相关路径,复制文件到工程目录

首先,进入到上一篇文章中建立的Cordova项目的路径中/Users/****/Desktop/Demo/platforms/ios,找到下面须要copy的4个文件夹( CordovaLib ,cordova, www, platform_www

 

)copy到工程项目的根路径中,以下
 
copy.png

5.2 拷贝对应的config.xml文件到对应的工程目录

而后将下面图中所示的config.xml文件copy到须要的iOS项目路径文件夹内,如图:


 
config

6 配置相关参数

6.1 打开工程,进入工程TARGETS -> Build Phases 下,而后入下图所示,点击①中的按键,建立New Run Script Phase,②为建立的Run Script:
 
image
6.2 将下图示意图中,①原名称Run Script修改成Copy www directory;而后讲②中的选项去掉,最后将下面的代码字段复制到③中:
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 

 

 

如图:
 
image
6.3 在工程 Build Settings -> Other Linker Flags 中添加-ObjC -all_load
 
image
6.4 Add Files to ... -> CordovaLib.xcodeproj
 
image
6.5 Add Files to ... -> config.xml
 
image
6.6 Add Files to ... -> www文件夹
 
image
6.7 Schemes按照下图配置,而后编译一次程序(command+R),最后导入下面两项

Build Phases -> Target Dependencies -> CordovaLib

 

Build Phases -> Link Binary With Libraries -> libCordova.a
 
image
6.8 Schemes按照下图配置,将"ViewController.h" 文件改成:
#import <Cordova/CDVViewController.h> #import <Cordova/CDVCommandDelegateImpl.h> #import <Cordova/CDVCommandQueue.h> @interface ViewController : CDVViewController @end 

至此,Cordova嵌入已存的开发项目就已经完成了,运行程序就可看到工程中www文件目录下,index.html文件中的网页信息了。只须要将该文件内容,改成公司须要的网页内容便可。具体交互以及自定义插件,将在后面文章中介绍。

自定义插件

7.1 在config.xml文件中加入下面代码:

<feature name="YourPluginName"> <param name="ios-package" value="Plugin" /> <param name="onload" value="true" /> </feature> 
 
config.png
3.1 建立一个Plugin类,实现下面的方法

下面介绍一个简单的web端调用原生手机相机以及选择相册图片并返回web显示的自定义插件调用:

  • (1)YanSYPlugin.h 的实现
#import <Cordova/CDVPlugin.h> @interface Plugin : CDVPlugin { UIImagePickerController *_imagePickerController;//相机 } - (void)myMethod:(CDVInvokedUrlCommand *)command; @end 
  • (2)YanSYPlugin.m 的实现
#import "Plugin.h" typedef void(^imgBlock)(NSString *data); @interface Plugin() <UIImagePickerControllerDelegate, UINavigationControllerDelegate> @property (copy, nonatomic) imgBlock myBlock; @end @implementation Plugin - (void)myMethod:(CDVInvokedUrlCommand *)command { [self.commandDelegate runInBackground:^{ NSString* myarg = [command.arguments objectAtIndex:0]; if (myarg !=nil) { [self switchMethodWithName:myarg andCommand:(CDVInvokedUrlCommand*)command]; }else{ return ; } }]; } // 根据方法选择判断调用具体内容 - (void)switchMethodWithName:(NSString *)name andCommand:(CDVInvokedUrlCommand*)command{ _imagePickerController = [[UIImagePickerController alloc] init]; _imagePickerController.delegate = self; _imagePickerController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; _imagePickerController.allowsEditing = YES; __block CDVPluginResult* pluginResult = nil; NSString * standbyJSStr = [NSString stringWithFormat:@"%@",@"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAVCAYAAACt4nWrAAAEDWlDQ1BJQ0MgUHJvZmlsZQAAOI2NVV1oHFUUPrtzZyMkzlNsNIV0qD8NJQ2TVjShtLp/3d02bpZJNtoi6GT27s6Yyc44M7v9oU9FUHwx6psUxL+3gCAo9Q/bPrQvlQol2tQgKD60+INQ6Ium65k7M5lpurHeZe58853vnnvuuWfvBei5qliWkRQBFpquLRcy4nOHj4g9K5CEh6AXBqFXUR0rXalMAjZPC3e1W99Dwntf2dXd/p+tt0YdFSBxH2Kz5qgLiI8B8KdVy3YBevqRHz/qWh72Yui3MUDEL3q44WPXw3M+fo1pZuQs4tOIBVVTaoiXEI/MxfhGDPsxsNZfoE1q66ro5aJim3XdoLFw72H+n23BaIXzbcOnz5mfPoTvYVz7KzUl5+FRxEuqkp9G/Ajia219thzg25abkRE/BpDc3pqvphHvRFys2weqvp+krbWKIX7nhDbzLOItiM8358pTwdirqpPFnMF2xLc1WvLyOwTAibpbmvHHcvttU57y5+XqNZrLe3lE/Pq8eUj2fXKfOe3pfOjzhJYtB/yll5SDFcSDiH+hRkH25+L+sdxKEAMZahrlSX8ukqMOWy/jXW2m6M9LDBc31B9LFuv6gVKg/0Szi3KAr1kGq1GMjU/aLbnq6/lRxc4XfJ98hTargX++DbMJBSiYMIe9Ck1YAxFkKEAG3xbYaKmDDgYyFK0UGYpfoWYXG+fAPPI6tJnNwb7ClP7IyF+D+bjOtCpkhz6CFrIa/I6sFtNl8auFXGMTP34sNwI/JhkgEtmDz14ySfaRcTIBInmKPE32kxyyE2Tv+thKbEVePDfW/byMM1Kmm0XdObS7oGD/MypMXFPXrCwOtoYjyyn7BV29/MZfsVzpLDdRtuIZnbpXzvlf+ev8MvYr/Gqk4H/kV/G3csdazLuyTMPsbFhzd1UabQbjFvDRmcWJxR3zcfHkVw9GfpbJmeev9F08WW8uDkaslwX6avlWGU6NRKz0g/SHtCy9J30o/ca9zX3Kfc19zn3BXQKRO8ud477hLnAfc1/G9mrzGlrfexZ5GLdn6ZZrrEohI2wVHhZywjbhUWEy8icMCGNCUdiBlq3r+xafL549HQ5jH+an+1y+LlYBifuxAvRN/lVVVOlwlCkdVm9NOL5BE4wkQ2SMlDZU97hX86EilU/lUmkQUztTE6mx1EEPh7OmdqBtAvv8HdWpbrJS6tJj3n0CWdM6busNzRV3S9KTYhqvNiqWmuroiKgYhshMjmhTh9ptWhsF7970j/SbMrsPE1suR5z7DMC+P/Hs+y7ijrQAlhyAgccjbhjPygfeBTjzhNqy28EdkUh8C+DU9+z2v/oyeH791OncxHOs5y2AtTc7nb/f73TWPkD/qwBnjX8BoJ98VVBg/m8AAAEFSURBVDgRY/z969//GO9HDAd3f2agNmDKjX9KE4NBDmXasPwDTgcX14sxPP+vg4JBYsQCJmIVkqNu1HCsoUbTYGEJiBBgCE8SZLCw5WTg4CDeLkt7bgYrB24UFx878JXh+MGvcDGW6ctl4BxSGCCDSxpQk2VPwysUw4l3Kik2Q9XS1HAWkCV//vxn2LL2M8Od6z9Q3AfyOnq4oiggwGF5++YvQ4TzA4Yrl75jUSpGkeFMM3re4DAYi10kCjHt3kb9ohbmBqZHN3/B2FSnmdg4GaluKMxAJitn1FwGk6AGzZRXKcrAykId16Obw2RgwsmwYJMcg4omBwOlVniH8jFISbPBPQ0Ay3NHXHSKRhIAAAAASUVORK5CYII="]; if ([name isEqualToString:@"调用相机"]) { [self selectImageFromCameraWithBlock:^(NSString *data) { // 因当前转码格式为iOS原生转码,web端没法解析 ,因此百度了一波图片转码成功后复用,若转码格式正确 可直接上传字符串 // NSString *jsStr = [NSString stringWithFormat:@"data:image/png;base64,%@",data]; // 使用备用字符串上传 pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:standbyJSStr]; [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; }]; }else if ([name isEqualToString:@"查看相册"]){ [self selectImageFromAlbumWithBlock:^(NSString *data) { // 因当前转码格式为iOS原生转码,web端没法解析 ,因此百度了一波图片转码成功后复用,若转码格式正确 可直接上传字符串 // NSString *jsStr = [NSString stringWithFormat:@"data:image/png;base64,%@",data]; // 使用备用字符串上传 pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:standbyJSStr]; [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; }]; }else { pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"You Are Error"]; [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; } } #pragma mark 从摄像头获取图片或视频 - (void)selectImageFromCameraWithBlock:(imgBlock)block{ self.myBlock = block; _imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera; //相机类型(拍照、录像...)字符串须要作相应的类型转换 //视频上传质量 //UIImagePickerControllerQualityTypeHigh高清 //UIImagePickerControllerQualityTypeMedium中等质量 //UIImagePickerControllerQualityTypeLow低质量 //UIImagePickerControllerQualityType640x480 _imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh; //设置摄像头模式(拍照,录制视频)为录像模式 _imagePickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto; [self.viewController presentViewController:_imagePickerController animated:YES completion:nil]; } #pragma mark 从相册获取图片或视频 - (void)selectImageFromAlbumWithBlock:(imgBlock)block{ self.myBlock = block; _imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; [self.viewController presentViewController:_imagePickerController animated:YES completion:nil]; } #pragma mark UIImagePickerControllerDelegate //该代理方法仅适用于只选取图片时 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(nullable NSDictionary<NSString *,id> *)editingInfo { NSString *encodedImageStr = [self imageProcessing:image]; self.myBlock(encodedImageStr); } //适用获取全部媒体资源,只需判断资源类型 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{ NSString *encodedImageStr = [self imageProcessing:info[UIImagePickerControllerEditedImage]]; self.myBlock(encodedImageStr); [self.viewController dismissViewControllerAnimated:YES completion:nil]; } // 图像处理 若未下载base64者 可不用查看 - (NSString *)imageProcessing:(UIImage *)proImage{ // 判断传过来照片的大小进行裁剪 CGFloat width = proImage.size.width; CGFloat height = proImage.size.height; CGSize size; if (width>height) { size = CGSizeMake(800, 450); }else { size = CGSizeMake(450, 800); } // 建立一个bitmap的context // 并把它设置成为当前正在使用的context UIGraphicsBeginImageContext(size); // 绘制改变大小的图片 [proImage drawInRect:CGRectMake(0,0, size.width, size.height)]; // 从当前context中建立一个改变大小后的图片 UIImage * tailoringImage =UIGraphicsGetImageFromCurrentImageContext(); // 使当前的context出堆栈 UIGraphicsEndImageContext(); // 判断图片大小进行压缩 NSData *imageData = UIImageJPEGRepresentation(tailoringImage,1.0); NSLog(@"imagedata == %lud,size.width = %f==%f",(unsigned long)imageData.length,tailoringImage.size.width,tailoringImage.size.height); if (imageData.length>100*1024) { if (imageData.length>1024*1024) { //1M以及以上 imageData=UIImageJPEGRepresentation(tailoringImage, 0.1); }else if (imageData.length>512*1024) {//0.5M-1M imageData=UIImageJPEGRepresentation(tailoringImage, 0.3); }else if (imageData.length>200*1024) {//0.25M-0.5M imageData=UIImageJPEGRepresentation(tailoringImage, 0.7); } } NSLog(@"imagedata == %lud,size.width = %f==%f",(unsigned long)imageData.length,tailoringImage.size.width,tailoringImage.size.height); // 最后进行 base64 转码 // NSString * encodedImageStr = [GTMBase64 stringByEncodingData:imageData]; // 原生转码方法 NSString * encodedImageStr = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; return encodedImageStr; } @end 
  • (3)编写index.html文件以下
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript" src="cordova.js"></script> <script type="text/javascript" src="cordova_plugins.js"></script> <script type="text/javascript" src="jquery.min.js"></script> <script type="text/javascript"> document.addEventListener("deviceready", yourCallbackFunction, false); function cameraBTClick(){ Cordova.exec(successFunction, failFunction, "YanSYPlugin", "myMethod", ["调用相机"]); } function PhotoAlbumBTClick(){ Cordova.exec(failFunction, failFunction, "YanSYPlugin", "myMethod", ["查看相册"]); } function failFunction(error){ alert("error"); document.getElementById("returnValue").value = img; } function aaaa(){ document.getElementById("2").innerHTML = "<img src='data:image/png;base64," } function successFunction(img){ document.getElementById("returnValue").value = img; document.getElementById("2").innerHTML = "![]("+img+")" } </script> </head> <body> <p>点击下面按钮调用相机拍照</p> <button onclick="cameraBTClick()">调用相机</button> </body> <body> <p>点击下面按钮选择相册照片</p> <button onclick="PhotoAlbumBTClick()">查看相册</button> <button onclick="aaaa()">测试</button> <h1>这是回调结果展现区</h1> <textarea id ="returnValue" type="value" rows="5" cols="40"> </textarea> </body> <body>/Users/YanSY/Desktop/代码运行示意11.gif <p> <img id="1" src=“”/> </p> <p id="2" > </p> </body> </html> 

 

 

将以上代码,按步骤写入程序中,可测试调用原生相机,注意,须要在plist文件中添加隐私权限。运行效果示例以下只作到调用原生相机相册。
 
result.gif

到这里基本结束了,须要Demo的点这里.

这样集成Cordova须要依赖cordova的一个工程,下篇文章介绍一种不须要依赖关系的方式,直接导入相关文件使用。

做者:afyylong 连接:https://www.jianshu.com/p/90605320bb28 来源:简书 简书著做权归做者全部,任何形式的转载都请联系做者得到受权并注明出处。
相关文章
相关标签/搜索