();
43 |
44 | private Bundle lastSavedState;
45 | private CallbackContext resumeContext;
46 |
47 | /**
48 | * Creates a request and adds it to the array of pending requests. Each created request gets a
49 | * unique result code for use with startActivityForResult() and requestPermission()
50 | * @param action The action this request corresponds to (capture image, capture audio, etc.)
51 | * @param options The options for this request passed from the javascript
52 | * @param callbackContext The CallbackContext to return the result to
53 | * @return The newly created Request object with a unique result code
54 | * @throws JSONException
55 | */
56 | public synchronized Request createRequest(int action, JSONObject options, CallbackContext callbackContext) throws JSONException {
57 | Request req = new Request(action, options, callbackContext);
58 | requests.put(req.requestCode, req);
59 | return req;
60 | }
61 |
62 | /**
63 | * Gets the request corresponding to this request code
64 | * @param requestCode The request code for the desired request
65 | * @return The request corresponding to the given request code or null if such a
66 | * request is not found
67 | */
68 | public synchronized Request get(int requestCode) {
69 | // Check to see if this request was saved
70 | if (lastSavedState != null && lastSavedState.containsKey(REQUEST_KEY_PREFIX + requestCode)) {
71 | Request r = new Request(lastSavedState.getBundle(REQUEST_KEY_PREFIX + requestCode), this.resumeContext, requestCode);
72 | requests.put(requestCode, r);
73 |
74 | // Only one of the saved requests will get restored, because that's all cordova-android
75 | // supports. Having more than one is an extremely unlikely scenario anyway
76 | this.lastSavedState = null;
77 | this.resumeContext = null;
78 |
79 | return r;
80 | }
81 |
82 | return requests.get(requestCode);
83 | }
84 |
85 | /**
86 | * Removes the request from the array of pending requests and sends an error plugin result
87 | * to the CallbackContext that contains the given error object
88 | * @param req The request to be resolved
89 | * @param error The error to be returned to the CallbackContext
90 | */
91 | public synchronized void resolveWithFailure(Request req, JSONObject error) {
92 | req.callbackContext.error(error);
93 | requests.remove(req.requestCode);
94 | }
95 |
96 | /**
97 | * Removes the request from the array of pending requests and sends a successful plugin result
98 | * to the CallbackContext that contains the result of the request
99 | * @param req The request to be resolved
100 | */
101 | public synchronized void resolveWithSuccess(Request req) {
102 | req.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, req.results));
103 | requests.remove(req.requestCode);
104 | }
105 |
106 |
107 | /**
108 | * Each request gets a unique ID that represents its request code when calls are made to
109 | * Activities and for permission requests
110 | * @return A unique request code
111 | */
112 | private synchronized int incrementCurrentReqId() {
113 | return currentReqId ++;
114 | }
115 |
116 | /**
117 | * Restore state saved by calling toBundle along with a callbackContext to be used in
118 | * delivering the results of a pending callback
119 | *
120 | * @param lastSavedState The bundle received from toBundle()
121 | * @param resumeContext The callbackContext to return results to
122 | */
123 | public synchronized void setLastSavedState(Bundle lastSavedState, CallbackContext resumeContext) {
124 | this.lastSavedState = lastSavedState;
125 | this.resumeContext = resumeContext;
126 | this.currentReqId = lastSavedState.getInt(CURRENT_ID_KEY);
127 | }
128 |
129 | /**
130 | * Save the current pending requests to a bundle for saving when the Activity gets destroyed.
131 | *
132 | * @return A Bundle that can be used to restore state using setLastSavedState()
133 | */
134 | public synchronized Bundle toBundle() {
135 | Bundle bundle = new Bundle();
136 | bundle.putInt(CURRENT_ID_KEY, currentReqId);
137 |
138 | for (int i = 0; i < requests.size(); i++) {
139 | Request r = requests.valueAt(i);
140 | int requestCode = requests.keyAt(i);
141 | bundle.putBundle(REQUEST_KEY_PREFIX + requestCode, r.toBundle());
142 | }
143 |
144 | if (requests.size() > 1) {
145 | // This scenario is hopefully very unlikely because there isn't much that can be
146 | // done about it. Should only occur if an external Activity is launched while
147 | // there is a pending permission request and the device is on low memory
148 | LOG.w(LOG_TAG, "More than one media capture request pending on Activity destruction. Some requests will be dropped!");
149 | }
150 |
151 | return bundle;
152 | }
153 |
154 | /**
155 | * Holds the options and CallbackContext for a capture request made to the plugin.
156 | */
157 | public class Request {
158 |
159 | // Keys for use in saving requests to a bundle
160 | private static final String ACTION_KEY = "action";
161 | private static final String LIMIT_KEY = "limit";
162 | private static final String DURATION_KEY = "duration";
163 | private static final String QUALITY_KEY = "quality";
164 | private static final String RESULTS_KEY = "results";
165 |
166 | // Unique int used to identify this request in any Android Permission or Activity callbacks
167 | public int requestCode;
168 |
169 | // The action that this request is performing
170 | public int action;
171 |
172 | // The number of pics/vids/audio clips to take (CAPTURE_IMAGE, CAPTURE_VIDEO, CAPTURE_AUDIO)
173 | public long limit = 1;
174 |
175 | // Optional max duration of recording in seconds (CAPTURE_VIDEO only)
176 | public int duration = 0;
177 |
178 | // Quality level for video capture 0 low, 1 high (CAPTURE_VIDEO only)
179 | public int quality = 1;
180 |
181 | // The array of results to be returned to the javascript callback on success
182 | public JSONArray results = new JSONArray();
183 |
184 | // The callback context for this plugin request
185 | private CallbackContext callbackContext;
186 |
187 | private Request(int action, JSONObject options, CallbackContext callbackContext) throws JSONException {
188 | this.callbackContext = callbackContext;
189 | this.action = action;
190 |
191 | if (options != null) {
192 | this.limit = options.optLong("limit", 1);
193 | this.duration = options.optInt("duration", 0);
194 | this.quality = options.optInt("quality", 1);
195 | }
196 |
197 | this.requestCode = incrementCurrentReqId();
198 | }
199 |
200 | private Request(Bundle bundle, CallbackContext callbackContext, int requestCode) {
201 | this.callbackContext = callbackContext;
202 | this.requestCode = requestCode;
203 | this.action = bundle.getInt(ACTION_KEY);
204 | this.limit = bundle.getLong(LIMIT_KEY);
205 | this.duration = bundle.getInt(DURATION_KEY);
206 | this.quality = bundle.getInt(QUALITY_KEY);
207 |
208 | try {
209 | this.results = new JSONArray(bundle.getString(RESULTS_KEY));
210 | } catch(JSONException e) {
211 | // This should never be caught
212 | LOG.e(LOG_TAG, "Error parsing results for request from saved bundle", e);
213 | }
214 | }
215 |
216 | private Bundle toBundle() {
217 | Bundle bundle = new Bundle();
218 |
219 | bundle.putInt(ACTION_KEY, this.action);
220 | bundle.putLong(LIMIT_KEY, this.limit);
221 | bundle.putInt(DURATION_KEY, this.duration);
222 | bundle.putInt(QUALITY_KEY, this.quality);
223 | bundle.putString(RESULTS_KEY, this.results.toString());
224 |
225 | return bundle;
226 | }
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/src/android/res/xml/mediacapture_provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/browser/CaptureProxy.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | const MediaFile = require('cordova-plugin-media-capture.MediaFile');
23 | const MediaFileData = require('cordova-plugin-media-capture.MediaFileData');
24 | const CaptureError = require('cordova-plugin-media-capture.CaptureError');
25 |
26 | /**
27 | * Helper function that converts data URI to Blob
28 | * @param {String} dataURI Data URI to convert
29 | * @return {Blob} Blob, covnerted from DataURI String
30 | */
31 | function dataURItoBlob (dataURI) {
32 | // convert base64 to raw binary data held in a string
33 | // doesn't handle URLEncoded DataURIs
34 | const byteString = atob(dataURI.split(',')[1]); // eslint-disable-line no-undef
35 |
36 | // separate out the mime component
37 | const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
38 |
39 | // write the bytes of the string to an ArrayBuffer
40 | const ab = new ArrayBuffer(byteString.length);
41 | const ia = new Uint8Array(ab);
42 | for (let i = 0; i < byteString.length; i++) {
43 | ia[i] = byteString.charCodeAt(i);
44 | }
45 |
46 | // write the ArrayBuffer to a blob, and you're done
47 | return new Blob([ab], { type: mimeString }); // eslint-disable-line no-undef
48 | }
49 |
50 | /**
51 | * Creates basic camera UI with preview 'video' element and 'Cancel' button
52 | * Capture starts, when you clicking on preview.
53 | */
54 | function CameraUI () {
55 | // Root element for preview
56 | const container = document.createElement('div');
57 | container.style.cssText =
58 | 'left: 0px; top: 0px; width: 100%; height: 100%; position: fixed; z-index:9999;' +
59 | 'padding: 40px; background-color: rgba(0,0,0,0.75);' +
60 | 'text-align:center; visibility: hidden';
61 |
62 | // Set up root element contetnts
63 | container.innerHTML =
64 | '' +
65 | '
' +
66 | 'Click on preview to capture image. Click outside of preview to cancel.' +
67 | '' +
68 | '
';
69 |
70 | // Add container element to DOM but do not display it since visibility == hidden
71 | document.body.appendChild(container);
72 |
73 | // Create fullscreen preview
74 | const preview = document.getElementById('capturePreview');
75 | preview.autoplay = true;
76 | // We'll show preview only when video element content
77 | // is fully loaded to avoid glitches
78 | preview.onplay = function () {
79 | container.style.visibility = 'visible';
80 | };
81 |
82 | this.container = container;
83 | this.preview = preview;
84 | }
85 |
86 | /**
87 | * Displays capture preview
88 | * @param {Number} count Number of images to take
89 | * @param {Function} successCB Success callback, that accepts data URL of captured image
90 | * @param {Function} errorCB Error callback
91 | */
92 | CameraUI.prototype.startPreview = function (count, successCB, errorCB) {
93 | const that = this;
94 |
95 | this.preview.onclick = function (e) {
96 | // proceed with capture here
97 | // We don't need to propagate click event to parent elements.
98 | // Otherwise click on vieo element will trigger click event handler
99 | // for preview root element and cause preview cancellation
100 | e.stopPropagation();
101 | // Create canvas element, put video frame on it
102 | // and save its contant as Data URL
103 | const canvas = document.createElement('canvas');
104 | canvas.width = this.videoWidth;
105 | canvas.height = this.videoHeight;
106 | canvas.getContext('2d').drawImage(that.preview, 0, 0);
107 | successCB(canvas.toDataURL('image/jpeg'));
108 | };
109 |
110 | this.container.onclick = function () {
111 | // Cancel capture here
112 | errorCB(new CaptureError(CaptureError.CAPTURE_NO_MEDIA_FILES));
113 | };
114 |
115 | navigator.getUserMedia(
116 | { video: true },
117 | function (previewStream) {
118 | // Save video stream to be able to stop it later
119 | that._previewStream = previewStream;
120 | that.preview.src = URL.createObjectURL(previewStream); // eslint-disable-line no-undef
121 | // We don't need to set visibility = true for preview element
122 | // since this will be done automatically in onplay event handler
123 | },
124 | function (/* err */) {
125 | errorCB(new CaptureError(CaptureError.CAPTURE_INTERNAL_ERR));
126 | }
127 | );
128 | };
129 |
130 | /**
131 | * Destroys camera preview, removes all elements created
132 | */
133 | CameraUI.prototype.destroyPreview = function () {
134 | this.preview.pause();
135 | this.preview.src = null;
136 | this._previewStream.stop();
137 | this._previewStream = null;
138 | if (this.container) {
139 | document.body.removeChild(this.container);
140 | }
141 | };
142 |
143 | module.exports = {
144 | captureAudio: function (successCallback, errorCallback) {
145 | if (errorCallback) {
146 | errorCallback(new CaptureError(CaptureError.CAPTURE_NOT_SUPPORTED));
147 | }
148 | },
149 |
150 | captureVideo: function (successCallback, errorCallback) {
151 | if (errorCallback) {
152 | errorCallback(new CaptureError(CaptureError.CAPTURE_NOT_SUPPORTED));
153 | }
154 | },
155 |
156 | captureImage: function (successCallback, errorCallback, args) {
157 | const fail = function (code) {
158 | if (errorCallback) {
159 | errorCallback(new CaptureError(code || CaptureError.CAPTURE_INTERNAL_ERR));
160 | }
161 | };
162 |
163 | const options = args[0];
164 |
165 | const limit = options.limit || 1;
166 | if (typeof limit !== 'number' || limit < 1) {
167 | fail(CaptureError.CAPTURE_INVALID_ARGUMENT);
168 | return;
169 | }
170 |
171 | // Counter for already taken images
172 | let imagesTaken = 0;
173 |
174 | navigator.getUserMedia =
175 | navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
176 |
177 | if (!navigator.getUserMedia) {
178 | fail(CaptureError.CAPTURE_NOT_SUPPORTED);
179 | return;
180 | }
181 |
182 | const ui = new CameraUI();
183 | ui.startPreview(
184 | limit,
185 | function (data) {
186 | // Check if we're done with capture. If so, then destroy UI
187 | if (++imagesTaken >= limit) {
188 | ui.destroyPreview();
189 | }
190 |
191 | // Array of resultant MediaFiles
192 | const mediaFiles = [];
193 |
194 | // save data to file here
195 | window.requestFileSystem(
196 | window.TEMPORARY,
197 | data.length * limit,
198 | function (fileSystem) {
199 | // If we need to capture multiple files, then append counter to filename
200 | const fileName = limit <= 1 ? 'image.jpg' : 'image' + imagesTaken + '.jpg';
201 | fileSystem.root.getFile(
202 | fileName,
203 | { create: true },
204 | function (file) {
205 | file.createWriter(function (writer) {
206 | writer.onwriteend = function () {
207 | file.getMetadata(function (meta) {
208 | mediaFiles.push(
209 | new MediaFile(file.name, file.toURL(), 'image/jpeg', meta.modificationTime, meta.size)
210 | );
211 | // Check if we're done with capture. If so, then call a successCallback
212 | if (imagesTaken >= limit) {
213 | successCallback(mediaFiles);
214 | }
215 | }, fail);
216 | };
217 | writer.onerror = fail;
218 | // Since success callback for start preview returns
219 | // a base64 encoded string, we need to convert it to blob first
220 | writer.write(dataURItoBlob(data));
221 | });
222 | },
223 | fail
224 | );
225 | },
226 | fail
227 | );
228 | },
229 | function (err) {
230 | ui.destroyPreview();
231 | fail(err.code);
232 | }
233 | );
234 | },
235 |
236 | getFormatData: function (successCallback, errorCallback, args) {
237 | const img = document.createElement('img');
238 | img.src = args[0];
239 | img.onload = function () {
240 | if (successCallback) {
241 | successCallback(new MediaFileData(null, 0, img.height, img.width, 0));
242 | }
243 | };
244 | }
245 | };
246 |
247 | require('cordova/exec/proxy').add('Capture', module.exports);
248 |
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/controls_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/controls_bg.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/controls_bg@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/controls_bg@2x.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/controls_bg@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/controls_bg@2x~ipad.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/controls_bg~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/controls_bg~ipad.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/de.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | // controller title for Videos
21 | "Videos title" = "Videos";
22 | // accessibility label for recording button
23 | "toggle audio recording" = "starten/beenden der Tonaufnahme";
24 | // notification spoken by VoiceOver when timed recording finishes
25 | "timed recording complete" = "programmierte Aufnahme beendet";
26 | // accessibility hint for display of recorded elapsed time
27 | "recorded time in minutes and seconds" = "aufgenommene Zeit in Minuten und Sekunden";
28 | // Access denied
29 | "Access denied" = "Zugriff abgelehnt";
30 | // Microphone access has been prohibited
31 | "Access to the microphone has been prohibited. Please enable it in the Settings app to continue." = "Der Zugriff auf das Mikrofon wurde verboten. Bitte aktivieren Sie es in der Einstellungen-App, um fortzufahren.";
32 |
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | // controller title for Videos
21 | "Videos title" = "Videos";
22 | // accessibility label for recording button
23 | "toggle audio recording" = "toggle audio recording";
24 | // notification spoken by VoiceOver when timed recording finishes
25 | "timed recording complete" = "timed recording complete";
26 | // accessibility hint for display of recorded elapsed time
27 | "recorded time in minutes and seconds" = "recorded time in minutes and seconds";
28 | // Access denied
29 | "Access denied" = "Access denied";
30 | // Microphone access has been prohibited
31 | "Access to the microphone has been prohibited. Please enable it in the Settings app to continue." = "Access to the microphone has been prohibited. Please enable it in the Settings app to continue.";
32 |
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/es.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | // controller title for Videos
21 | "Videos title" = "Videos";
22 | // accessibility label for recording button
23 | "toggle audio recording" = "activar/desactivar la grabación de audio";
24 | // notification spoken by VoiceOver when timed recording finishes
25 | "timed recording complete" = "límite de grabación alcanzado";
26 | // accessibility hint for display of recorded elapsed time
27 | "recorded time in minutes and seconds" = "tiempo de grabación en minutos y segundos";
28 | // Access denied
29 | "Access denied" = "Acceso denegado";
30 | // Microphone access has been prohibited
31 | "Access to the microphone has been prohibited. Please enable it in the Settings app to continue." = "Se ha prohibido el acceso al micrófono. Habilítelo en la aplicación Configuración para continuar.";
32 |
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/fr.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | // controller title for Videos
21 | "Videos title" = "Vidéos";
22 | // accessibility label for recording button
23 | "toggle audio recording" = "activer/désactiver l'enregistrement audio";
24 | // notification spoken by VoiceOver when timed recording finishes
25 | "timed recording complete" = "limite d'enregistrement atteinte";
26 | // accessibility hint for display of recorded elapsed time
27 | "recorded time in minutes and seconds" = "temps d'enregistrement en minutes et secondes";
28 | // Access denied
29 | "Access denied" = "Accès refusé";
30 | // Microphone access has been prohibited
31 | "Access to the microphone has been prohibited. Please enable it in the Settings app to continue." = "L'accès au micro a été interdit. Veuillez l'activer dans l'application Paramètres pour continuer.";
32 |
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/microphone-568h@2x~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/microphone-568h@2x~iphone.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/microphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/microphone.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/microphone@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/microphone@2x.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/microphone@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/microphone@2x~ipad.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/microphone~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/microphone~ipad.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/record_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/record_button.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/record_button@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/record_button@2x.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/record_button@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/record_button@2x~ipad.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/record_button~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/record_button~ipad.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/recording_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/recording_bg.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/recording_bg@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/recording_bg@2x.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/recording_bg@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/recording_bg@2x~ipad.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/recording_bg~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/recording_bg~ipad.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/se.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | // controller title for Videos
21 | "Videos title" = "Videor";
22 | // accessibility label for recording button
23 | "toggle audio recording" = "börja/avsluta inspelning";
24 | // notification spoken by VoiceOver when timed recording finishes
25 | "timed recording complete" = "inspelning har avslutad";
26 | // accessibility hint for display of recorded elapsed time
27 | "recorded time in minutes and seconds" = "inspelad tid in minuter och sekund";
28 | // Access denied
29 | "Access denied" = "Tillträde beviljas ej";
30 | // Microphone access has been prohibited
31 | "Access to the microphone has been prohibited. Please enable it in the Settings app to continue." = "Tillgång till mikrofonen har förbjudits. Aktivera det i appen Inställningar för att fortsätta.";
32 |
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/stop_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/stop_button.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/stop_button@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/stop_button@2x.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/stop_button@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/stop_button@2x~ipad.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.bundle/stop_button~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/cordova-plugin-media-capture/00b33f44991cd86d787be36ba12063f717d2c683/src/ios/CDVCapture.bundle/stop_button~ipad.png
--------------------------------------------------------------------------------
/src/ios/CDVCapture.h:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | #import
21 | #import
22 | #import
23 | #import
24 | #import "CDVFile.h"
25 |
26 | enum CDVCaptureError {
27 | CAPTURE_INTERNAL_ERR = 0,
28 | CAPTURE_APPLICATION_BUSY = 1,
29 | CAPTURE_INVALID_ARGUMENT = 2,
30 | CAPTURE_NO_MEDIA_FILES = 3,
31 | CAPTURE_PERMISSION_DENIED = 4,
32 | CAPTURE_NOT_SUPPORTED = 20
33 | };
34 | typedef NSUInteger CDVCaptureError;
35 |
36 | @interface CDVImagePicker : UIImagePickerController
37 | {
38 | NSString* callbackid;
39 | NSInteger quality;
40 | NSString* mimeType;
41 | }
42 | @property (assign) NSInteger quality;
43 | @property (copy) NSString* callbackId;
44 | @property (copy) NSString* mimeType;
45 |
46 | @end
47 |
48 | @interface CDVCapture : CDVPlugin
49 | {
50 | CDVImagePicker* pickerController;
51 | BOOL inUse;
52 | }
53 | @property BOOL inUse;
54 | - (void)captureAudio:(CDVInvokedUrlCommand*)command;
55 | - (void)captureImage:(CDVInvokedUrlCommand*)command;
56 | - (CDVPluginResult*)processImage:(UIImage*)image type:(NSString*)mimeType forCallbackId:(NSString*)callbackId;
57 | - (void)captureVideo:(CDVInvokedUrlCommand*)command;
58 | - (CDVPluginResult*)processVideo:(NSString*)moviePath forCallbackId:(NSString*)callbackId;
59 | - (void)getMediaModes:(CDVInvokedUrlCommand*)command;
60 | - (void)getFormatData:(CDVInvokedUrlCommand*)command;
61 | - (NSDictionary*)getMediaDictionaryFromPath:(NSString*)fullPath ofType:(NSString*)type;
62 | - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info;
63 | - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo;
64 | - (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker;
65 |
66 | @end
67 |
68 | @interface CDVAudioNavigationController : UINavigationController
69 |
70 | @end
71 |
72 | /* AudioRecorderViewController is used to create a simple view for audio recording.
73 | * It is created from [Capture captureAudio]. It creates a very simple interface for
74 | * recording by presenting just a record/stop button and a Done button to close the view.
75 | * The recording time is displayed and recording for a specified duration is supported. When duration
76 | * is specified there is no UI to the user - recording just stops when the specified
77 | * duration is reached. The UI has been minimized to avoid localization.
78 | */
79 | @interface CDVAudioRecorderViewController : UIViewController
80 | {
81 | CDVCaptureError errorCode;
82 | NSString* callbackId;
83 | NSNumber* duration;
84 | CDVCapture* captureCommand;
85 | UIBarButtonItem* doneButton;
86 | UIView* recordingView;
87 | UIButton* recordButton;
88 | UIImage* recordImage;
89 | UIImage* stopRecordImage;
90 | UILabel* timerLabel;
91 | AVAudioRecorder* avRecorder;
92 | AVAudioSession* avSession;
93 | CDVPluginResult* pluginResult;
94 | NSTimer* timer;
95 | BOOL isTimed;
96 | }
97 | @property (nonatomic) CDVCaptureError errorCode;
98 | @property (nonatomic, copy) NSString* callbackId;
99 | @property (nonatomic, copy) NSNumber* duration;
100 | @property (nonatomic, strong) CDVCapture* captureCommand;
101 | @property (nonatomic, strong) UIBarButtonItem* doneButton;
102 | @property (nonatomic, strong) UIView* recordingView;
103 | @property (nonatomic, strong) UIButton* recordButton;
104 | @property (nonatomic, strong) UIImage* recordImage;
105 | @property (nonatomic, strong) UIImage* stopRecordImage;
106 | @property (nonatomic, strong) UILabel* timerLabel;
107 | @property (nonatomic, strong) AVAudioRecorder* avRecorder;
108 | @property (nonatomic, strong) AVAudioSession* avSession;
109 | @property (nonatomic, strong) CDVPluginResult* pluginResult;
110 | @property (nonatomic, strong) NSTimer* timer;
111 | @property (nonatomic) BOOL isTimed;
112 |
113 | - (id)initWithCommand:(CDVPlugin*)theCommand duration:(NSNumber*)theDuration callbackId:(NSString*)theCallbackId;
114 | - (void)processButton:(id)sender;
115 | - (void)stopRecordingCleanup;
116 | - (void)dismissAudioView:(id)sender;
117 | - (NSString*)formatTime:(int)interval;
118 | - (void)updateTime;
119 | @end
120 |
--------------------------------------------------------------------------------
/src/windows/MediaFile.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | /* global Windows */
23 |
24 | const MediaFileData = require('cordova-plugin-media-capture.MediaFileData');
25 | const CaptureError = require('cordova-plugin-media-capture.CaptureError');
26 |
27 | module.exports = {
28 | getFormatData: function (successCallback, errorCallback, args) {
29 | Windows.Storage.StorageFile.getFileFromPathAsync(this.fullPath).then(
30 | function (storageFile) {
31 | const mediaTypeFlag = String(storageFile.contentType).split('/')[0].toLowerCase();
32 | if (mediaTypeFlag === 'audio') {
33 | storageFile.properties.getMusicPropertiesAsync().then(
34 | function (audioProperties) {
35 | successCallback(new MediaFileData(null, audioProperties.bitrate, 0, 0, audioProperties.duration / 1000));
36 | },
37 | function () {
38 | errorCallback(new CaptureError(CaptureError.CAPTURE_INVALID_ARGUMENT));
39 | }
40 | );
41 | } else if (mediaTypeFlag === 'video') {
42 | storageFile.properties.getVideoPropertiesAsync().then(
43 | function (videoProperties) {
44 | successCallback(
45 | new MediaFileData(
46 | null,
47 | videoProperties.bitrate,
48 | videoProperties.height,
49 | videoProperties.width,
50 | videoProperties.duration / 1000
51 | )
52 | );
53 | },
54 | function () {
55 | errorCallback(new CaptureError(CaptureError.CAPTURE_INVALID_ARGUMENT));
56 | }
57 | );
58 | } else if (mediaTypeFlag === 'image') {
59 | storageFile.properties.getImagePropertiesAsync().then(
60 | function (imageProperties) {
61 | successCallback(new MediaFileData(null, 0, imageProperties.height, imageProperties.width, 0));
62 | },
63 | function () {
64 | errorCallback(new CaptureError(CaptureError.CAPTURE_INVALID_ARGUMENT));
65 | }
66 | );
67 | } else {
68 | errorCallback(new CaptureError(CaptureError.CAPTURE_INVALID_ARGUMENT));
69 | }
70 | },
71 | function () {
72 | errorCallback(new CaptureError(CaptureError.CAPTURE_INVALID_ARGUMENT));
73 | }
74 | );
75 | }
76 | };
77 |
--------------------------------------------------------------------------------
/tests/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cordova-plugin-media-capture-tests",
3 | "version": "6.0.1-dev",
4 | "description": "",
5 | "cordova": {
6 | "id": "cordova-plugin-media-capture-tests",
7 | "platforms": []
8 | },
9 | "keywords": [
10 | "ecosystem:cordova"
11 | ],
12 | "author": "",
13 | "license": "Apache 2.0"
14 | }
15 |
--------------------------------------------------------------------------------
/tests/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
26 | Cordova Media Capture Plugin Tests
27 | Apache 2.0
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/tests/tests.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | /* global CaptureAudioOptions, CaptureImageOptions, CaptureVideoOptions, CaptureError */
23 | /* global Media, MediaFile, MediaFileData, resolveLocalFileSystemURL, cordova */
24 |
25 | exports.defineAutoTests = function () {
26 | describe('Capture (navigator.device.capture)', function () {
27 | it('capture.spec.1 should exist', function () {
28 | expect(navigator.device).toBeDefined();
29 | expect(navigator.device.capture).toBeDefined();
30 | });
31 |
32 | it('capture.spec.2 should have the correct properties ', function () {
33 | expect(navigator.device.capture.supportedAudioModes).toBeDefined();
34 | expect(navigator.device.capture.supportedImageModes).toBeDefined();
35 | expect(navigator.device.capture.supportedVideoModes).toBeDefined();
36 | });
37 |
38 | it('capture.spec.3 should contain a captureAudio function', function () {
39 | expect(navigator.device.capture.captureAudio).toBeDefined();
40 | expect(typeof navigator.device.capture.captureAudio === 'function').toBe(true);
41 | });
42 |
43 | it('capture.spec.4 should contain a captureImage function', function () {
44 | expect(navigator.device.capture.captureImage).toBeDefined();
45 | expect(typeof navigator.device.capture.captureImage === 'function').toBe(true);
46 | });
47 |
48 | it('capture.spec.5 should contain a captureVideo function', function () {
49 | expect(navigator.device.capture.captureVideo).toBeDefined();
50 | expect(typeof navigator.device.capture.captureVideo === 'function').toBe(true);
51 | });
52 |
53 | describe('CaptureAudioOptions', function () {
54 | it('capture.spec.6 CaptureAudioOptions constructor should exist', function () {
55 | const options = new CaptureAudioOptions();
56 | expect(options).toBeDefined();
57 | expect(options.limit).toBeDefined();
58 | expect(options.duration).toBeDefined();
59 | });
60 | });
61 |
62 | describe('CaptureImageOptions', function () {
63 | it('capture.spec.7 CaptureImageOptions constructor should exist', function () {
64 | const options = new CaptureImageOptions();
65 | expect(options).toBeDefined();
66 | expect(options.limit).toBeDefined();
67 | });
68 | });
69 |
70 | describe('CaptureVideoOptions', function () {
71 | it('capture.spec.8 CaptureVideoOptions constructor should exist', function () {
72 | const options = new CaptureVideoOptions();
73 | expect(options).toBeDefined();
74 | expect(options.limit).toBeDefined();
75 | expect(options.duration).toBeDefined();
76 | });
77 | });
78 |
79 | describe('CaptureError interface', function () {
80 | it('capture.spec.9 CaptureError constants should be defined', function () {
81 | expect(CaptureError.CAPTURE_INTERNAL_ERR).toBe(0);
82 | expect(CaptureError.CAPTURE_APPLICATION_BUSY).toBe(1);
83 | expect(CaptureError.CAPTURE_INVALID_ARGUMENT).toBe(2);
84 | expect(CaptureError.CAPTURE_NO_MEDIA_FILES).toBe(3);
85 | });
86 |
87 | it('capture.spec.10 CaptureError properties should exist', function () {
88 | const error = new CaptureError();
89 | expect(error).toBeDefined();
90 | expect(error.code).toBeDefined();
91 | });
92 | });
93 |
94 | describe('MediaFileData', function () {
95 | it('capture.spec.11 MediaFileData constructor should exist', function () {
96 | const fileData = new MediaFileData();
97 | expect(fileData).toBeDefined();
98 | expect(fileData.bitrate).toBeDefined();
99 | expect(fileData.codecs).toBeDefined();
100 | expect(fileData.duration).toBeDefined();
101 | expect(fileData.height).toBeDefined();
102 | expect(fileData.width).toBeDefined();
103 | });
104 | });
105 |
106 | describe('MediaFile', function () {
107 | it('capture.spec.12 MediaFile constructor should exist', function () {
108 | const fileData = new MediaFile();
109 | expect(fileData).toBeDefined();
110 | expect(fileData.name).toBeDefined();
111 | expect(fileData.type).toBeDefined();
112 | expect(fileData.lastModifiedDate).toBeDefined();
113 | expect(fileData.size).toBeDefined();
114 | });
115 | });
116 | });
117 | };
118 |
119 | /******************************************************************************/
120 | /******************************************************************************/
121 | /******************************************************************************/
122 |
123 | exports.defineManualTests = function (contentEl, createActionButton) {
124 | const pageStartTime = +new Date();
125 |
126 | function log (value) {
127 | document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
128 | console.log(value);
129 | }
130 |
131 | function captureAudioWin (mediaFiles) {
132 | const path = mediaFiles[0].fullPath;
133 | log('Audio captured: ' + path);
134 | const m = new Media(path);
135 | m.play();
136 | getFileMetadata(mediaFiles[0]);
137 | }
138 |
139 | function captureAudioFail (e) {
140 | log('Error getting audio: ' + e.code);
141 | }
142 |
143 | function getAudio () {
144 | clearStatus();
145 | const options = { limit: 1, duration: 10 };
146 | navigator.device.capture.captureAudio(captureAudioWin, captureAudioFail, options);
147 | }
148 |
149 | function captureImageWin (mediaFiles) {
150 | let path = mediaFiles[0].fullPath;
151 | // Necessary since windows doesn't allow file URLs for
elements
152 | if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') {
153 | // eslint-disable-line no-undef
154 | path = mediaFiles[0].localURL;
155 | }
156 | log('Image captured: ' + path);
157 | document.getElementById('camera_image').src = path;
158 | }
159 |
160 | function captureImagesWin (mediaFiles) {
161 | let path = mediaFiles[0].fullPath;
162 | // Necessary since windows doesn't allow file URLs for
elements
163 | if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') {
164 | // eslint-disable-line no-undef
165 | path = mediaFiles[0].localURL;
166 | }
167 | const path2 = mediaFiles[1].fullPath;
168 | // Necessary since windows doesn't allow file URLs for
elements
169 | if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') {
170 | // eslint-disable-line no-undef
171 | path = mediaFiles[1].localURL;
172 | }
173 | const path3 = mediaFiles[2].fullPath;
174 | // Necessary since windows doesn't allow file URLs for
elements
175 | if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') {
176 | // eslint-disable-line no-undef
177 | path = mediaFiles[2].localURL;
178 | }
179 | log('Image captured: ' + path);
180 | log('Image captured: ' + path2);
181 | log('Image captured: ' + path3);
182 | document.getElementById('camera_image').src = path;
183 | document.getElementById('camera_image2').src = path2;
184 | document.getElementById('camera_image3').src = path3;
185 | }
186 |
187 | function captureImageFail (e) {
188 | log('Error getting image: ' + e.code);
189 | }
190 |
191 | function getImage () {
192 | clearStatus();
193 | const options = { limit: 1 };
194 | navigator.device.capture.captureImage(captureImageWin, captureImageFail, options);
195 | }
196 |
197 | function getImages () {
198 | clearStatus();
199 | const options = { limit: 3 };
200 | navigator.device.capture.captureImage(captureImagesWin, captureImageFail, options);
201 | }
202 |
203 | function captureVideoWin (mediaFiles) {
204 | const path = mediaFiles[0].fullPath;
205 | log('Video captured: ' + path);
206 |
207 | // need to inject the video element into the html
208 | // doesn't seem to work if you have a pre-existing video element and
209 | // add in a source tag
210 | const vid = document.createElement('video');
211 | vid.id = 'theVideo';
212 | vid.width = '320';
213 | vid.height = '240';
214 | vid.controls = 'true';
215 | const source_vid = document.createElement('source');
216 | source_vid.id = 'theSource';
217 | source_vid.src = path;
218 | vid.appendChild(source_vid);
219 | document.getElementById('video_container').appendChild(vid);
220 | getFileMetadata(mediaFiles[0]);
221 | }
222 |
223 | function getFileMetadata (mediaFile) {
224 | mediaFile.getFormatData(getMetadataWin, getMetadataFail);
225 | }
226 |
227 | function getMetadataWin (metadata) {
228 | const strMetadata = 'duration = ' + metadata.duration + '\n' + 'width = ' + metadata.width + '\n' + 'height = ' + metadata.height;
229 | log(strMetadata);
230 | }
231 |
232 | function getMetadataFail (e) {
233 | log('Error getting metadata: ' + e.code);
234 | }
235 |
236 | function captureVideoFail (e) {
237 | log('Error getting video: ' + e.code);
238 | }
239 |
240 | function getVideo () {
241 | clearStatus();
242 | const options = { limit: 1, duration: 10 };
243 | navigator.device.capture.captureVideo(captureVideoWin, captureVideoFail, options);
244 | }
245 |
246 | function permissionWasNotAllowed () {
247 | log('Media has been captured. Have you forgotten to disallow camera for this app?');
248 | }
249 |
250 | function catchPermissionError (error) {
251 | if (CaptureError.CAPTURE_PERMISSION_DENIED === error.code) {
252 | log('Sucess: permission error has been detected!');
253 | } else {
254 | log('Error: another error with code: ' + error.code);
255 | }
256 | }
257 |
258 | function getVideoPermissionError () {
259 | const options = { limit: 1, duration: 10 };
260 | navigator.device.capture.captureVideo(permissionWasNotAllowed, catchPermissionError, options);
261 | }
262 |
263 | function getImagePermissionError () {
264 | const options = { limit: 1 };
265 | navigator.device.capture.captureImage(permissionWasNotAllowed, catchPermissionError, options);
266 | }
267 |
268 | function resolveMediaFileURL (mediaFile, callback) {
269 | resolveLocalFileSystemURL(
270 | mediaFile.localURL,
271 | function (entry) {
272 | log('Resolved by URL: ' + mediaFile.localURL);
273 | if (callback) callback();
274 | },
275 | function (err) {
276 | log('Failed to resolve by URL: ' + mediaFile.localURL);
277 | log('Error: ' + JSON.stringify(err));
278 | if (callback) callback();
279 | }
280 | );
281 | }
282 |
283 | function resolveMediaFile (mediaFile, callback) {
284 | resolveLocalFileSystemURL(
285 | mediaFile.fullPath,
286 | function (entry) {
287 | log('Resolved by path: ' + mediaFile.fullPath);
288 | if (callback) callback();
289 | },
290 | function (err) {
291 | log('Failed to resolve by path: ' + mediaFile.fullPath);
292 | log('Error: ' + JSON.stringify(err));
293 | if (callback) callback();
294 | }
295 | );
296 | }
297 |
298 | function resolveVideo () {
299 | clearStatus();
300 | const options = { limit: 1, duration: 5 };
301 | navigator.device.capture.captureVideo(
302 | function (mediaFiles) {
303 | captureVideoWin(mediaFiles);
304 | resolveMediaFile(mediaFiles[0], function () {
305 | resolveMediaFileURL(mediaFiles[0]);
306 | });
307 | },
308 | captureVideoFail,
309 | options
310 | );
311 | }
312 |
313 | function clearStatus () {
314 | document.getElementById('camera_status').innerHTML = '';
315 | document.getElementById('camera_image').src = 'about:blank';
316 | document.getElementById('camera_image2').src = 'about:blank';
317 | document.getElementById('camera_image3').src = 'about:blank';
318 | }
319 |
320 | /******************************************************************************/
321 |
322 | contentEl.innerHTML =
323 | '' +
324 | '
Status: ' +
325 | 'img1:
![]()
' +
326 | 'img2:
![]()
' +
327 | 'img3:
![]()
' +
328 | 'video:
' +
329 | '
' +
330 | 'Expected result: Audio recorder will come up. Press record button to record for 10 seconds. Press Done. Status box will update with audio file and automatically play recording.' +
331 | ' ' +
332 | 'Expected result: Status box will update with image just taken.' +
333 | ' ' +
334 | 'Expected result: Status box will update with images just taken.' +
335 | ' ' +
336 | 'Expected result: Record 10 second video. Status box will update with video file that you can play.' +
337 | ' ' +
338 | 'Expected result: Record 5 second video. Status box will show that URL was resolved and video will get added at the bottom of the status box for playback.' +
339 | ' ' +
340 | 'Expected result (iOS only): camera picker and alert with message that camera access is prohibited are shown. The alert has 2 buttons: OK and Settings. By click on "OK" camera is hidden, by pressing Settings it shows privacy settings for the app' +
341 | ' ' +
342 | 'Expected result (iOS only): camera picker and alert with message that camera access is prohibited are shown. The alert has 2 buttons: OK and Settings. By click on "OK" camera is hidden, by pressing Settings it shows privacy settings for the app';
343 |
344 | createActionButton(
345 | 'Capture 10 sec of audio and play',
346 | function () {
347 | getAudio();
348 | },
349 | 'audio'
350 | );
351 |
352 | createActionButton(
353 | 'Capture 1 image',
354 | function () {
355 | getImage();
356 | },
357 | 'image'
358 | );
359 |
360 | createActionButton(
361 | 'Capture 3 images',
362 | function () {
363 | getImages();
364 | },
365 | 'images'
366 | );
367 |
368 | createActionButton(
369 | 'Capture 10 sec of video',
370 | function () {
371 | getVideo();
372 | },
373 | 'video'
374 | );
375 |
376 | createActionButton(
377 | 'Capture 5 sec of video and resolve',
378 | function () {
379 | resolveVideo();
380 | },
381 | 'video_and_resolve'
382 | );
383 |
384 | createActionButton(
385 | 'Disable access to Camera and click to capture video',
386 | function () {
387 | getVideoPermissionError();
388 | },
389 | 'prohibited_camera_video'
390 | );
391 |
392 | createActionButton(
393 | 'Disable access to Camera and click to capture image',
394 | function () {
395 | getImagePermissionError();
396 | },
397 | 'prohibited_camera_image'
398 | );
399 | };
400 |
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | // Type definitions for Apache Cordova MediaCapture plugin
2 | // Project: https://github.com/apache/cordova-plugin-media-capture
3 | // Definitions by: Microsoft Open Technologies Inc
4 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
5 | //
6 | // Copyright (c) Microsoft Open Technologies Inc
7 | // Licensed under the MIT license
8 |
9 | interface Navigator {
10 | device: Device;
11 | }
12 |
13 | interface Device {
14 | capture: Capture;
15 | }
16 |
17 | /** This plugin provides access to the device's audio, image, and video capture capabilities. */
18 | interface Capture {
19 | /**
20 | * Start the audio recorder application and return information about captured audio clip files.
21 | * @param onSuccess Executes when the capture operation finishes with an array
22 | * of MediaFile objects describing each captured audio clip file.
23 | * @param onError Executes, if the user terminates the operation before an audio clip is captured,
24 | * with a CaptureError object, featuring the CaptureError.CAPTURE_NO_MEDIA_FILES error code.
25 | * @param options Encapsulates audio capture configuration options.
26 | */
27 | captureAudio(
28 | onSuccess: (mediaFiles: MediaFile[]) => void,
29 | onError: (error: CaptureError) => void,
30 | options?: AudioOptions): void ;
31 | /**
32 | * Start the camera application and return information about captured image files.
33 | * @param onSuccess Executes when the capture operation finishes with an array
34 | * of MediaFile objects describing each captured image clip file.
35 | * @param onError Executes, if the user terminates the operation before an audio clip is captured,
36 | * with a CaptureError object, featuring the CaptureError.CAPTURE_NO_MEDIA_FILES error code.
37 | * @param options Encapsulates audio capture configuration options.
38 | */
39 | captureImage(
40 | onSuccess: (mediaFiles: MediaFile[]) => void,
41 | onError: (error: CaptureError) => void,
42 | options?: ImageOptions): void ;
43 | /**
44 | * Start the video recorder application and return information about captured video clip files.
45 | * @param onSuccess Executes when the capture operation finishes with an array
46 | * of MediaFile objects describing each captured video clip file.
47 | * @param onError Executes, if the user terminates the operation before an audio clip is captured,
48 | * with a CaptureError object, featuring the CaptureError.CAPTURE_NO_MEDIA_FILES error code.
49 | * @param options Encapsulates audio capture configuration options.
50 | */
51 | captureVideo(
52 | onSuccess: (mediaFiles: MediaFile[]) => void,
53 | onError: (error: CaptureError) => void,
54 | options?: VideoOptions): void ;
55 | /** The audio recording formats supported by the device. */
56 | supportedAudioModes: ConfigurationData[];
57 | /** The recording image sizes and formats supported by the device. */
58 | supportedImageModes: ConfigurationData[];
59 | /** The recording video resolutions and formats supported by the device. */
60 | supportedVideoModes: ConfigurationData[];
61 | }
62 |
63 | /** Encapsulates properties of a media capture file. */
64 | interface MediaFile {
65 | /** The name of the file, without path information. */
66 | name: string;
67 | /** The full path of the file, including the name. */
68 | fullPath: string;
69 | /** The file's mime type */
70 | type: string;
71 | /** The date and time when the file was last modified. */
72 | lastModifiedDate: Date;
73 | /** The size of the file, in bytes. */
74 | size: number;
75 | /**
76 | * Retrieves format information about the media capture file.
77 | * @param successCallback Invoked with a MediaFileData object when successful.
78 | * @param errorCallback Invoked if the attempt fails, this function.
79 | */
80 | getFormatData(
81 | successCallback: (data: MediaFileData) => void,
82 | errorCallback?: () => void): void;
83 | }
84 |
85 | /** Encapsulates format information about a media file. */
86 | interface MediaFileData {
87 | /** The actual format of the audio and video content. */
88 | codecs: string;
89 | /** The average bitrate of the content. The value is zero for images. */
90 | bitrate: number;
91 | /** The height of the image or video in pixels. The value is zero for audio clips. */
92 | height: number;
93 | /** The width of the image or video in pixels. The value is zero for audio clips. */
94 | width: number;
95 | /** The length of the video or sound clip in seconds. The value is zero for images. */
96 | duration: number;
97 | }
98 |
99 | /** Encapsulates the error code resulting from a failed media capture operation. */
100 | interface CaptureError {
101 | /**
102 | * One of the pre-defined error codes listed below.
103 | * CaptureError.CAPTURE_INTERNAL_ERR
104 | * The camera or microphone failed to capture image or sound.
105 | * CaptureError.CAPTURE_APPLICATION_BUSY
106 | * The camera or audio capture application is currently serving another capture request.
107 | * CaptureError.CAPTURE_INVALID_ARGUMENT
108 | * Invalid use of the API (e.g., the value of limit is less than one).
109 | * CaptureError.CAPTURE_NO_MEDIA_FILES
110 | * The user exits the camera or audio capture application before capturing anything.
111 | * CaptureError.CAPTURE_NOT_SUPPORTED
112 | * The requested capture operation is not supported.
113 | */
114 | code: number;
115 | message: string;
116 | }
117 |
118 | declare var CaptureError: {
119 | /** Constructor for CaptureError */
120 | new (code: number, message: string): CaptureError;
121 | CAPTURE_INTERNAL_ERR: number;
122 | CAPTURE_APPLICATION_BUSY: number;
123 | CAPTURE_INVALID_ARGUMENT: number;
124 | CAPTURE_NO_MEDIA_FILES: number;
125 | CAPTURE_NOT_SUPPORTED: number;
126 | CAPTURE_PERMISSION_DENIED: number;
127 | }
128 |
129 | /** Encapsulates audio capture configuration options. */
130 | interface AudioOptions {
131 | /**
132 | * The maximum number of audio clips the device's user can capture in a single
133 | * capture operation. The value must be greater than or equal to 1.
134 | */
135 | limit?: number;
136 | /** The maximum duration of a audio clip, in seconds. */
137 | duration?: number;
138 | }
139 |
140 | /** Encapsulates image capture configuration options. */
141 | interface ImageOptions {
142 | /**
143 | * The maximum number of images the user can capture in a single capture operation.
144 | * The value must be greater than or equal to 1 (defaults to 1).
145 | */
146 | limit?: number;
147 | }
148 |
149 | /** Encapsulates video capture configuration options. */
150 | interface VideoOptions {
151 | /**
152 | * The maximum number of video clips the device's user can capture in a single
153 | * capture operation. The value must be greater than or equal to 1.
154 | */
155 | limit?: number;
156 | /** The maximum duration of a video clip, in seconds. */
157 | duration?: number;
158 | }
159 |
160 | /** Encapsulates a set of media capture parameters that a device supports. */
161 | interface ConfigurationData {
162 | /** The ASCII-encoded lowercase string representing the media type. */
163 | type: string;
164 | /** The height of the image or video in pixels. The value is zero for sound clips. */
165 | height: number;
166 | /** The width of the image or video in pixels. The value is zero for sound clips. */
167 | width: number;
168 | }
--------------------------------------------------------------------------------
/www/CaptureAudioOptions.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | /**
23 | * Encapsulates all audio capture operation configuration options.
24 | */
25 | const CaptureAudioOptions = function () {
26 | // Upper limit of sound clips user can record. Value must be equal or greater than 1.
27 | this.limit = 1;
28 | // Maximum duration of a single sound clip in seconds.
29 | this.duration = 0;
30 | };
31 |
32 | module.exports = CaptureAudioOptions;
33 |
--------------------------------------------------------------------------------
/www/CaptureError.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | /**
23 | * The CaptureError interface encapsulates all errors in the Capture API.
24 | */
25 | const CaptureError = function (c) {
26 | this.code = c || null;
27 | };
28 |
29 | // Camera or microphone failed to capture image or sound.
30 | CaptureError.CAPTURE_INTERNAL_ERR = 0;
31 | // Camera application or audio capture application is currently serving other capture request.
32 | CaptureError.CAPTURE_APPLICATION_BUSY = 1;
33 | // Invalid use of the API (e.g. limit parameter has value less than one).
34 | CaptureError.CAPTURE_INVALID_ARGUMENT = 2;
35 | // User exited camera application or audio capture application before capturing anything.
36 | CaptureError.CAPTURE_NO_MEDIA_FILES = 3;
37 | // User denied permissions required to perform the capture request.
38 | CaptureError.CAPTURE_PERMISSION_DENIED = 4;
39 | // The requested capture operation is not supported.
40 | CaptureError.CAPTURE_NOT_SUPPORTED = 20;
41 |
42 | module.exports = CaptureError;
43 |
--------------------------------------------------------------------------------
/www/CaptureImageOptions.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | /**
23 | * Encapsulates all image capture operation configuration options.
24 | */
25 | const CaptureImageOptions = function () {
26 | // Upper limit of images user can take. Value must be equal or greater than 1.
27 | this.limit = 1;
28 | };
29 |
30 | module.exports = CaptureImageOptions;
31 |
--------------------------------------------------------------------------------
/www/CaptureVideoOptions.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | /**
23 | * Encapsulates all video capture operation configuration options.
24 | */
25 | const CaptureVideoOptions = function () {
26 | // Upper limit of videos user can record. Value must be equal or greater than 1.
27 | this.limit = 1;
28 | // Maximum duration of a single video clip in seconds.
29 | this.duration = 0;
30 | // Video quality parameter, 0 means low quality, suitable for MMS messages, and value 1 means high quality.
31 | this.quality = 1;
32 | };
33 |
34 | module.exports = CaptureVideoOptions;
35 |
--------------------------------------------------------------------------------
/www/ConfigurationData.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | /**
23 | * Encapsulates a set of parameters that the capture device supports.
24 | */
25 | function ConfigurationData () {
26 | // The ASCII-encoded string in lower case representing the media type.
27 | this.type = null;
28 | // The height attribute represents height of the image or video in pixels.
29 | // In the case of a sound clip this attribute has value 0.
30 | this.height = 0;
31 | // The width attribute represents width of the image or video in pixels.
32 | // In the case of a sound clip this attribute has value 0
33 | this.width = 0;
34 | }
35 |
36 | module.exports = ConfigurationData;
37 |
--------------------------------------------------------------------------------
/www/MediaFile.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | const utils = require('cordova/utils');
23 | const exec = require('cordova/exec');
24 | const File = require('cordova-plugin-file.File');
25 | const CaptureError = require('./CaptureError');
26 | /**
27 | * Represents a single file.
28 | *
29 | * name {DOMString} name of the file, without path information
30 | * fullPath {DOMString} the full path of the file, including the name
31 | * type {DOMString} mime type
32 | * lastModifiedDate {Date} last modified date
33 | * size {Number} size of the file in bytes
34 | */
35 | const MediaFile = function (name, localURL, type, lastModifiedDate, size) {
36 | MediaFile.__super__.constructor.apply(this, arguments);
37 | };
38 |
39 | utils.extend(MediaFile, File);
40 |
41 | /**
42 | * Request capture format data for a specific file and type
43 | *
44 | * @param {Function} successCB
45 | * @param {Function} errorCB
46 | */
47 | MediaFile.prototype.getFormatData = function (successCallback, errorCallback) {
48 | if (typeof this.fullPath === 'undefined' || this.fullPath === null) {
49 | errorCallback(new CaptureError(CaptureError.CAPTURE_INVALID_ARGUMENT));
50 | } else {
51 | exec(successCallback, errorCallback, 'Capture', 'getFormatData', [this.fullPath, this.type]);
52 | }
53 | };
54 |
55 | module.exports = MediaFile;
56 |
--------------------------------------------------------------------------------
/www/MediaFileData.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | /**
23 | * MediaFileData encapsulates format information of a media file.
24 | *
25 | * @param {DOMString} codecs
26 | * @param {long} bitrate
27 | * @param {long} height
28 | * @param {long} width
29 | * @param {float} duration
30 | */
31 | const MediaFileData = function (codecs, bitrate, height, width, duration) {
32 | this.codecs = codecs || null;
33 | this.bitrate = bitrate || 0;
34 | this.height = height || 0;
35 | this.width = width || 0;
36 | this.duration = duration || 0;
37 | };
38 |
39 | module.exports = MediaFileData;
40 |
--------------------------------------------------------------------------------
/www/android/init.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | const cordova = require('cordova');
23 | const helpers = require('./helpers');
24 |
25 | const SUCCESS_EVENT = 'pendingcaptureresult';
26 | const FAILURE_EVENT = 'pendingcaptureerror';
27 |
28 | const sChannel = cordova.addStickyDocumentEventHandler(SUCCESS_EVENT);
29 | const fChannel = cordova.addStickyDocumentEventHandler(FAILURE_EVENT);
30 |
31 | // We fire one of two events in the case where the activity gets killed while
32 | // the user is capturing audio, image, video, etc. in a separate activity
33 | document.addEventListener('deviceready', function () {
34 | document.addEventListener('resume', function (event) {
35 | if (event.pendingResult && event.pendingResult.pluginServiceName === 'Capture') {
36 | if (event.pendingResult.pluginStatus === 'OK') {
37 | const mediaFiles = helpers.wrapMediaFiles(event.pendingResult.result);
38 | sChannel.fire(mediaFiles);
39 | } else {
40 | fChannel.fire(event.pendingResult.result);
41 | }
42 | }
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/www/capture.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | const exec = require('cordova/exec');
23 | const helpers = require('./helpers');
24 |
25 | /**
26 | * Launches a capture of different types.
27 | *
28 | * @param (DOMString} type
29 | * @param {Function} successCB
30 | * @param {Function} errorCB
31 | * @param {CaptureVideoOptions} options
32 | */
33 | function _capture (type, successCallback, errorCallback, options) {
34 | const win = function (pluginResult) {
35 | successCallback(helpers.wrapMediaFiles(pluginResult));
36 | };
37 | exec(win, errorCallback, 'Capture', type, [options]);
38 | }
39 |
40 | /**
41 | * The Capture interface exposes an interface to the camera and microphone of the hosting device.
42 | */
43 | function Capture () {
44 | this.supportedAudioModes = [];
45 | this.supportedImageModes = [];
46 | this.supportedVideoModes = [];
47 | }
48 |
49 | /**
50 | * Launch audio recorder application for recording audio clip(s).
51 | *
52 | * @param {Function} successCB
53 | * @param {Function} errorCB
54 | * @param {CaptureAudioOptions} options
55 | */
56 | Capture.prototype.captureAudio = function (successCallback, errorCallback, options) {
57 | _capture('captureAudio', successCallback, errorCallback, options);
58 | };
59 |
60 | /**
61 | * Launch camera application for taking image(s).
62 | *
63 | * @param {Function} successCB
64 | * @param {Function} errorCB
65 | * @param {CaptureImageOptions} options
66 | */
67 | Capture.prototype.captureImage = function (successCallback, errorCallback, options) {
68 | _capture('captureImage', successCallback, errorCallback, options);
69 | };
70 |
71 | /**
72 | * Launch device camera application for recording video(s).
73 | *
74 | * @param {Function} successCB
75 | * @param {Function} errorCB
76 | * @param {CaptureVideoOptions} options
77 | */
78 | Capture.prototype.captureVideo = function (successCallback, errorCallback, options) {
79 | _capture('captureVideo', successCallback, errorCallback, options);
80 | };
81 |
82 | module.exports = new Capture();
83 |
--------------------------------------------------------------------------------
/www/helpers.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | const MediaFile = require('./MediaFile');
23 |
24 | function wrapMediaFiles (pluginResult) {
25 | const mediaFiles = [];
26 | let i;
27 | for (i = 0; i < pluginResult.length; i++) {
28 | const mediaFile = new MediaFile(
29 | pluginResult[i].name,
30 | // Backwards compatibility
31 | pluginResult[i].localURL || pluginResult[i].fullPath,
32 | pluginResult[i].type,
33 | pluginResult[i].lastModifiedDate,
34 | pluginResult[i].size
35 | );
36 | mediaFile.fullPath = pluginResult[i].fullPath;
37 | mediaFiles.push(mediaFile);
38 | }
39 | return mediaFiles;
40 | }
41 |
42 | module.exports = {
43 | wrapMediaFiles
44 | };
45 |
--------------------------------------------------------------------------------