在介绍插件的使用之前,我们有必要先大致了解下插件的原理
一、插件工作原理分析
一个插件是如何正确地在IONIC框架下运行的呢?
前台的HTML/js代码又是如何与后面具体平台做数据交互的呢?
这个就需要对插件的工作原理及各个模块之间的流程关系有一个基本的了解。
为了让插件能够访问具体平台系统的代码,Cordova提供了对应的标准封装API来完成,下面的图简单地示意了Android平台情况下的封装过程:
当用户使用ionic platform add android这个命令之后,
ionic项目会自动将插件下的Java文件copy到platform/android/目录下面,同时将JS也copy到platform/android/目录下,最终使用Android的编译工具(aapt/aidl/dx/apkbuilder等)生成.APK应用程序。
对于一个新建的ionic项目,目录结构如下:
我们添加了一个相机插件,对于该插件下的java文件,可以发现当前整个项目下只有该处存在这个java文件:(在目录:项目根目录pluginscordova-plugin-camerasrcandroid下)
当我们使用ionic platform add android这个命令之后,可以发现,我们的插件相关的java文件被copy到platform/android/目录下面,即(项目根目录platformsandroidsrcorgapachecordovacamera)
当我们用ionic build android命令编译过后,可以发现,这些java文件被编译成了class文件:
二、数据的交互
接着之前的继续。
我们已经清楚JS和ANDROID平台之间分别通过JS的CORDOVA.EXEC()和JAVA的CORDOVAPLUGIN.EXECUTE()函数来对接。
这两个接口的参数对应关系如下所示:
由于JS发送到Java的数据已经作为函数的参数传入, 所以函数中的回调参数,主要是帮助Java侧反馈数据给JS侧所用。
Cordova使用了org.apache.cordova.PluginResult来完成,当中的PluginResult.Staus代表JS调用插件成功与否的状态。
通常代码中判断状态值是否为PluginResult.Staus.OK,来确认调用结果成果或者失败。
此处参考了:http://www.ioniconline.com/plugin-dev-android/
此处参考了:http://blog.csdn.net/luo_xinran/article/details/52163307
三、使用cordova的camera插件
cordova plugin add cordova-plugin-camera
四、插件使用
1、仿微信模式(拍照,从相册选择两种模式),做好模式选择模板(photo.html)
1 <ion-modal-view style="min-height:90px;height:90px;top:40%" id="photo"> 2 <ion-content class="padding" scroll="false" style="height:90px;padding:0px;"> 3 <button class="button button-full button-calm photo" style="100%;marigin-top:0px;marigin-bottom:0px;border-bottom:1px solid white" ng-click="takePhoto(str,data)">拍照</button> 4 <button class="button button-full button-calm photo" style="100%;marigin-top:0px;marigin-bottom:0px;" ng-click="takePhoto1(str,data)">从相册选择</button> 5 </ion-content> 6 </ion-modal-view>
2、modal展示
1 $ionicModal.fromTemplateUrl('templates/photo.html', { 2 scope: $scope 3 }).then(function(modal) { 4 $scope.modal1 = modal; 5 }); 6 $scope.show1 = function(str,taskData) { 7 $scope.str=str; 8 $scope.data=taskData; 9 $scope.modal1.show(); 10 };
3、界面调用modal,展示模板界面:通过选择拍照,调用takePhoto;选择从相册选择,调用taskPhoto1;
<button ng-click="show1('afterImg',taskData)" style="132px;height:173px;background:url('camera.png') no-repeat;"></button>
4、调用摄像头
1 //调用摄像头 2 $scope.takePhoto = function (str,taskData) { 3 $scope.modal1.hide(); 4 document.addEventListener("deviceready", function () { 5 var options = { 6 quality: 100, //相片质量0-100 7 destinationType: Camera.DestinationType.FILE_URI, //返回类型:DATA_URL= 0,返回作为 base64 編碼字串。 FILE_URI=1,返回影像档的 URI。NATIVE_URI=2,返回图像本机URI 8 sourceType: Camera.PictureSourceType.CAMERA, //从哪里选择图片:PHOTOLIBRARY=0,相机拍照=1,SAVEDPHOTOALBUM=2。0和1其实都是本地图库 9 allowEdit: false, //在选择之前允许修改截图 10 encodingType: Camera.EncodingType.JPEG, //保存的图片格式: JPEG = 0, PNG = 1 11 targetWidth: 375, //照片宽度 12 targetHeight: 667, //照片高度 13 mediaType: 2, //可选媒体类型:圖片=0,只允许选择图片將返回指定DestinationType的参数。 視頻格式=1,允许选择视频,最终返回 FILE_URI。ALLMEDIA= 2,允许所有媒体类型的选择。 14 cameraDirection: 0, //枪后摄像头类型:Back= 0,Front-facing = 1 15 popoverOptions: CameraPopoverOptions, 16 saveToPhotoAlbum: true, //照片是否保存到相册 17 correctOrientation:true //此项为true,照片于拍照方向一样(但个别图片依然会出现旋转90度问题);为false图片会选择90度; 18 }; 19 20 $cordovaCamera.getPicture(options).then(function (imageData) { //此处根据实际需求,对上传文件地址(imageData)进行相应的操作,本项目是将其放入数组当中,以便通过ng-reapeat进行循环展示 21 if(str=="img"){ 22 /* $scope.isShow=false;*/ 23 $scope.arrayObj.push(imageData); 24 $scope.id=taskData.id; 25 /* $scope.imageSrc = imageData;*/ 26 }else{ 27 /* $scope.isShowAfter=false;*/ 28 $scope.arrayObj1.push(imageData); 29 $scope.id1=taskData.id; 30 /* $scope.imageSrcAfter = imageData;*/ 31 } 32 /* $scope.uploadPhoto(taskData.id);*/ 33 }, function (err) { 34 // error 35 }); 36 37 }, false); 38 }; 39 //调用摄像头(从相册选择) 40 $scope.takePhoto1 = function (str,taskData) { 41 $scope.modal1.hide(); 42 document.addEventListener("deviceready", function () { 43 var options = { 44 quality: 100, //相片质量0-100 45 destinationType: Camera.DestinationType.FILE_URI, //返回类型:DATA_URL= 0,返回作为 base64 編碼字串。 FILE_URI=1,返回影像档的 URI。NATIVE_URI=2,返回图像本机URI 46 sourceType: Camera.PictureSourceType.PHOTOLIBRARY, //从哪里选择图片:PHOTOLIBRARY=0,相机拍照=1,SAVEDPHOTOALBUM=2。0和1其实都是本地图库 47 allowEdit: false, //在选择之前允许修改截图 48 encodingType: Camera.EncodingType.JPEG, //保存的图片格式: JPEG = 0, PNG = 1 49 targetWidth: 375, //照片宽度 50 targetHeight: 667, //照片高度 51 mediaType: 2, //可选媒体类型:圖片=0,只允许选择图片將返回指定DestinationType的参数。 視頻格式=1,允许选择视频,最终返回 FILE_URI。ALLMEDIA= 2,允许所有媒体类型的选择。 52 cameraDirection: 0, //枪后摄像头类型:Back= 0,Front-facing = 1 53 popoverOptions: CameraPopoverOptions, 54 saveToPhotoAlbum: true, 55 correctOrientation:true 56 }; 57 58 $cordovaCamera.getPicture(options).then(function(imageData) { 59 if(str=="img"){ //标记str中,如果从相册选择的文件是mp4格式,将其放入arrayVideo数组,进行循环显示 60 /* $scope.isShow=false;*/ 61 var type=imageData.split('.'); 62 var last=type.length-1; 63 if(type[last]=='mp4'){ 64 $scope.arrayVideo.push(imageData); 65 } 66 if(type[last]=='jpg'||type[last]=='png'){ 67 $scope.arrayObj.push(imageData); 68 } 69 $scope.id=taskData.id; 70 /* $scope.imageSrc = imageData;*/ 71 }else{ 72 /* $scope.isShowAfter=false;*/ 73 $scope.arrayObj1.push(imageData); 74 $scope.id1=taskData.id; 75 /* $scope.imageSrcAfter = imageData;*/ 76 } 77 /* $scope.uploadPhoto(taskData.id);*/ 78 }, function (err) { 79 // error 80 }); 81 82 }, false); 83 }; 84 $scope.uploadPhoto = function (id,array) { 85 for(var i=0;i<array.length;i++){ 86 var str=array[i].substring(0,4); 87 88 if(str!='http'){ //判断是否已经上传到服务器,如果已经上传,则不再重复上传(服务器获取的以http开头,从相册选择或者拍照的地址以file开头) 89 var url='http://www.xxx.com/uploadProcessFile'; //文件上传地址 90 var options = new FileUploadOptions(); 91 var params = { 92 id: id 93 }; 94 options.params = params; 95 options.fileKey = "uploadFile"; 96 options.fileName = array[i].substr(array[i].lastIndexOf('/') + 1); //获取文件名字,此处如果不写,后台处理默认当图片,则造成选择的是视频,但是上传到服务器上则是无法打开的图片 97 98 $cordovaFileTransfer.upload(encodeURI(url),array[i], options) 99 .then(function (result) { 100 console.log(JSON.stringify(result)); 101 console.log("success"); 102 }, function (err) { 103 console.log(JSON.stringify(err)); 104 console.log("fail"); 105 }, function (progress) { //上传图片进度条展示 106 $timeout(function () { 107 var uploadProgress = (progress.loaded / progress.total) * 100; 108 $ionicLoading.show({ 109 template: "已经上传:" + Math.floor(uploadProgress) + "%" 110 }); 111 if (uploadProgress > 99) { 112 $ionicLoading.hide(); 113 } 114 }) 115 }); 116 } 117 } 118 }; 119
ionic也是在初步的学习当中,如果有好的实现方法,欢迎交流讨论~