I am trying to capture image from camera in my cordova application
<div onclick="getImage();">
<img width="60" height="60" id="img0" />
</div>
my getImage function
function getImage()
{
navigator.camera.getPicture(onCaptureTaskPhoto, onFail, {quality: 25,targetWidth: 512, destinationType: destinationType.FILE_URI, correctOrientation: true});
}
my onCaptureTaskPhoto function
function onCaptureTaskPhoto(fileURI)
{
var image1=document.getElementById('img0');
image1.src =fileURI;
image1.width="80";
image1.height="80";
}
Now sometimes i can able to capture the image and put it in src of img. And sometimes its showing exception. and the application will be unfortunately app has stopped.
Internal storage of phone is 400MB.
This is the exception i am getting
E/AndroidRuntime(13231): java.lang.RuntimeException:
Unable to resume activity {com.app/com.app.MainActivity}:
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null,
request=34, result=-1, data=null} to activity
{com.app/com.app.MainActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method
'java.lang.String android.net.Uri.toString()' on a null object reference
here is the complete process how to use camera in ionic...
first of all add camera plugin into your project:
cordova plugin add org.apache.cordova.camera
services.js Code
.factory('Camera', function($q) {
return {
getPicture: function(options) {
var q = $q.defer();
navigator.camera.getPicture(function(result) {
q.resolve(result);
}, function(err) {
q.reject(err);
}, options);
return q.promise;
}
}
});
HTML Code
<button class = "button" ng-click = "takePicture()">Take Picture</button>
<button class = "button" ng-click = "getPicture()">Open Gallery</button>
<img ng-src = "{{user.picture}}">
Controller Code
.controller('MyCtrl', function($scope, Camera) {
$scope.takePicture = function (options) {
var options = {
quality : 75,
targetWidth: 200,
targetHeight: 200,
sourceType: 1
};
Camera.getPicture(options).then(function(imageData) {
$scope.picture = imageData;;
}, function(err) {
console.log(err);
});
};
})
Related
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.
i am trying ion native camera api , thats takin picture as the camera shows up and i can click an image but tha image is not shoing up
i am using android oreo , ionic 3 and latest cordova and running app on a real device
<-- file home.html-->`
<ion-header>
<ion-navbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<button ion-button round (click)="eventofClick()">Round Button</button>
<p><img src="{{image}}" /> </p>
{{image}}
</ion-content>
<--home.ts-- ------------------------------------------------------>
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { Camera, CameraOptions } from '#ionic-native/camera';
#Component({
selector: 'page-home',
templateUrl: 'home.html',
})
export class HomePage {
image: any;
constructor(public navCtrl: NavController, public camera: Camera) {
console.log("constructor");
}
eventofClick() {
console.log("called");
console.log('inside');
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
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 (DATA_URL):
let base64Image = 'data:image/jpeg;base64,' + imageData;
this.image = 'data:image/jpeg;base64,' + imageData;
}, (err) => {
// Handle error
});
}
}
i want after taking picture i want to show it along
what i am getting as output is
and at console i am getting 1549019043619.jpg:1 GET unsafe:data:image/jpeg;base64,file:///storage/emulated/0/Android/data/com.catalyst.android.safra/cache/1549019043619.jpg 404 (Not Found)
Try it, this will return you an FILE_URI of your image. If you are uploading image to the server try to show images from your server after uploading. or You can show it directly with base 64. For Base64 you have to change destinationType: this.camera.DestinationType.FILE_URI to destinationType: this.camera.DestinationType.DATA_URL in CameraOptions.
upload Image and Show it.
takePhoto(){
const options: CameraOptions = {
quality: 80,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY
}
this.camera.getPicture(options).then((imageData) => {
// imageData is either a base64 encoded string or a file URI
// If it's base64 (DATA_URL):
console.log(imageData);
this.imageUpload(imageData) / pass your URL in upload function
}, (err) => {
// Handle error
});
}
imageUpload(path) {
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: 'image',
fileName: '.png',
chunkedMode: false,
//mimeType: "image/jpeg",
}
fileTransfer.upload(path, 'Server_URL', options)
.then((data) => {
let res = JSON.parse(data.response);
if (res.success == true) {
//server will return you image name Push that name into an array and show it on your View
}
}, (err) => {
console.log(err);
});
}
It's an ionic app with $cordovaImagePicker and $cordovaCamera functions in the same controller and both called from the same reservation.html
This is the controller definition:
.controller('AppCtrl', ['$scope', '$timeout', '$ionicModal', '$localStorage', '$cordovaCamera', '$ionicPlatform', '$cordovaImagePicker', function($scope, $timeout, $ionicModal, $localStorage, $cordovaCamera, $ionicPlatform, $cordovaImagePicker){
I installed $cordovaImagePicker using ionic plugin add cordova-plugin-imagepicker and $cordovaCamera using ionic plugin add cordova-plugin-camera
This is the controller code:
$ionicPlatform.ready(function() {
var options1 = {
quality: 50,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
$scope.takePicture = function() {
$cordovaCamera.getPicture(options1).then(function(imageData) {
$scope.registration.imgSrc = "data:image/jpeg;base64," + imageData;
}, function(err) {
console.log(err);
});
$scope.registerform.show();
};
var options2 = {
maximumImagesCount: 1,
width: 800,
height: 800,
quality: 80
};
$scope.getPicture = function() {
$cordovaImagePicker.getPictures(options2).then(function (results) {
for (var i = 0; i < results.length; i++) {
console.log('Image URI: ' + results[i]);
$scope.registration.imgSrc = results[i];
}
}, function(error) {
// error getting photos
console.log(error);
});
};
});
}])
I'm running the app on an android 5 phone.
The takePicture function works perfectly.
The getPicture function does not work.
The devTools console shows:
TypeError: Cannot read property 'getPictures' of undefined
at Object.getPictures (file:///android_asset/www/lib/ngCordova/dist/ng-cordova.js:4420:28)
at Scope.$scope.getPicture (file:///android_asset/www/js/controllers.js:132:37)
at fn (eval at <anonymous> (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:26457:15), <anonymous>:4:221)
at file:///android_asset/www/lib/ionic/js/ionic.bundle.js:62386:9
at Scope.$eval (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:29158:28)
at Scope.$apply (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:29257:23)
at HTMLButtonElement.<anonymous> (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:62385:13)
at HTMLButtonElement.eventHandler (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:16583:21)
at triggerMouseEvent (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:2948:7)
at tapClick (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:2937:3)
The error seems to be saying that getPictures is in the scope of Scope.$scope.getPicture but that's not how the code is organised.
I've tried uninstalling and reinstalling $cordovaImagePicker but no change.
After hours of searching for an answer I found this link
https://github.com/ratkop/-cordova-imagePickerEx/issues/8
and reinstalled imagePicker with this :
ionic plugin add https://github.com/b-alidra/-cordova-imagePickerEx.git --save
and it now works without any errors.
So I'm trying to get the camera to take a picture and display it in img tag, simple enough right ? Everything seems fine, I'm able to take a picture and the URI is printed, but I'm getting an error on $scope.$apply(). I'm running it on Android 4.4.4. Here's my code:
.controller("TakePictureController", function($scope, Camera) {
$scope.getPhoto = function() {
Camera.getPicture().then(function(imageURI) {
$scope.src = imageURI;
$scope.$apply();
console.log(imageURI);
}, function(err) {
console.log(err);
});
};
});
.factory('Camera', ['$q', function($q) {
return {
getPicture: function(options) {
var q = $q.defer();
navigator.camera.getPicture(function(result) {
q.resolve(result);
}, function(err) {
q.reject(err);
}, options);
return q.promise;
}
}
}])
and the HTML:
<ion-content class="padding">
<button class="button button-full button-positive" ng-click="getPhoto()">
Take pic
</button>
<img ng-src="{{src}}">
</ion-content>
This is what I get in the console as URI:
file:///storage/sdcard0/Android/data/com.ionicframework.overtredingbe668924/cache/1437826221441.jpg
This is the error I get:
12 237093 error Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.3.13/$rootScope/inprog?p0=%24digest
I tried putting this in
if(!$scope.$$phase) {
$scope.$apply();
}
I don't get the error anymore, but picture is not shown. Any advice ?
I have a service upload imageto amazon s3 after i sign it with my own backend using cordova file-transfer plugin.
I call this service after taking a picture using cordova camera plugin to upload the taken picture to the s3 bucket.
The app sign correctly with my own backend but when it trigger the function upload i get the error i defined in the title.
This is the service that it call an end point in my backend to sign the file and then upload the image to amazon s3:
//Image upload Service
.factory('S3Uploader', function($q, $window, $http, $ionicPopup, API_URL) {
var signingURI = API_URL + "s3signing";
function upload(imageURI, fileName) {
document.addEventListener('deviceready', function() {
console.log('Uploading ' + fileName + ' to S3');
var deferred = $q.defer(),
ft = new FileTransfer(),
options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = fileName;
options.mimeType = "image/jpeg";
options.chunkedMode = false;
console.log('Requesting signed doc ' + signingURI);
$http.post(signingURI, {
"fileName": fileName
})
.success(function(data) {
console.log('Got signed doc: ' + JSON.stringify(data));
options.params = {
"auth": true,
"key": fileName,
"AWSAccessKeyId": data.awsKey,
"acl": "public-read",
"policy": data.policy,
"signature": data.signature,
"Content-Type": "image/jpeg"
};
ft.upload(imageURI, "https://" + data.bucket + ".s3.amazonaws.com/",
function(e) {
console.log("Upload succeeded");
console.log(JSON.stringify(e));
deferred.resolve(e);
$ionicPopup.alert({
title: 'great',
content: 'The image upload to amazon success'
});
},
function(e) {
deferred.reject(e);
$ionicPopup.alert({
title: 'Oops',
content: 'The image upload failed to amazon'
});
}, options);
})
.error(function(data, status, headers, config) {
console.log(JSON.stringify(data));
console.log(status);
$ionicPopup.alert({
title: 'Oops',
content: 'The image upload failed to sign with node'
});
});
return deferred.promise;
}, false); //device ready
}
return {
upload: upload
}
})
and here is the controller code where am calling the camera plugin and in the success of taking the picture am calling the upload function from the S3Uploader service:
.controller('newItemCtrl', function($scope, $http, $ionicPopup, $timeout, $cordovaCamera, API_URL, me, S3Uploader) {
$scope.selectPicture = function() {
document.addEventListener('deviceready', function() {
var options = {
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 300,
targetHeight: 300,
};
$cordovaCamera.getPicture(options).then(function(imageURI) {
$scope.imageSrc = imageURI;
// upload to Amazon s3 bucket
var fileName = new Date().getTime() + ".jpg";
S3Uploader.upload(imageURI, fileName).then(function() {
alert("upload to S3 successed");
});
}, function(err) {
alert(err);
});
}, false); // device ready
}; // Select picture
})
i get the erorr in this line of the controller:
S3Uploader.upload(imageURI, fileName).then(function() {
it's also important to mention am using crosswalk with my ionic app.
Your current implementation of S3Uploader.upload does not return a promise, it returns nothing. Move your declaration and return of the promise to directly inside the S3Uploader.upload function and not nested inside the document.addEventListener code.
Change your code to something like:
.factory('S3Uploader', function($q, $window, $http, $ionicPopup, API_URL) {
var signingURI = API_URL + "s3signing";
function upload(imageURI, fileName) {
var deferred = $q.defer()
document.addEventListener('deviceready', function() {
// Removed for brevity
}, false);
return deferred.promise;
}
return {
upload: upload
}
})
You are creating and returning your deferred object and it's promise from an event listener. Not the upload factory method.
Something along these lines is what you need:
.factory('S3Uploader', function($q) {
function upload() {
var deferred = $q.defer();
// listener logic
return deferred.promise;
}
return {
upload : upload
}
});
You will have problems with this, as you will want a new deferred object for each time the listener is fired. Adding a listener to a factory method to perform something seems like a bad pattern to me. The event should wrap the invocation of the factory method.