I have developed an android application using Ionic4. I am facing some issues with Ionic Native Camera plugin. The following is my code. The issues that i am facing is given below. The version if camera plugin i am using is "#ionic-native/camera": "^5.3.0",.
Issues
Gallery is not opening
Captured image is not returning.
Application crashes after taking picture
html
<img [src]="studentImage!==null ? studentImage: 'assets/icon/ic_avatar.png'" class="add-picture" (click)="addImage()">
.ts
public addImage() {
this.genericServices.presentActionSheet(this.openGallery, this.openCamera);
}
private openCamera = () => {
this.studentImage = this.genericServices.selectPicture('camera');
console.log('Captured Image:=>' + this.studentImage);
}
private openGallery() {
this.studentImage = this.genericServices.selectPicture('gallery');
}
service
public async selectPicture(source) {
let base64Image = null;
const cameraOptions: CameraOptions = {
quality: 75,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.PNG,
mediaType: this.camera.MediaType.PICTURE,
sourceType: source === 'camera' ? this.camera.PictureSourceType.CAMERA : this.camera.PictureSourceType.PHOTOLIBRARY,
correctOrientation: true
};
await this.camera.getPicture(cameraOptions).then((imageData) => {
console.log('Returned Image=>' + base64Image);
return base64Image = 'data:image/jpeg;base64,' + imageData;
}).catch(() => {
});
}
Hard to say what your problem is. I would probably write the code slightly different, like this:
async selectImage() {
const actionSheet = await this.actionCtrl.create({
header: "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'
}
]
});
await actionSheet.present();
}
And then in the takePicture() method decide what destinationType should be, default is FILE_URI (1).
takePicture(sourceType: PictureSourceType) {
var options: CameraOptions = {
quality: 80,
sourceType: sourceType,
saveToPhotoAlbum: false,
correctOrientation: true,
destinationType: 1,
targetWidth: 1240,
targetHeight: 768,
};
this.camera.getPicture(options)
.then((imageData) => {
// do something with the imageData, should be able to bind it to a variable and
// show it in your html file. You might need to fix file path,
// remember to import private win: any = window, and use it like this.
this.imagePreview = this.win.Ionic.WebView.convertFileSrc(imageData);
}).catch((err) => {
console.warn("takePicture Error: " + err);
});
}
This should work fine... i just tested it. But as i said, there could be several things wrong with your setup. Hope it helps in one way or another... otherwise create a fiddle, and i will gladly look at the code for you.
Related
I'm currently developing a Android app where the user can take his or hers picture and upload it to a PATCH API endpoint that would listen to the key 'avatar'.
I'm using the Cordova Camera and the Advanced HTTP plugin to handle it.
Below is the function that triggers when taking a photo.
takePicture() {
const options: CameraOptions = {
quality: 50,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
correctOrientation: true, // Corrects Android orientation quirks
allowEdit: false, // Post process aanpassingen
sourceType: this.camera.PictureSourceType.CAMERA // Pak de selfie camera
};
this.camera.getPicture(options).then((imageData) => {
const formData = new FormData();
formData.append('avatar', imageData, 'pic.jpg');
this.web.updateUserInfo(formData).subscribe(() => {});
}, (err) => {
console.error('Camera Error: ' + err);
});
}
Here is the API handling
updateUserInfo(newData: any) {
return new Observable((obs) => {
this.http2.patch('localhost/user', {newData}, {
'X-Subdomain': 'host',
'X-Token': this.apiKey,
}).then(() => {console.log('Camera API success!'); obs.next(); }).catch(error => {
console.error(error);
});
});
}
No errors are being given out so it is hard for me to see where the issue is. I have little experience working with Cordova and Ionic so this is all new to me.
Problem is destinationType: this.camera.DestinationType.FILE_URI,
you are sending, file url over http and not the base64 of image
Change your destination type:
destinationType: this.camera.DestinationType.DATA_URL,
DATA_URL Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI or NATIVE_URI if possible
UPDATE
In this video you can check how to send base64 to api as File
https://www.youtube.com/watch?v=tph5Nk4Ab1g
I am building a cordova application and I need to retrieve a blob from an image file and use that as the src of an img tag. Right now the image is stored locally, but will be pulled from a database in the future. Everything is working as expected, but the source of the image is not being set when I use URL.createObjectURL(blob), it seems the url is corrupt.
Here is my code:
takePicture() {
// eslint-disable-next-line no-undef
const srcType = Camera.PictureSourceType.CAMERA;
const options = {
// Some common settings are 20, 50, and 100
quality: 10,
// eslint-disable-next-line no-undef
destinationType: Camera.DestinationType.FILE_URI,
// In this app, dynamically set the picture source, Camera or photo gallery
sourceType: srcType,
// eslint-disable-next-line no-undef
encodingType: Camera.EncodingType.PNG,
// eslint-disable-next-line no-undef
mediaType: Camera.MediaType.PICTURE,
allowEdit: true,
correctOrientation: true, //Corrects Android orientation quirks
};
navigator.camera.getPicture(
function cameraSuccess(imageUri) {
window.resolveLocalFileSystemURL(
imageUri,
function success(fileEntry) {
fileEntry.file(
function(file) {
const reader = new FileReader();
reader.onloadend = function() {
const blob = new Blob([new Uint8Array(this.result)], { type: 'image/png' });
const elem = document.getElementById('img');
elem.src = URL.createObjectURL(blob);
};
reader.readAsArrayBuffer(file);
},
function(e) {
alert(e);
}
);
},
function() {}
);
},
function cameraError(error) {
alert('Unable to obtain picture: ' + error, 'app');
},
options
);
If I remove this line of code: elem.src = URL.createObjectURL(blob);
And replace it with this: elem.src = imageUri;
Everything works fine, so I know the image is being saved correctly. Is it possible that the image is to large, and therefore being rejected?
OK, after doing some more troubleshooting, I figured out the problem was the tag was missing the img-src directive. To fix this I simply added img-src '*' data: blob: ; to the tag, and everything is working.
Note: Just adding '*' did not work. I also had to add blob: as well
I am relatively new to Ionic 2, Cordova & mobile. I followed a sample app to build a simple camera app. It is very similar to the code in a couple of other questions. Running on my android phone, the camera takes the picture but no image is displayed. The "takePicture fired" log entry displays but no further log entries. Is there something I am missing like a permission issue? Can't understand why I am not even seeing a log entry.
Relevant code:
mypage.html
<button ion-button block color="primary" (click)="takePicture()">Take Picture</button>
...
<img [src]="base64Image" *ngIf="base64Image" />
mypage.ts
export class MyPage {
public base64Image: string;
constructor(public navCtrl: NavController) {
}
takePicture() {
console.log("takePicture fired.");
Camera.getPicture({
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 1000,
targetHeight: 1000
}).then((imageData) => {
// imageData is a base64 encoded string
this.base64Image = "data:image/jpeg;base64," + imageData;
if (this.base64Image) {
console.log("base64Image = " + this.base64Image);
}
else {
console.log("base64Image = NULL");
}
}, (err) => {
console.log("An error occurred.");
console.error(err);
});
});
Step 1: In your class.ts
import { Camera } from 'ionic-native';
Step 2: HTML
<img [src]="base64Image" *ngIf="base64Image" (click)="captureImage()"/>
Step 3:
captureImage(){
Camera.getPicture({
quality: 100,
saveToPhotoAlbum: true,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: true,
correctOrientation: false
})
.then((result) => {
this.base64Image = result;
console.log('Image URI: ' + this.base64Image);
}, (error) => {
console.log("ERROR -> " + JSON.stringify(error));
});
}
It's working fine...
Cheers!
I have an app to take photos and upload them when the user synchronises their app. However, it keeps giving me errors after I take the photo and doesnt save it at all to phone.
Here is my code:
(function () {
'use strict';
var serviceId = 'camera';
angular.module('app').service(serviceId, ['$cordovaCamera', '$cordovaFile', '$q', function ($cordovaCamera, $cordovaFile, $q) {
this.takePhoto = function () {
if (window.Camera) {
var options = {
quality: 75,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: false,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 800,
targetHeight: 800,
saveToPhotoAlbum: true,
correctOrientation: true
};
return $cordovaCamera.getPicture(options).then(function (imageData) {
console.log("Photo Success: " + imageData);
return imageData;
}, function (err) {
console.error("Error taking photo: " + JSON.stringify(err));
throw err;
});
} else {
var deferred = $q.defer();
deferred.resolve("/img/sunrise.jpg");
return deferred.promise;
}
}
}]);
})();
What am I doing wrong here?
First make sure that you include the Camera and File plugins in your project.If not please add this two plugins,
cordova plugin add org.apache.cordova.camera
and
cordova plugin add org.apache.cordova.file
I have made small example for you.Here I am using Ionic’s ngCordova to implement the Camera functionality,.
Conroller
$scope.photoSave = 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
});
}
};
HTML
<ion-view>
<ion-content>
<button ng-click="photoSave()">Capture</button>
</ion-content>
</ion-view>
Refer
I would like the user to be able to either take a picture or select an image from his phone's gallery.
I successfully manage to take a picture and get the imageURI.
I'm using Genymotion as emulator since i need to access to some functionalities such as camera. I know there are some other solutions. It is a little bit hard to debug while emulating but this is the only way i found to access to the camera for now. Therefor i can't see what is going on on the second part (Select an image from Gallery).
$scope.uploadPopup = function() {
var uploadPopup = $ionicPopup.show({
title: "Edit profile's picture",
templateUrl: 'templates/partials/upload-img.html',
buttons: [
{
text: '',
type: 'button-energized icon-center ion-ios7-camera',
onTap: function(e) {
// e.preventDefault() will stop the popup from closing when tapped.
e.preventDefault();
alert('Getting camera');
Camera.getPicture({
quality: 100,
saveToPhotoAlbum: false
}).then(function(imageURI) {
alert(imageURI);
$scope.lastPhoto = imageURI;
}, function(err) {
alert(err);
});
}
},
{
text: 'From gallery',
type: 'button',
onTap: function(e) {
e.preventDefault();
alert('Getting gallery');
Camera.getPicture({
quality: 100,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY
}).then(function(imageURI) {
alert(imageURI);
$scope.lastPhoto = imageURI;
}, function(err) {
alert(err);
});
}
}
]
});
};
Service :
app.factory('Camera', ['$q', function($q) {
return {
getPicture: function(options) {
var q = $q.defer();
navigator.camera.getPicture(function(result) {
// Do any magic you need
q.resolve(result);
}, function(err) {
q.reject(err);
}, options);
return q.promise;
}
}
}]);
Is it the correct way to do? Any hints or ideas?
UPDATE :
When i add :
sourceType: Camera.PictureSourceType.CAMERA
to the first function (take a picture from camera). It does not work any more. While without (using the default one probably) it does work.
When i added the sourceType instead of using the default sourceType(CAMERA)
sourceType: Camera.PictureSourceType.CAMERA
It was not working anymore so i guessed something was wrong here.
The correct syntax is :
navigator.camera.PictureSourceType.CAMERA
OR (with different option) :
navigator.camera.PictureSourceType.PHOTOLIBRARY
Not sure why "navigator.camera" and not "Camera", i'm guessing "Camera" is an alias of "navigator.camera".
I think your code is on the right track, like you said it is hard to tell without being able to test it on a device. So i can help you there. go grab the intel xdk https://software.intel.com/en-us/html5/tools. import your ionic project, then make an account. after you log in go to the test tab and push your app to a test server. Then install the intel app preview on your phone/tablet (is on android and ios). open the app, log in, and hit server apps at the bottom, you will see your app and be able to run it on your phone. You can also use the intel xdk to run an app on your phone with live debugging. Hope this helps! cheers!
Here is the code for my ngCordova plugin:
//opens up the phones camera in order to take a picture
//requires module ngCordova and the method $cordovaCamera
//sets Data.Image to a base 64 string
$scope.takePhoto = function () {
document.addEventListener("deviceready", function () {
var options = {
quality: 100,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: false,
encodingType: Camera.EncodingType.PNG,
targetWidth: 800,
targetHeight: 1100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
$cordovaCamera.getPicture(options).then(function (imageData) {
$scope.image = "data:image/png;base64," + imageData;
}, function (err) {
// error
});
}, false);
};