在介紹插件的使用之前,我們有必要先大致了解下插件的原理
一、插件工作原理分析
一個插件是如何正確地在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文件:(在目錄:項目根目錄\plugins\cordova-plugin-camera\src\android下)
當我們使用ionic platform add android這個命令之后,可以發現,我們的插件相關的java文件被copy到platform/android/目錄下面,即(項目根目錄\platforms\android\src\org\apache\cordova\camera)
當我們用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="width: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="width: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="width: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也是在初步的學習當中,如果有好的實現方法,歡迎交流討論~