I am trying to upload camera picture from cordova app to firebase storage. It is working fine in webbrowser but not working through cordova. I have searched a lot but not able to find the exact solution.
This is the code i have written:-
onOpenCamera: function(oEvent){
var oImage = this.getView().byId("profilePicId");
navigator.camera.getPicture(onSuccess, onFail, {
quality: 25,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.CAMERA
});
function onSuccess(imageURI) {
//var options = { quality: 100 };
//plugins.crop(function success (newPath) {
oImage.setSrc(imageURI);
var sBusyDialog = new BusyDialog({
customIcon: "Images/loader.gif",
customIconDensityAware: false
});
sBusyDialog.open();
var profileUploadRequest = Firebase.uploadFile('users/'+ Firebase.currentUser().uid + '/Profile.png', imageURI);
profileUploadRequest.then(function(snapshot){
sBusyDialog.close();
var oProfileUpdate = Firebase.updateProfilePic(snapshot.downloadURL);
oProfileUpdate.catch(function(oError){
sBusyDialog.close();
var message = oError.message;
MessageBox.show(message, {
title : oError.code,
icon : sap.m.MessageBox.Icon.ERROR
});
});
});
profileUploadRequest.catch(function(oError){
sBusyDialog.close();
var message = oError.message;
MessageBox.show(message, {
title : oError.code,
icon : sap.m.MessageBox.Icon.ERROR
});
});
/* }, function fail (error) {
MessageToast.show('Failed because: ' + error);
}, imageURI, options);*/
}
function onFail(message) {
MessageToast.show('Failed because: ' + message);
}
},
This is Firebase file:-
uploadFile: function(path, dataUrl){
var storageRef = firebase.storage().ref();
var profileRef = storageRef.child(path);
return profileRef.putString(dataUrl, 'data_url');
},
Please check it once.
I have went through all the stackoverflow solutions like creating a blob, using cordova file plugin. I have read in firebase that cordova doesn't support file upload but download works.
Thanks.
Related
As you can see below, I am using the [src] attribute. What I am trying to do is preview the image taken from a device's camera. Please see the rest of the typescript code below.
<img [src]="lastImage" style="width: 100%" [hidden]="lastImage === null">
<button ion-button icon-left (click)="presentActionSheet()">
<ion-icon name="camera"></ion-icon>Select Image
</button>
Here is .ts code
lastImage: string = null;
public presentActionSheet() {
let actionSheet = this.actionSheetCtrl.create({
title: 'Select Image Source',
buttons: [
{
text: 'Load from Library',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY);
}
},
{
text: 'Use Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA);
}
},
{
text: 'Cancel',
role: 'cancel'
}
]
});
actionSheet.present();
}
public takePicture(sourceType) {
// Create options for the Camera Dialog
var options = {
quality: 100,
sourceType: sourceType,
saveToPhotoAlbum: false,
correctOrientation: true
};
// Get the data of an image
this.camera.getPicture(options).then((imagePath) => {
// Special handling for Android library
if (this.platform.is('ios') && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) {
alert('IF');
this.filePath.resolveNativePath(imagePath).then(filePath => {
let correctPath = filePath.substr(0, filePath.lastIndexOf('/') + 1);
let currentName = imagePath.substring(imagePath.lastIndexOf('/') + 1, imagePath.lastIndexOf('?'));
// alert(correctPath);
alert(correctPath + currentName);
this.lastImage = correctPath + currentName;
// this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
});
} else {
alert('ELSE'); // This part runs
var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
alert(cordova.file.dataDirectory + currentName); // This returns proper image path
this.lastImage = cordova.file.dataDirectory + currentName;
alert(this.lastImage); // this also has the image path.
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
}
}, (err) => {
this.presentToast('Error while selecting image.');
});
}
Now when I choose image Use Camera then it opens the camera and I take a photo. But somehow the photo is not previewed in my above HTML where I am using [src]="lastImage". What is wrong with my code that it does not show any image from the camera?
UPDATE
I also used normalizeURL which I found here like following!
import { normalizeURL } from 'ionic-angular';
this.lastImage = normalizeURL(cordova.file.dataDirectory + currentName);
What happens with this piece of code is that it replaces file:/// part with http://localhost:8080 whereas I am taking a photo from the camera which local not any server and want to display that on img tag.
He, I suggest that use base64 to set image to img tag, check the next code:
Controller atribute
private base64Image: any = false;
In your controller constructor set: "public domSanitizer: DomSanitizer" as parameter, this allow say to angular that the image is "safe".
Controller method
takePicture() {
const options: CameraOptions = {
quality: 10,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
}
this.camera.getPicture(options).then((imageData) => {
// imageData is either a base64 encoded string or a file URI
// If it's base64:
this.base64Image = 'data:image/jpeg;base64,' + imageData;
}, (err) => {
this.message("Error, your camera device not work");
});
}
In your view file
<img *ngIf="base64Image != 'false'" [src]="domSanitizer.bypassSecurityTrustUrl(base64Image)">
import { normalizeURL } from 'ionic-angular';
<img *ngIf="base64Image" src="{{base64Image}}"/>
openCamera(pictureSourceType: any) {
let options: CameraOptions = {
quality: 95,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: pictureSourceType,
encodingType: this.camera.EncodingType.PNG,
targetWidth: 400,
targetHeight: 400,
saveToPhotoAlbum: true,
correctOrientation: true
};
this.camera.getPicture(options).then(imageData => {
if (this.platform.is('ios'))
this.base64Image = normalizeURL(imageData);
// IF problem only occur in ios and normalizeURL
//not work for you then you can also use
//this.base64Image= imageData.replace(/^file:\/\//, '');
else
this.base64Image= "data:image/jpeg;base64," + imageData;
}, error => {
console.log('ERROR -> ' + JSON.stringify(error));
});
}
in my case, when i'm setting src to image tag in my localhost it is giving some unsafe security issue ERR_UNKNOWN_URL_SCHEME.
so i used DomSanitizer to bypassSecurity like below.
constructor(private senitizer: DomSanitizer) {}
this.imageUrl = <string>this.senitizer.bypassSecurityTrustUrl(this.imageUrl);
so check your console and if there is same problem, then instead of 'normalizeURL' use above code to bypass security for localhost.
or if you deploy your code on some secure domain (https), it does not require security bypass.
Probably it passes the LOCATION to the src (instead of URL). You can:
1) Move the picture file (i.e from C:/path/file.jpg ) into the LOCALHOST's www root folder and use url http://localhost/file.jpg in src attribute.
or
2) convert/append image to <canvas> element ( but learn some basics of that)
or
3) As advised already, convert image to BASE64 string (not nice way, but works) and append the data to src.
May this code helps you
App Component
export class AppComponent implements OnInit{
video: any;
canvas: any;
ngOnInit() {
this.startup();
}
startup(): void {
this.video = document.getElementById('video');
this.canvas = document.getElementById('canvas');
const nav = <any>navigator;
nav.getUserMedia = nav.getUserMedia || nav.mozGetUserMedia || nav.webkitGetUserMedia;
const self = this;
navigator.mediaDevices.getUserMedia({video: true, audio: false})
.then(function (stream) {
self.video.srcObject = stream;
self.video.play();
});
}
onBtnClicked(event: Event): void {
this.takePicture();
event.preventDefault();
}
takePicture() {
const context = this.canvas.getContext('2d');
context.drawImage(this.video, 0, 0, 100, 100);
}
}
And component's template is :
<div class="camera">
<video id="video" #video
width="width"
height="height"
(canplay)="onCanPlay($event)">
Video stream not available.
</video>
</div>
<canvas id="canvas" #canvas
width="width"
height="height">
</canvas>
<button (click)="takePicture()">Take Picture</button>
For detail check this
view template:
<img style="margin:5px; width: 100%" *ngIf="imageURL" src={{this.imageURL}} #myImage (click)="presentImage(myImage)" imageViewer/>
<button ion-button icon-left (click)="presentActionSheet()">
<ion-icon name="camera"></ion-icon>Select Image
</button>
TypeScript:
import { Camera,CameraOptions, CameraPopoverOptions } from '#ionic-native/camera';
import { ImageViewerController } from 'ionic-img-viewer';
then add 'Camera' in providers:
#Component({
//.....
providers: [Camera],
//....
})
then initialize the given objects:
_imageViewerCtrl: ImageViewerController;
imageURL;
camera: Camera;
then
options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
}
public presentActionSheet(){
this.camera.getPicture(this.options).then((imageData) => {
this.imageURL = 'data:image/jpeg;base64,' + imageData;
this.presentImage(this.imageURL);
}, (err) => {
console.log(err);
});
}
presentImage(myImage) {
const imageViewer = this._imageViewerCtrl.create(myImage);
imageViewer.present();
}
I am unable to get cordovaCapture.captureVideo to work. Using cordovaCamera lets me use the camera to take photos and choose photos from the library without any problems but I am trying to to use cordovaCapture to use take a video on iOS, I would also like to get a thumbnail or image preview of the video to show on the view once the video is taken.
I have included the code below which uses both cordovaCamera and cordovaCapture. I have followed the examples on ngCordova website.
.controller("CameraController", function($scope, $cordovaCamera, $cordovaCapture) {
$scope.takePhoto = function () {
var options = {
quality: 75,
cameraDirection: Camera.Direction.FRONT,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
$cordovaCamera.getPicture(options).then(function (imageData) {
$scope.imgURI = "data:image/jpeg;base64," + imageData;
}, function (err) {
// An error occured. Show a message to the user
});
}
$scope.choosePhoto = function () {
var options = {
quality: 75,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
$cordovaCamera.getPicture(options).then(function (imageData) {
$scope.imgURI = "data:image/jpeg;base64," + imageData;
}, function (err) {
// An error occured. Show a message to the user
});
}
$scope.captureVideo = function() {
var options = { limit: 1, duration: 15 };
$cordovaCapture.captureVideo(options).then(function(videoData) {
// Video data
}, function(err) {
// An error occurred. Show a message to the user
});
}
})
I see that you use $cordovaCamera and $cordovaCapture inside controller.
This means that you need to install both
$ cordova plugin add cordova-plugin-camera from $cordovaCamera
and
$ cordova plugin add cordova-plugin-media-capture from $cordovaCapture
If takePhoto() works, but captureVideo() does not, this means that you did not install $cordovaCapture.
I have generated a PDF invoice using the file plugin. Now I want to open the file in the app. I tried inAppBrowser, but its giving an empty page. I tried fileopener, its neither giving a success or failed message. How do I specify the path to my file . please help!!
In app Browser Method
var cdr='';
window.resolveLocalFileSystemURL(cordova.file.externalDataDirectory, function(dir) {
cdr=dir;
alert("cdr "+cdr);
dir.getFile("test.pdf", {create: true, exclusive: false}, function (fileEntry)
{
fileEntry.createWriter(function (writer) {
writer.onwrite = function(evt) {
console.log(" write success");
};
console.log("writing to file");
writer.write( pdfOutput );
},function () {
console.log("ERROR SAVEFILE");
});
});
});
window.resolveLocalFileSystemURL(cordova.file.externalDataDirectory, function(dir) {
alert("open file");
dir.getFile("test.pdf", {create:false}, function(fileEntry) { //EXISTS
alert("native url "+cdr.toNativeURL());
var url =cdr.toNativeURL() + "test.pdf";
alert(url);
window.open(url, '_blank');
}, function() { //NOT EXISTS
alert("no file found");
});
});
}
Fileopener Method
var cdr='';
window.resolveLocalFileSystemURL(cordova.file.externalDataDirectory , function(dir) {
cdr=dir;
console.log(" vidhya cdr "+cdr);
dir.getFile("test.pdf", {create: true, exclusive: false}, function (fileEntry)
{
fileEntry.createWriter(function (writer) {
writer.onwrite = function(evt) {
console.log("vidhya write success");
openFile(cdr);
};
console.log("vidhya writing to file");
writer.write( pdfOutput );
},function () {
console.log("vidhya ERROR SAVEFILE");
});
});
});
function openFile(cdr) {
var fs;
function fsSuccess(fileSystem)
{
fs = fileSystem;
console.log("vidhya "+fs);
}
function fsFail(event)
{
console.log(event.target.error.code);
}
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, fsSuccess, fsFail);
console.log("vidhya opening file " +cdr.toNativeURL());
cordova.plugins.fileOpener2.open(
fs.root.toURL() +'test.pdf',
"application/pdf", //mimetype
{
error: function(e) {
alert("Error Opening the File.Unsupported document format.");
},
success: function() {
// success callback handler
alert("success");
}
}
);
}
My file is getting saved in /internal storage/Android/Data/app_folder/files/test.pdf
This is how i made it work in my hybrid mobile app:
var cdr;
sessionStorage.platform = device.platform;
var fileTransfer = new FileTransfer();
if (sessionStorage.platform.toLowerCase() == "android") {
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory, onFileSystemSuccess, onError);
} else {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFileSystemSuccess, onError);
}
function onError(e) {
navigator.notification.alert("Error : Downloading Failed");
};
function onFileSystemSuccess(fileSystem) {
var entry = "";
if (sessionStorage.platform.toLowerCase() == "android") {
entry = fileSystem;
} else {
entry = fileSystem.root;
}
entry.getDirectory("Cordova", {
create: true,
exclusive: false
}, onGetDirectorySuccess, onGetDirectoryFail);
};
function onGetDirectorySuccess(dir) {
dir.getDirectory("My_App", {
create: true,
exclusive: false
}, onGetDirectorySuccess1, onGetDirectoryFail);
};
function onGetDirectorySuccess1(dir) {
cdr = dir;
dir.getFile(filename, {
create: true,
exclusive: false
}, gotFileEntry, errorHandler);
};
function gotFileEntry(fileEntry) {
var documentUrl = "http://myserverurl.com/test.pdf";
var uri = documentUrl;
fileTransfer.download(uri, cdr.nativeURL + docFileNameToView,
function(entry) {
openFile();
},
function(error) {
navigator.notification.alert("Error");
},
false
);
};
function openFile() {
cordova.plugins.fileOpener2.open(
cdr.nativeURL + docFileNameToView,
'application/pdf', {
error: function(e) {
navigator.notification.alert("Error Opening the File.Unsupported document format.");
},
success: function() {
}
}
);
};
function fail(error) {
navigator.notification.alert("Error");
};
function errorHandler(e) {
navigator.notification.alert("Error");
};
function onGetDirectoryFail(error) {
navigator.notification.alert("Error");
};
This code uses cordova file transfer plugin to download pdf and file opener plugin to view the pdf. This sample code also use device plugin to get the device platform (iOS or Android) and dialog plugin to display notification.
Code was tested on iOS 9 and Android 6 devices and works fine. In Android, the file gets stored in storage/emulated/0/Cordova/My_App folder
If someone faces an issue while opening the file stored in device even with proper destination file path specified, please do ensure that the file is downloaded properly without corruption.
Many a times file opening fails due to improper or corrupted download. You can also trace any error during download using chrome inspect devices option. Also ensure to use latest version of file transfer plugin to avoid download error.
I have the following error after taking a picture using the cordova-plugin-camera version 1.2.0 plugin on a SM-G386F device running Android 4.2.2.
My ionic version is 1.1.0
TypeError: Cannot read property 'add' of undefined
at Object.jqLite.addClass (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:46098:56)
at Object.beforeStart (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:40117:17)
at triggerAnimationStart (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:39950:28)
at runNextTask (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:37511:5)
at nextTick (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:37495:7)
at scheduler (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:37466:5)
at file:///android_asset/www/lib/ionic/js/ionic.bundle.js:39942:15
at forEach (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:9163:20)
at file:///android_asset/www/lib/ionic/js/ionic.bundle.js:39923:9
at Scope. (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:24560:36)
Any help would be very appreciated, as I have no idea how to fix that!
Thanks a lot in advance to anybody willing to help :)
I faced same issue before.Then i just followed this tutorial.I got output
1.Capture image
First add the Camera plugin using the command
cordova plugin add org.apache.cordova.camera
HTML
<button ng-click="takePhoto()">Capture</button>
<li ng-repeat="i in myImage">
<img ng-src="{{baseURL+i}}">
</li>
Controller
$scope.takePhoto = function() {
navigator.camera.getPicture(onSuccess, onFail, {
quality: 75,
targetWidth: 320,
targetHeight: 320,
destinationType: 0,
saveToPhotoAlbum: true
});
function onSuccess(imageData) {
$scope.imgURI = imageData;
$scope.myImage.push($scope.imgURI);
$scope.$apply();
}
function onFail(message) {
alert('Failed because: ' + message);
}
};
2.Save photo after capture
If you want to save this photo in your storage.Please add file plugin also,
cordova plugin add org.apache.cordova.file
Controller
$scope.takePhoto = function() {
if (window.cordova) {
var options = {
quality: 100,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.CAMERA,
encodingType: Camera.EncodingType.JPEG,
cameraDirection: 1,
saveToPhotoAlbum: true
};
$cordovaCamera.getPicture(options).then(function(imagePath) {
$scope.imgURI = imagePath;
//Grab the file name of the photo in the temporary directory
var currentName = imagePath.replace(/^.*[\\\/]/, '');
//Create a new name for the photo
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
//Move the file to permanent storage
$cordovaFile.moveFile(cordova.file.tempDirectory, currentName, cordova.file.dataDirectory, newFileName).then(function(success) {
//success.nativeURL will contain the path to the photo in permanent storage, do whatever you wish with it, e.g:
//createPhoto(success.nativeURL);
}, function(error) {
//an error occured
});
}, function(error) {
//An error occured
});
}
};
If you have any doubt.Please let me know.Thanks
I am using below code to select a video from library
navigator.camera.getPicture(function (data) {
callback(true, data);
},
function (e) {
callback(false, null);
}, {
destinationType: navigator.camera.DestinationType.FILE_URI,
sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY,
mediaType: navigator.camera.MediaType.VIDEO
});
But in callback I am getting path in below format
content://media/external/video/media/832
How can I get the original file path?
I know its to late but maybe someone else needs this ( use resolveLocalFileSystemURL then toURL() )
check this code
navigator.camera.getPicture(onSuccess, onFail, {
limit: 1,
mediaType: window.Camera.MediaType.VIDEO,
destinationType: window.Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY
});
function onSuccess(fileURI) {
window.resolveLocalFileSystemURL(fileURI,
function (fileEntry) {
console.log(fileEntry.toURL());
//console.log(fileEntry.fullPath);
},
function () { });
}
function onFail(error) {
console.log(error);
}
step1
cordova plugin add cordova-filepath-resolver
For Ionic specifically, you can also use:
ionic plugin add cordova-filepath-resolver
step2
put this code
function camerasucess(videourl) {
//videourl is something like this content //media/external/video
var successCallback = function (data) {
console.log(JSON.stringify(data));
//here you will get the correct path of the video file and you can upload the video file
$scope.data = data;
};
var errorCallback = function (data) {
console.log(JSON.stringify(data));
};
window.FilePath.resolveNativePath(videourl, successCallback, errorCallback);
};
function cameraError(data) {
alert(JSON.stringify(data));
};
if (navigator.camera)
{
navigator.camera.getPicture(camerasucess, cameraError, {
sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY, mediaType: navigator.camera.MediaType.VIDEO,
});
}