Skip to content

Commit 7d159cf

Browse files
authored
docs: Revisions for v8 public API changes with the return string formats of getPicture (#913)
1 parent c208754 commit 7d159cf

File tree

1 file changed

+117
-87
lines changed

1 file changed

+117
-87
lines changed

README.md

Lines changed: 117 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,31 @@ To add these entries into the `info.plist`, you can use the `edit-config` tag in
135135

136136
### camera.getPicture(successCallback, errorCallback, options)
137137
Takes a photo using the camera, or retrieves a photo from the device's
138-
image gallery. The image is passed to the success callback as a
139-
Base64-encoded `String`, or as the URI for the image file.
138+
image gallery. The result is provided in the first parameter of the `successCallback` as a string.
139+
140+
As of v8.0.0, the result is formatted as URIs. The scheme will vary depending on settings and platform.
141+
142+
|Platform|Destination Type|Format|
143+
|---|---|---|
144+
|Android|FILE_URI|An URI scheme such as `file://...` or `content://...`|
145+
||DATA_URL|Base 64 encoded with the proper data URI header|
146+
|iOS|FILE_URI|`file://` schemed paths|
147+
||DATA_URL|Base 64 encoded with the proper data URI header|
148+
|Browser|FILE_URI|Not supported|
149+
||DATA_URL|Base 64 encoded with the proper data URI header|
150+
151+
v7 and earlier versions, the return format is as follows:
152+
153+
|Platform|Destination Type|Format|
154+
|---|---|---|
155+
|Android|FILE_URI|Raw file path (unprefixed)|
156+
||DATA_URL|Base 64 encoded, without the `data:` prefix
157+
|iOS|FILE_URI|`file://` schemed paths|
158+
||DATA_URL|Base 64 encoded, without the `data:` prefix
159+
|Browser|FILE_URI|Not supported|
160+
||DATA_URL|Base 64 encoded, without the `data:` prefix|
161+
162+
For this reason, upgrading to v8 is strongly recommended as it greatly streamlines the return data.
140163

141164
The `camera.getPicture` function opens the device's default camera
142165
application that allows users to snap pictures by default - this behavior occurs,
@@ -149,16 +172,10 @@ that allows users to select an existing image.
149172

150173
The return value is sent to the [`cameraSuccess`](#module_camera.onSuccess) callback function, in
151174
one of the following formats, depending on the specified
152-
`cameraOptions`:
153-
154-
- A `String` containing the Base64-encoded photo image.
155-
- A `String` representing the image file location on local storage (default).
156-
157-
You can do whatever you want with the encoded image or URI, for
158-
example:
175+
`cameraOptions`. You can do whatever you want with content:
159176

160-
- Render the image in an `<img>` tag, as in the example below
161-
- Save the data locally (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.)
177+
- Render the content in an `<img>` or `<video>` tag
178+
- Copy the data to a persistent location
162179
- Post the data to a remote server
163180

164181
__NOTE__: Photo resolution on newer devices is quite good. Photos
@@ -167,6 +184,20 @@ quality, even if a `quality` parameter is specified. To avoid common
167184
memory problems, set `Camera.destinationType` to `FILE_URI` rather
168185
than `DATA_URL`.
169186

187+
#### FILE_URI Usage
188+
189+
When `FILE_URI` is used, the returned path is not directly usable. The file path needs to be resolved into
190+
a DOM-usable URL using the [Cordova File Plugin](https://github.com/apache/cordova-plugin-file).
191+
192+
Additionally, the file URIs returned is a temporary read access grant. The OS reserves the right to revoke permission to access the resource, which typically occurs after the app has been closed. For images captured using the camera, the image is stored in a temporary location which can be cleared at any time, usually after the app exits. It's the application's decision to decide how the content should be used depending on their use cases.
193+
194+
For persistent access to the content, the resource should be copied to your app's storage container. An example use case is an app allowing an user to select a profile picture from their gallery or camera. The application will need
195+
consistent access to that resource, so it's not suitable to retain the temporary access path. So the appplication should copy the resource to a persistent location.
196+
197+
For use cases that involve temporary use, it is valid and safe to use the temporary file path to display the content. An example of this could be an image editing application, rendering the data into a canvas.
198+
199+
__NOTE__: The returned schemes is an implementation detail. Do not assume that it will always be a `file://` URI.
200+
170201
__Supported Platforms__
171202

172203
- Android
@@ -232,15 +263,22 @@ Callback function that provides the image data.
232263

233264
| Param | Type | Description |
234265
| --- | --- | --- |
235-
| imageData | <code>string</code> | Base64 encoding of the image data, _or_ the image file URI, depending on [`cameraOptions`](#module_camera.CameraOptions) in effect. |
266+
| imageData | <code>string</code> | Data URI, _or_ the image file URI, depending on [`cameraOptions`](#module_camera.CameraOptions) in effect. |
236267

237268
**Example**
238269
```js
239-
// Show image
240-
//
270+
// Show image captured with FILE_URI
271+
function cameraCallback(imageData) {
272+
window.resolveLocalFileSystemURL(uri, (entry) => {
273+
let image = document.getElementById('myImage');
274+
image.src = entry.toURL();
275+
}, onError);
276+
}
277+
278+
// Show image captured with DATA_URL
241279
function cameraCallback(imageData) {
242280
var image = document.getElementById('myImage');
243-
image.src = "data:image/jpeg;base64," + imageData;
281+
image.src = imageData;
244282
}
245283
```
246284
<a name="module_camera.CameraOptions"></a>
@@ -282,7 +320,7 @@ Defines the output format of `Camera.getPicture` call.
282320

283321
| Name | Type | Default | Description |
284322
| --- | --- | --- | --- |
285-
| DATA_URL | <code>number</code> | <code>0</code> | Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI if possible |
323+
| DATA_URL | <code>number</code> | <code>0</code> | Return data uri. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI if possible |
286324
| FILE_URI | <code>number</code> | <code>1</code> | Return file uri (content://media/external/images/media/2 for Android) |
287325

288326
<a name="module_Camera.EncodingType"></a>
@@ -409,38 +447,46 @@ window.onorientationchange = function() {
409447

410448
Take a photo and retrieve the image's file location:
411449

412-
navigator.camera.getPicture(onSuccess, onFail, { quality: 50,
413-
destinationType: Camera.DestinationType.FILE_URI });
450+
```javascript
451+
// Don't forget to install cordova-plugin-file for resolveLocalFileSystemURL!
414452

415-
function onSuccess(imageURI) {
416-
var image = document.getElementById('myImage');
417-
image.src = imageURI;
418-
}
453+
navigator.camera.getPicture(onSuccess, onFail, { quality: 50,
454+
destinationType: Camera.DestinationType.FILE_URI });
419455

420-
function onFail(message) {
421-
alert('Failed because: ' + message);
422-
}
456+
function onSuccess(imageURI) {
457+
window.resolveLocalFileSystemURL(uri, (entry) => {
458+
let img = document.getElementById('image');
459+
img.src = entry.toURL();
460+
}, onFail);
461+
}
462+
463+
function onFail(message) {
464+
alert('Failed because: ' + message);
465+
}
466+
```
423467

424468
Take a photo and retrieve it as a Base64-encoded image:
425469

426-
/**
427-
* Warning: Using DATA_URL is not recommended! The DATA_URL destination
428-
* type is very memory intensive, even with a low quality setting. Using it
429-
* can result in out of memory errors and application crashes. Use FILE_URI
430-
* instead.
431-
*/
432-
navigator.camera.getPicture(onSuccess, onFail, { quality: 25,
433-
destinationType: Camera.DestinationType.DATA_URL
434-
});
435-
436-
function onSuccess(imageData) {
437-
var image = document.getElementById('myImage');
438-
image.src = "data:image/jpeg;base64," + imageData;
439-
}
470+
```javascript
471+
/**
472+
* Warning: Using DATA_URL is not recommended! The DATA_URL destination
473+
* type is very memory intensive, even with a low quality setting. Using it
474+
* can result in out of memory errors and application crashes. Use FILE_URI
475+
* instead.
476+
*/
477+
navigator.camera.getPicture(onSuccess, onFail, { quality: 25,
478+
destinationType: Camera.DestinationType.DATA_URL
479+
});
440480

441-
function onFail(message) {
442-
alert('Failed because: ' + message);
443-
}
481+
function onSuccess(imageData) {
482+
var image = document.getElementById('myImage');
483+
image.src = imageData;
484+
}
485+
486+
function onFail(message) {
487+
alert('Failed because: ' + message);
488+
}
489+
```
444490

445491
#### Preferences (iOS)
446492

@@ -461,7 +507,7 @@ successful.
461507

462508
#### Browser Quirks
463509

464-
Can only return photos as Base64-encoded image.
510+
Can only return photos as data URI image.
465511

466512
#### iOS Quirks
467513

@@ -470,9 +516,11 @@ can cause problems. Wrap the alert within a `setTimeout()` to allow
470516
the iOS image picker or popover to fully close before the alert
471517
displays:
472518

473-
setTimeout(function() {
474-
// do your thing here!
475-
}, 0);
519+
```javascript
520+
setTimeout(function() {
521+
// do your thing here!
522+
}, 0);
523+
```
476524

477525
## `CameraOptions` Errata <a name="CameraOptions-quirks"></a>
478526

@@ -486,11 +534,6 @@ displays:
486534

487535
- Ignores the `encodingType` parameter if the image is unedited (i.e. `quality` is 100, `correctOrientation` is false, and no `targetHeight` or `targetWidth` are specified). The `CAMERA` source will always return the JPEG file given by the native camera and the `PHOTOLIBRARY` and `SAVEDPHOTOALBUM` sources will return the selected file in its existing encoding.
488536

489-
#### iOS Quirks
490-
491-
- When using `destinationType.FILE_URI`, photos are saved in the application's temporary directory. The contents of the application's temporary directory is deleted when the application ends.
492-
493-
494537
[android_lifecycle]: http://cordova.apache.org/docs/en/dev/guide/platforms/android/lifecycle.html
495538

496539
## Sample: Take Pictures, Select Pictures from the Picture Library, and Get Thumbnails <a name="sample"></a>
@@ -639,49 +682,36 @@ function openFilePicker(selection) {
639682

640683
## Take a picture and get a FileEntry Object <a name="convert"></a>
641684

642-
If you want to do something like copy the image to another location, or upload it somewhere using the FileTransfer plugin, you need to get a FileEntry object for the returned picture. To do that, call `window.resolveLocalFileSystemURL` on the file URI returned by the Camera app. If you need to use a FileEntry object, set the `destinationType` to `Camera.DestinationType.FILE_URI` in your CameraOptions object (this is also the default value).
685+
If you want to do something like copy the image to another location, or upload it somewhere, an `FileEntry` is needed for the returned picture. To do this, call `window.resolveLocalFileSystemURL` on the file URI returned by the Camera app. If you need to use a FileEntry object, set the `destinationType` to `Camera.DestinationType.FILE_URI` in your CameraOptions object (this is also the default value).
643686

644-
>*Note* You need the [File plugin](https://www.npmjs.com/package/cordova-plugin-file) to call `window.resolveLocalFileSystemURL`.
687+
__NOTE:__ You need the [File plugin](https://www.npmjs.com/package/cordova-plugin-file) to call `window.resolveLocalFileSystemURL`.
645688

646689
Here is the call to `window.resolveLocalFileSystemURL`. The image URI is passed to this function from the success callback of `getPicture`. The success handler of `resolveLocalFileSystemURL` receives the FileEntry object.
647690

648691
```js
649692
function getFileEntry(imgUri) {
650693
window.resolveLocalFileSystemURL(imgUri, function success(fileEntry) {
651694

652-
// Do something with the FileEntry object, like write to it, upload it, etc.
653-
// writeFile(fileEntry, imgUri);
654-
console.log("got file: " + fileEntry.fullPath);
655-
// displayFileData(fileEntry.nativeURL, "Native URL");
656-
657-
}, function () {
658-
// If don't get the FileEntry (which may happen when testing
659-
// on some emulators), copy to a new FileEntry.
660-
createNewFileEntry(imgUri);
661-
});
662-
}
663-
```
664-
665-
In the example shown in the preceding code, you call the app's `createNewFileEntry` function if you don't get a valid FileEntry object. The image URI returned from the Camera app should result in a valid FileEntry, but platform behavior on some emulators may be different for files returned from the file picker.
666-
667-
>*Note* To see an example of writing to a FileEntry, see the [File plugin README](https://www.npmjs.com/package/cordova-plugin-file).
668-
669-
The code shown here creates a file in your app's cache (in sandboxed storage) named `tempFile.jpeg`. With the new FileEntry object, you can copy the image to the file or do something else like upload it.
670-
671-
```js
672-
function createNewFileEntry(imgUri) {
673-
window.resolveLocalFileSystemURL(cordova.file.cacheDirectory, function success(dirEntry) {
674-
675-
// JPEG file
676-
dirEntry.getFile("tempFile.jpeg", { create: true, exclusive: false }, function (fileEntry) {
677-
678-
// Do something with it, like write to it, upload it, etc.
679-
// writeFile(fileEntry, imgUri);
680-
console.log("got file: " + fileEntry.fullPath);
681-
// displayFileData(fileEntry.fullPath, "File copied to");
682-
683-
}, onErrorCreateFile);
684-
685-
}, onErrorResolveUrl);
695+
// Example 1: Copy to app data directory
696+
window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function (dataDirectoryEntry) {
697+
fileEntry.copyTo(dataDirectoryEntry, "profilePic", onSuccess, onError);
698+
}, onError);
699+
700+
// Example 2: Upload it!
701+
fileEntry.file(function (file) {
702+
var reader = new FileReader();
703+
704+
reader.onloadend = function() {
705+
var xhr = new XMLHttpRequest();
706+
xhr.open('POST', 'https://myserver.com/upload');
707+
xhr.onload = function () {
708+
// All done!
709+
};
710+
xhr.send(this.result);
711+
};
712+
713+
reader.readAsArrayBuffer(file);
714+
}, onError);
715+
}, onError);
686716
}
687717
```

0 commit comments

Comments
 (0)