This Cordova/Phonegap plugin provides access to photo library on device.
Only iOS and Android are supported for now - please feel free to make your pull requests for new platforms.
Please note that this plugin deals with photo images only - not videos or any other media data.
- Using
- More Info
$ cordova plugin add cordova-plugin-photos
or last, fresh version right from Github:
$ cordova plugin add https://github.com/domax/cordova-plugin-photos.git --save
Since Android plugin implementation is written on Java 7, you have to switch your project to Java 7 or 8.
If your project is Gradle-driven, just open your project's build.gradle
script
and replace JavaVersion.VERSION_1_6
to JavaVersion.VERSION_1_7
, like that:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
Or, you can do the same in Android Studio:
File -> Project Structure -> Modules -> "android" -> Properties
And select "1.7" or "1.8" in "Source/Target Compatibility" combo boxes.
This function requests the list of available photo collections (or albums) depending on platform.
An optional option
argument supports only one field collectionMode
with the following values depending on platforms:
Value | Action |
---|---|
ROLL |
Return collection data of device's Camera Roll. Default. |
SMART |
Return list of albums that gather and display photos automatically based on criteria you specify. |
ALBUMS |
Return list of all regular albums you create and name. |
MOMENTS |
Return list of albums that are automatically generated based on date and location. |
For Android platform SMART
, ALBUMS
and MOMENTS
all work as ALBUMS
.
The resulting structure of argument that comes into success
callback function is
array of objects with the following structure:
Property | Type | Descritpion |
---|---|---|
id |
string | An unique collection identifier that you may use in photos() method. |
name |
string | A human-friendly name of collection. May not be unique. |
The failure
callback function takes a string argument with error description.
-
Get all the user's collections/albums:
Photos.collections({"collectionMode": "ALBUMS"}, function(albums) { console.log(albums); }, function(error) { console.error("Error: " + error); });
This function requests the list of photo assets that are available in specified collections.
-
An optional
collectionIds
argument takes an array of collection IDs that are obtained withcollections()
method. You may specify only one ID as a string argument.
If you omitcollectionIds
argument then only assets from device's Camera Roll are returned. -
An optional
options
argument that supports the following keys and according values:Key Type Default Action offset
int 0
Amount of first N photos that should be skipped during fetch. Less than 0
means0
.limit
int 0
Maximal number of photos that should be returned to client at once during fetch. 0
or less means no limit.interval
int 30
A time interval delay in millis between bundle fetches. Less than 0
means default.
Please be warned that limit
option doesn't stop fetching process - it just limits the amount
of fetched photo records that are aggregated in plugin for client -
so that if you use limit
option then you may get several success
callback calls,
where each of them brings next aggregated bundle of fetched photos.
If you want to stop fetching, you have to explicitly call cancel()
function,
that will break the running fetch process.
An interval
option makes sense only if limit
is specified.
It is useful for some kind of "background" photo fetches (e.g. driven by timer events)
to minimize or even avoid UI freezes.
An interval
value less than 30
may cause cancel()
function to break fetching
not instantly - so that you may receive one more excessive incomplete bundle.
The resulting structure of argument that comes into success
callback function is
array of objects with the following structure:
Property | Type | Descritpion |
---|---|---|
id |
string | An unique photo identifier that you may use in thumbnail() or image() methods. |
name |
string | A file name of photo (without path and extension). |
timestamp |
long | A photo's timestamp in millis from Jan 1, 1970 |
date |
string | A photo's timestamp in ISO 8601 format in YYYY-MM-dd'T'HH:mm:ssZZZ pattern. |
contentType |
string | Content type of image: e.g. "image/png" or "image/jpeg" . |
width |
int | A width of image in pixels. |
height |
int | A height of image in pixels. |
latitude |
double | An optional geolocation latitude. |
longitude |
double | An optional geolocation longitude. |
The failure
callback function takes a string argument with error description.
-
Get all the photos' metadata that are available in Camera Roll now:
Photos.photos( function(photos) { console.log(photos); }, function(error) { console.error("Error: " + error); });
-
More complicated example with full set of arguments and fetching cancelling:
// Get all photos from albums "XXXXXX" and "YYYYYY" // partially, by 10 record bundles, skipping 100 first photos, // and only first 2 bundles maximum are needed. var bundleSize = 10; var bundleMax = 2; var bundle = 0; Photos.photos(["XXXXXX", "YYYYYY"], {"offset": 100, "limit": bundleSize}, function(photos) { ++bundle; // We need only 2 bundles, so let's stop fetching // as soon as possible we've got them if (bundle >= bundleMax) Photos.cancel(); // This code will be called several times // in case if amount of your photos is at least // 100 (offset) + 10 (limit) = 110 console.log("Bundle #" + bundle + ": " + JSON.stringify(photos)); if (photos.length < bundleSize) { // It is guaranteed that if limit option is set // then there will be the last call with photos.length < bundleSize, // so that you may get the last call with photos.length == 0 console.log("That's it - no more bundles"); } }, console.error);
This function requests generating a scaled (reduced) image from its original data. Each supported platform uses its own specific tools to make scaled images - including optimizations and caching.
Despite the fact that multiple parallel calls to this function is quite safe, use it with caution - if you will request generating a lot of thumbnails simultaneously, all of them are processed by device in parallel threads, so you may suffer from big delays.
Thumbnails are returned only as JPEG data, even if source image is in other format (e.g. PNG screenshot).
-
A required
photoId
argument that is a photo ID you obtained byphotos()
function. -
An optional
options
argument that supports the following keys and according values:Key Type Default Action asDataUrl
boolean false
Whether return thumbnail data as Data URL ( true
) or as ArrayBuffer.dimension
int 120
A maximal size of thumbnail both for width and height (aspect ratio will be kept). quality
int 80
A JPEG quality factor from 100
(best quality) to1
(least quality).
Please note that you have to use combination of asDataUrl:true
and dimension
carefully:
device's WebViews have limitations in processing large Data URLs.
The resulting data of argument that comes into success
callback function
depends on options.asDataUrl
flag:
- if it's
true
then data is returned as string in Data URL format that you e.g. may use assrc
attribute inimg
tag; - otherwise data is returned as an ArrayBuffer that you may:
- render as blob-url in
src
attribute ofimg
tag; - draw in canvas (you'll need JPEG decoder for that);
- save it as a file with cordova-plugin-file.
- render as blob-url in
The failure
callback function takes a string argument with error description.
-
Generate a thumbnail as ArrayBuffer and render it using Blob and a blob-url as image source:
// Do not forget to extend your Content-Security-Policy with explicit 'img-src blob:' rule Photos.thumbnail("XXXXXX", function(data) { var blob = new Blob([data], {"type": "image/jpeg"}); var domURL = window.URL || window.webkitURL; document.getElementsByTagName("img")[0].src = domURL.createObjectURL(blob); }, function(error) { console.error("Error: " + error); });
-
Generate and render a thumbnail as Data URL with maximal dimension by width or height of 300 pixels and JPEG quality of 70:
Photos.thumbnail("XXXXXX", {"asDataUrl": true, "dimension": 300, "quality": 70}, function(data) { document.getElementsByTagName("img")[0].src = data; }, function(error) { console.error("Error: " + error); });
-
Generate a thumbnail as ArrayBuffer, store it as a temporary file on device and then render it as an image source (requires cordova-plugin-file to be installed):
var photoId = "XXXXXX"; Photos.thumbnail(photoId, {"dimension": 300, "quality": 70}, function(data) { requestFileSystem(LocalFileSystem.TEMPORARY, 1024*1024, function(fs) { var fn = photoId.replace(/\W/g, "_") + "-thumb.jpeg"; fs.root.getFile(fn, {"create": true, "exclusive": false}, function(entry) { entry.createWriter(function(writer) { writer.onwriteend = function() { document.getElementsByTagName("img")[0].src = entry.toURL(); }; writer.onerror = console.error; writer.write(new Blob([data], {"type": "image/jpeg"})); }, console.error); }, console.error); }, console.error); }, console.error);
See full simple caching example in
image()
examples.
This function requests original data of specified photo.
The content type of returned data may be different:
you may pick it up in contentType
property of results of photos()
function.
A required photoId
argument that is a photo ID you obtained by photos()
function.
The resulting data of argument that comes into success
callback function
is an ArrayBuffer that you may:
- render as blob-url in
src
attribute ofimg
tag; - draw in canvas (you'll need JPEG decoder for
image/jpeg
data or PNG decoder forimage/png
data); - save it as a file with cordova-plugin-file.
The failure
callback function takes a string argument with error description.
-
Render ArrayBuffer image using Blob and a blob-url as image source:
// Do not forget to extend your Content-Security-Policy with explicit 'img-src blob:' rule var photo = {"id": "XXXXXX", "contentType": "image/jpeg"}; // Get it from Photos.photos() Photos.image(photo.id, function(data) { var blob = new Blob([data], {"type": photo.contentType}); var domURL = window.URL || window.webkitURL; document.getElementsByTagName("img")[0].src = domURL.createObjectURL(blob); }, function(error) { console.error("Error: " + error); });
-
Draw ArrayBuffer PNG screenshot into canvas (requires PNG decoder to be included):
Photos.image("XXXXXX", function(data) { // you know MIME type from Photos.photos() result var png = new PNG(new Uint8Array(data)); png.render(document.getElementsByTagName("canvas")[0]); }, function(error) { console.error("Error: " + error); });
-
Draw ArrayBuffer JPEG photo into canvas (requires JPEG decoder to be included):
Photos.image("XXXXXX", function(data) { // you know MIME type from Photos.photos() result var parser = new JpegDecoder(); parser.parse(new Uint8Array(data)); var numComponents = parser.numComponents; var width = parser.width; var height = parser.height; var decoded = parser.getData(width, height); var canvas = document.getElementsByTagName("canvas")[0]; canvas.width = width; canvas.height = height; var ctx = canvas.getContext("2d"); var imageData = ctx.createImageData(width, height); var imageBytes = imageData.data; for (var i = 0, j = 0, ii = width * height * 4; i < ii;) { imageBytes[i++] = decoded[j++]; imageBytes[i++] = numComponents === 3 ? decoded[j++] : decoded[j - 1]; imageBytes[i++] = numComponents === 3 ? decoded[j++] : decoded[j - 1]; imageBytes[i++] = 255; } ctx.putImageData(imageData, 0, 0); }, function(error) { console.error("Error: " + error); });
-
Full simple caching solution of getting and rendering original image as an image source (requires cordova-plugin-file to be installed):
var photo = {"id": "XXXXXX", "contentType": "image/jpeg"}; // Get it from Photos.photos() var img = document.getElementsByTagName("img")[0]; // Get it from your DOM requestFileSystem(LocalFileSystem.TEMPORARY, 3*1024*1024, function(fs) { fs.root.getFile( photo.id.replace(/\W/g, "_") + photo.contentType.replace(/^image\//, "."), {create: true, exclusive: false}, function(entry) { entry.file(function(file) { if (file.size == 0) { Photos.image(photo.id, function(data) { entry.createWriter(function(writer) { writer.onwriteend = function() {img.src = entry.toURL()}; writer.onerror = console.error; writer.write(new Blob([data], {"type": photo.contentType})); }, console.error); }, console.error); } else img.src = entry.toURL(); }, console.error); }, console.error); }, console.error);
This is no-argument function that simply breaks any long fetching process that runs in the background.
Though, it is used with only photos()
function now.
Please, see photos()
examples for details.
For more information on setting up Cordova see the documentation.
For more info on plugins see the Plugin Development Guide.