最近准备尝试hybird开发原生应用,因为公司的项目本来就是原生开发的,所以准备选择cordova作为webview嵌入原生项目的开发方式。这里就以mac上整合ios项目为例。
1. 创建cordova项目:
1)安装cordova:
sudo npm install -g cordova
2)创建cordova项目:
cordova create hello com.example.hello HelloWorld
这里hello是目标目录名,HelloWorld是项目名称,com.example.hello是项目ID。
创建的项目会包含一个config.xml文件,在这里可以修改项目名称和项目ID以及其他的配置。项目还会包含一个www文件夹,其下包含index.html和css,js,img这些资源目录。www文件夹就是cordova h5项目的资源目录,其下的文件会被保存在设备的文件系统中,而非通过网络下载。这些css,js,img目录的名称和位置都可以*变动(只要在www文件夹下)。index.html是单独的cordova项目的入口,也可以在config.xml中配置成其他文件,而在原生/cordova混合项目中也是可以另外配置的,将在之后说到。
3) 添加平台与启动:
cd hello // 切换到项目文件夹下 cordova platform add ios // 添加ios平台 cordova platforms ls // 列出已添加的平台,此时我们已添加了ios平台 cordova run ios // 编译构建ios平台并启动模拟器运行项目
2. 使用cordova插件:
使用cordova不仅可以将我们的h5项目包装成原生应用,还能使用各种包装好的插件调用原生接口,或是使用cordova包装好的js bridge来开发自己的插件。接下来就以一个toast插件为例,介绍如何在项目中添加插件。
1) 搜索插件:
可以在 https://cordova.apache.org/plugins/ 这里搜索插件
2)添加插件:
cordova plugin add cordova-plugin-x-toast // 添加 cordova-plugin-x-toast 插件 cordova prepare
这是cordova项目自动安装插件的方式,除此之外还有手动安装的方式,将在之后说到。
3)使用插件:
在页面包含的js中调用:
document.getElementById('toast-btn').addEventListener('click', function () { window.plugins.toast.show( 'Hello there!', 'long', 'center', function(info){ console.log('toast success: ' + info) }, function(err){ alert('toast error: ' + err) }) });
以上提到的工作流程都是独立的cordova项目,而我们要做的是在原生项目中嵌入cordova项目。接下来就来看看整合流程。
1)添加项目:
使用Xcode将congig.xml和www目录添加到项目代码目录中。
使用Xcode复制.xcodeproj文件到workspace下并设置构建参数。
在Link Binaries with Libraries中添加需要的框架。
在Build Settings中修改Header Search Paths。
以上步骤可以参考文档,让熟悉Xcode的原生项目开发童鞋来搞一搞,其实这一块的步骤我也不太懂,是原生的小伙伴配置的(不太会用Xcode T_T)。
添加完之后的目录结构类似于:
- 根目录 - 项目代码目录 - config.xml - www目录 ... - .xcworkspace文件 - .xcodeproj ...
2)使用CDVViewController:
在需要使用cordova webview的地方添加代码:
#import <Cordova/CDVViewController.h> // 导入CDVViewController头文件 CDVViewController* viewController = [CDVViewController new]; // 创建CDVViewController实例 viewController.wwwFolderName = @"anotherForder"; // 设置h5文件目录,不设默认就是www目录 viewController.startPage = @"html/page1.html" // 之前提到的,除了config.xml之外,我们还可以在这里设置启动页,不同的CDVViewController实例可以设置不同的启动页 [myView addSubview:viewController.view]; // 将我们的cordova webview显示出来
3)添加插件:
然后是添加插件这一步,需要用手动添加的方式。
回到我们之前的独立cordova项目,我们可以看到在项目目录下的platforms/ios文件夹下也有一个www文件夹,除了我们原本的文件之外,还有一些额外的文件。其中包括指定插件引用的cordova_plugins.js,包含插件js代码的plugins文件夹,我们需要将这两项复制到混合项目的www文件夹下。(cordova_plugins.js是全局插件的配置,因此我们可以在页面中单独包含插件的js文件,而不必将配置添加到cordova_plugins.js)
接下来,修改config.html文件,在feature标签中添加Toast插件:
<feature name="Toast"> <param name="ios-package" value="Toast" /> </feature>
最后还要将独立项目目录下platforms/ios/[项目名称]文件夹下的Plugins文件夹用Xcode复制到混合项目的代码目录下。最后,混合项目的目录结构应该类似于:
- 根目录 - 项目代码目录 - config.xml - www目录 - plugins目录(插件js文件) ... - Plugins目录(插件.h/.m文件) ... - .xcworkspace文件 - .xcodeproj ...
cordova混合项目的优势之一是h5项目我们可以绕过App Store更新代码。这里我们使用cordova-app-loader插件。
1)添加插件:
cordova plugin add org.apache.cordova.file cordova plugin add org.apache.cordova.file-transfer
2)下载CordovaAppLoader的js文件(包含Promise插件bluebird.js,Cordova文件插件cordova-promise-fs.js,manifest下载更新插件cordova-app-loader.js):
cordova-app-loader-complete.js
3)添加初始manifest文件,并添加初始资源文件:
manifest.json:
{ "files": { // 需要下载的文件 "cordova-app-loader-complete": { "version": "76f1eecd3887e69d7b08c60be4f14f90069ca8b8", "filename": "cordova-app-loader-complete.js" }, "autoupdate": { "version": "76f1eecd3887e69d7b08c60be4f14f90069ca8b8", "filename": "autoupdate.js" }, "template": { "version": "3e70f2873de3d9c91e31271c1a59b32e8002ac23", "filename": "template.html" }, "app": { "version": "8c99369a825644e68e21433d78ed8b396351cc7d", "filename": "app.js" }, "style": { "version": "6e76f36f27bf29402a70c8adfee0f84b8a595973", "filename": "style.css" } }, "load": [ // 启动时包含的文件 "cordova-app-loader-complete.js", "autoupdate.js", "app.js", "style.css" ] }
4)引用manifest文件:
在.html文件中添加:
<script type="text/javascript" server="http://data.madebymark.nl/cordova-app-loader/" manifest="manifest.json" src="bootstrap.js"></script>
在deviceready后,manifest.json指定的css/js文件会被添加到页面。
5)更新manifest及文件:
初始化CordovaAppLoader:
var CordovaPromiseFS = require('cordova-promise-fs'); var CordovaAppLoader = require('cordova-app-loader'); var Promise = require('bluebird'); var fs = new CordovaPromiseFS({ Promise: Promise }); var loader = new CordovaAppLoader({ fs: fs, serverRoot: 'http://example.com/', localRoot: 'app', cacheBuster: true, checkTimeout: 10000 });
比对manifest文件并更新:
loader.check().then(function(updateAvailable) { ... }); // 检查localStorage中的manifest与http://example.com/manifest.json的差别 loader.download(onprogress).then(function(manifest){ ... },function(failedDownloadUrlArray){ ... }); // 按照更新的manifest文件更新下载新的依赖,下载的文件将被保存到设备的本地存储 loader.update(); // 重新加载页面 loader.update(false); // 将manifest保存到localStorage,但不重载页面,内容将在下一次进入是更新
如果新内容加载失败,项目将回退到初始打包的manifest状态。