ngCordova Camera Plugin

Store Camera Photos Permanently Using PhoneGap, Ionic & ngCordova



·

One of the most commonly used PhoneGap API’s is the Camera API. In the age of the selfie, a phones camera is one of the most commonly used functions of the device – naturally, a lot of apps integrate with this.

It’s simple enough to trigger the devices camera and grab the resulting photo, but there’s one big problem. The photo will eventually disappear. I’m not sure on the exact timeframe, but you can probably kiss your photos goodbye after a few days.

Any photos that are taken using the Camera API are stored in a temporary folder, and after a little while the file will be deleted. This is fine if your app is uploading the picture to a server or otherwise only needs to display the photo temporarily, but if you want to permanently store the photo within your application by referencing its File URI (the location of the photo on the device) you’re going to run into some trouble.

The way to solve this problem is to move the file into permanent storage with PhoneGap’s File API after you take the photo, and then reference that URI within your application instead. This makes the process a bit more tricky though so I’ll show you how to do it step by step.

I’ll be using Ionic’s ngCordova to implement the Camera functionality, which adds a few bells and whistles to make things easier, but you could easily adapt this to use any other framework by referencing the PhoneGap Camera and File API’s in the documentation. If you want some help, you can download an example file further down in this post of a plain PhoneGap implementation (there’s quite a bit more code involved than the ngCordova implementation).

1. Include the plugins in your project

First make sure that you include the Camera and File plugins in your project. If you are using a local version of PhoneGap or ngCordova you will need to run:

cordova plugin add org.apache.cordova.camera

and

cordova plugin add org.apache.cordova.file

If you are using PhoneGap Build you will need to include the plugins in your config.xml file:

    <gap:plugin name="org.apache.cordova.file" />
    <gap:plugin name="org.apache.cordova.camera" />

2. Trigger the getPicture() method

When using ngCordova, we can use the getPicture() method to activate the devices camera and return a photo. The implementation will look something like this:

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){
  //Success
}, function(error){
  //An error occured
});

This will trigger the camera to launch and once the photo is taken we can do whatever we want with the resulting data, which in this case is a path to the image on the device. Typically you might inject that path into an img element, or save it somewhere to display later.

Notice that we are also supplying an options array, this specifies how the camera should behave. In this case I’m saying that I want to receive a File URI as the result, it should use the camera to take a photo, it should return a JPEG image, the front facing camera should be used and a copy of the photo should also be saved tot he users photo album.

For a full list of options see the camera documentation.

NOTE: Remember, if you’re using ngCordova then you need to make sure you require the plugins you need in your controller, i.e:

.controller('MyControllers', function($scope, $cordovaCamera, $cordovaFile){

})

3. Move the file to permanent storage

With the above code we’ve managed to successfully capture a photo and retrieve its file path. It’s only stored in a temporary directory that will eventually be wiped though, so now we need to move it.

You will need to add some additional code that makes use of the File API within the callback function for the Camera. It should look something like this:

$cordovaCamera.getPicture(options).then(function(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
});

What we’re doing in the code above is getting the current directory and file name, and moving it to a new directory with a new file name.

We use the date to create the file name so that each new photo taken will have a unique name, if you just kept the original name then it would overwrite previous photos that were taken.

You can use the success.nativeURL value to do whatever you want with the resulting photo, this will be the path to the photo in permanent storage.

BONUS CONTENT: Want to see how to use the PhoneGap Camera and File API’s to permanently store photos without Ionic / ngCordova? Enter your email address below to get access to the file.

If you’re having any trouble, be sure to leave a comment below!

What to watch next...

  • Pingback: 100 Ionic Framework Resources()

  • Pingback: 100+ Ionic Framework Resources | Dinesh Ram Kali.()

  • Wing Chiu Tong

    Great article! I have a question though. I have followed exactly how you did in the article, but the movefile function results in error 5 (encoding error). Do you know what’s happening?

    Thank you in advance!

  • Nenad Jakovljevic

    I have the errors on cordova variable. It says it is not defined. If you could tell me what am i missing here? … thanks 🙂

  • M Argus

    Hello Joshua Monory,

    I’ve follow your tutorial, and I’m get error that sound like this
    Wrong type for parameter “uri” of resolveLocalFileSystemURI: Expected String, but got Null.

    I think the file have been moved from temp directory to actual directory. But I don’t have any qlue how to resolve it..

    Can you give me any answer ?

  • Roel

    How to include the module for $cordovaFile? Which module? I get this error: Error: [$injector:unpr] Unknown provider: $cordovaFileProvider <- $cordovaFile

    • mubashar shahzad

      there may be a problem that u have not properly added plugin for cordoveFile…The command mentioned above has been updated to “cordova plugin add cordova-plugin-file”..

      While u may also not added ngCordova in app.js modules like “angular.module(‘starter’, [‘ngCordova’])”…

  • thanks for these tips

  • Vivek Gautam

    i am also trying this in ionic2 and angular 2 but getting following error.
    Wrong type for parameter “uri” of resolveLocalFileSystemURI: Expected String, but got Null.

  • Riccardo Proietti

    How I can remove photo saved in the album? This doesn’t work (android):

    window.resolveLocalFileSystemURL(pathtoDelete, function (result) {
    result.remove(function(){
    console.log(‘ok’)
    });
    }

    The method works succesfully, but the photo is already present in the device file system. Sometimes happens that I can see the small preview, and the if I click the photo I see an invalid message with a black background color.

    If I don’t save the photo in the album saveToPhotoAlbum: false, images are saved in the cache and here the method works fine. The images are removed.

    Thank you

  • Riccardo Proietti

    Hi all,

    After the File.move() I save the new path. All works fine but if I show the picture in tag, the picture is rotated of 90 deg.
    This happens in my samsung s7, in other models, huwwei 8p, for example it doesn’t happen.
    I don’t understand what happens, and how I can figure it, beacuse it is not deterministic.

    If I save the picture in the cache app, without moving, I can see the picture in the right orientation in all devices.

    • Riccardo Proietti

      I Solved, passing “correctOrientation: true” to the camera plugin options object.

  • MATRIX.REAL

    Hi,
    i would like to know if it’s possible to save image(.jpg) and video (.mov) to camera roll gallery with specific name ?
    thank you