To capture and select images or videos , using cordova , the plugin cordova-plugin-camera can be used .
$ cordova create demo-camera com.twiserandom.mobileapps.demo.camera "Demo Camera" # Create an application , in a folder named # demo-camera , with an id of # com.twiserandom.mobileapps.demo.camera # and a title of : Demo Camera $ cd demo-camera $ cordova platform add ios # add the iOS platform $ cordova platform add android # add the android platform $ cordova plugin add cordova-plugin-camera # add the camera plugin .
To get a picture or a video , the function :
navigator.camera.getPicture(cameraSuccessFct , cameraErrorFct , cameraOptions );
can be used .
The navigator.camera object is globally accessible , after the deviceready event has been fired .
The navigator.camera.getPicture function , takes as arguments two functions , one called on success , and the other one called on error . The last argument that it takes , is an object containing options for the media and the camera . This object has the following format .
/*Camera object properties .*/
{
"mediaType":
Camera.MediaType.PICTURE
/*Select a picture , default .*/
Camera.MediaType.VIDEO
/*Select a video , returns url only .*/
Camera.MediaType.ALLMEDIA
/*Select from all media .*/ ,
"sourceType":
Camera.PictureSourceType.PHOTOLIBRARY
/*Source , device photo library .*/
Camera.PictureSourceType.CAMERA
/*Source camera , default .*/
Camera.PictureSourceType.SAVEDPHOTOALBUM
/*Source Roll album , iOS only .*/ ,
"cameraDirection":
Camera.Direction.BACK
/*Back Camera default .*/
Camera.Direction.FRONT
/*Front Camera .*/ ,
"destinationType":
Camera.DestinationType.DATA_URL
/*Return a base 64 encoded stream .*/
Camera.DestinationType.FILE_URI
/*Return a file url , default , for example :
file:///var/mobile/Containers/Data/...../cdv_photo_001.jpg
In iOS , Pictures or videos are saved in the app ,
temporary directory , which is emptied when the app
exits .*/
Camera.DestinationType.NATIVE_URI ,
/* In iOS files are saved in the save Photo Album , when
source type is camera , and editing is ignored when
source type is PHOTOLIBRARY .*/
"saveToPhotoAlbum": true
/*True or false , save image to
photo album , default true .*/ ,
"encodingType":
Camera.EncodingType.JPEG
/*Returned image encoding type
JPEG , default .*/
Camera.EncodingType. PNG
/*Returned image encoding type
PNG .*/ ,
"quality": 50
/*Quality of the captured image ,
between 0 and 100 , default is
50 .*/ ,
"allowEdit": false
/*True or false .
Allow image editing before
selection , iOS only , default
false .*/ ,
"targetWidth": undefined
/*Width in px to scale image ,
must be used with targetHeight .
Aspect ratio remains constant
, default undefined .*/ ,
"targetHeight": undefined
/*Height in px to scale image ,
must be used with targetWidth .
Aspect ratio remains constant ,
default undefined .*/ ,
"correctOrientation": undefined
/*True or false .
Correct rotation of device using capture
by rotating the image ,
default undefined .*/ ,
"popoverOptions": undefined
/*default , undefined .
new CameraPopoverOptions(
/*Where to anchor PopOver , iPad , iOS only .*/
300, /*x coordinate px , default 0 .*/
300, /*y coordinate px , default 32 .*/
100, /*width px element where anchor popover , default 320 .*/
100, /*Height px element where anchor popover , default 480 .*/
Camera.PopoverArrowDirection.ARROW_ANY,
/*Specify location arrow location on
popover , iPad , iOS Only , default ARROW_ANY
Camera.PopoverArrowDirection.ARROW_UP
Camera.PopoverArrowDirection.ARROW_DOWN
Camera.PopoverArrowDirection.ARROW_LEFT
Camera.PopoverArrowDirection.ARROW_RIGHT
Camera.PopoverArrowDirection. ARROW_ANY */
300, /*width pop over , default 0 , apple default */
600 /*Height pop over , default 0 , apple default */ ) .*/
}
For iOS , for this plugin to work , it must be set what the application is doing . This can be done by editing the config.xml file , found in the root of your application , to look like this :
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.twiserandom.mobileapps.demo.camera" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>Demo Camera</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
</description>
<author email="dev@cordova.apache.org" href="http://cordova.io">
Apache Cordova Team
</author>
<content src="index.html" />
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<platform name="android">
<allow-intent href="market:*" />
</platform>
<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
</platform>
<!-- IOS camera access , for cordova camera plugin -->
<edit-config target="NSCameraUsageDescription" file="*-Info.plist" mode="merge">
<string>need camera access to take pictures</string>
</edit-config>
<edit-config target="NSPhotoLibraryUsageDescription" file="*-Info.plist" mode="merge">
<string>need photo library access to get pictures from there</string>
</edit-config>
<edit-config target="NSLocationWhenInUseUsageDescription" file="*-Info.plist" mode="merge">
<string>need location access to find things nearby</string>
</edit-config>
<edit-config target="NSPhotoLibraryAddUsageDescription" file="*-Info.plist" mode="merge">
<string>need photo library access to save pictures there</string>
</edit-config>
<preference name="CameraUsesGeolocation" value="false" />
<!-- Enable Geolocation for iOS , set the value to
true , it seems there is a problem , with geolocation
enabled in this plugin . -->
<!-- IOS camera access , for cordova camera plugin -->
</widget>
Edit the www/index.html to be like this :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" >
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
<meta name="color-scheme" content="light dark">
<link rel="stylesheet" href="css/index.css">
<title>Demo Cordova camera plugin</title>
</head>
<body>
<div class="app">
<h1>Demo Cordova camera plugin</h1>
<div class="xmpl">
<div
class="button"
ontouchstart="btnTouchStart(this )"
ontouchend="btnTouchEnd(this )"
onclick="exampleOneClicked(this.nextElementSibling )">
Camera Picture</div>
<img
/>
</div>
<div class="xmpl">
<div
class="button"
ontouchstart="btnTouchStart(this )"
ontouchend="btnTouchEnd(this )"
onclick="exampleTwoClicked(this.nextElementSibling )">
Photo Library Picture</div>
<img
/>
</div>
<div class="xmpl">
<div
class="button"
ontouchstart="btnTouchStart(this )"
ontouchend="btnTouchEnd(this )"
onclick="exampleThreeClicked(this.nextElementSibling )">
Ipad Photo Library Pop Over </div>
<img
/>
</div>
<div class="xmpl">
<div
class="button"
ontouchstart="btnTouchStart(this )"
ontouchend="btnTouchEnd(this )"
onclick="exampleFourClicked(this.nextElementSibling )">
Photo Library Video</div>
<video
controls
preload="metadata"
/>
</div>
</div>
<script src="cordova.js"></script>
<script src="js/index.js"></script>
</body>
</html>
Edit the www/css/index.css file to be like this :
*{
border : 0px;
margin : 0px;
padding : 0px;
border-radius: 0px; }
html{
box-sizing: border-box; }
html * , html *::after , html *::before{
box-sizing: inherit; }
body{
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+/Edge */
user-select: none; /* Standard */
background-color: cornsilk; }
h1{
margin: 6px 0px;
font-size : 28px;
text-align: center;
color : firebrick; }
.xmpl {
display: flex;
flex-direction: column; }
.xmpl .button{
text-align: center;
margin: 0px 19px 6px;
border : 1px solid salmon;
border-radius: 18px 9px;
color: rgb(172, 55, 123);
padding : 4px 0px;
font-family: monospace;
font-size : 22px;
background-color: white; }
.xmpl .button.touchStart{
background-color: transparent; }
.xmpl img , .xmpl video{
object-fit: contain;
width : 100%;
border : 6px solid ivory;
background-image: url(data:image/png;base64,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);
min-height: 128px;
margin-bottom: 12px; }
Edit the www/js/index.js to look like this :
document.addEventListener('deviceready', onDeviceReady, false);
let isDeviceReady = false;
function btnTouchStart(btn ){
btn.classList.add("touchStart" ); }
function btnTouchEnd(btn ){
btn.classList.remove("touchStart" ); }
function onDeviceReady( ) {
isDeviceReady = true ; }
function exampleOneClicked(img ){
/* Front Camera , disable save to phone ,
data url , quality 60 . */
if(isDeviceReady ){
let pictureOptions = {
cameraDirection: Camera.Direction.FRONT,
saveToPhotoAlbum: false,
destinationType: Camera.DestinationType.DATA_URL,
quality: 60 };
function fctSuccess(image ){
img.src = `data:image/jpeg;base64,${image }`; }
function fctFailure(errorMsg ){
console.log(errorMsg ); }
navigator
.camera
.getPicture(fctSuccess ,
fctFailure ,
pictureOptions ); }}
function exampleTwoClicked(img ){
/* Photo Library , allow Edit */
if(isDeviceReady ){
let pictureOptions = {
sourceType: Camera.PictureSourceType.PHOTOLIBRARY ,
allowEdit: true };
function fctSuccess(image ){
img.src = image; }
function fctFailure(errorMsg ){
console.log(errorMsg ); }
navigator
.camera
.getPicture(fctSuccess ,
fctFailure ,
pictureOptions ); }}
function exampleThreeClicked(img ){
/* Photo Library , popover */
if(isDeviceReady ){
let pictureOptions = {
sourceType: Camera.PictureSourceType.PHOTOLIBRARY ,
popoverOptions: new CameraPopoverOptions(
0 ,
200 ,
300,
400 ,
Camera.PopoverArrowDirection.ARROW_UP ,
0 ,
0 ) };
function fctSuccess(image ){
img.src = image; }
function fctFailure(errorMsg ){
console.log(errorMsg ); }
navigator
.camera
.getPicture(fctSuccess ,
fctFailure ,
pictureOptions );
function updatePopOverLocation(){
let cameraPopoverHandle = new CameraPopoverHandle();
let cameraPopoverOptions = new CameraPopoverOptions(
100 ,
300 ,
300 ,
600 ,
Camera.PopoverArrowDirection.ARROW_DOWN ,
0 ,
0 );
cameraPopoverHandle.setPosition(cameraPopoverOptions ); }
window.setTimeout(updatePopOverLocation , 4000 ); }}
function exampleFourClicked(vdo ){
/* video , Photo Library */
if(isDeviceReady ){
let pictureOptions = {
mediaType: Camera.MediaType.VIDEO ,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY };
function fctSuccess(video ){
vdo.src = video; }
function fctFailure(errorMsg ){
console.log(errorMsg ); }
navigator
.camera
.getPicture(fctSuccess ,
fctFailure ,
pictureOptions ); }}
Run the application :
$ cordova emulate ios # on iOS $ cordova emulate android # on android




When setting the sourceType to Camera.PictureSourceType.CAMERA , and the destinationType to Camera.DestinationType.FILE_URI , temporary files on iOS can be cleaned by calling the method :
navigator.camera.cleanup(cleanupSuccessFct, cleanupFailFct );
/*Call the cleanup method , to clean
temporary files on iOS .
Pass an on success function and an
on failure function .*/
function cleanupSuccessFct( ){
console.log("Cleanup Success" ); }
function cleanupFailFct(errorMsg ){
console.log(errorMsg ); }

