mirror of
https://github.com/apache/cordova-plugin-camera.git
synced 2026-04-10 00:00:10 +08:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e419a74546 | ||
|
|
9a47f5c791 | ||
|
|
66d3f03270 | ||
|
|
731c10f5b2 | ||
|
|
f704689200 | ||
|
|
2bad1fd81c | ||
|
|
b43c78b419 | ||
|
|
db2ffedecc | ||
|
|
0d13b71d33 | ||
|
|
8975171d7a | ||
|
|
2d1ee66a2b | ||
|
|
ebe0517a24 | ||
|
|
43d6591d9e | ||
|
|
64d8c5108a | ||
|
|
11769962bd | ||
|
|
140e8861e3 | ||
|
|
5ae56cf8f0 | ||
|
|
e2e04ba3d8 | ||
|
|
4584f15d9f | ||
|
|
0111e93448 | ||
|
|
0333d001c7 | ||
|
|
45496213b3 | ||
|
|
3f42591363 | ||
|
|
e2ecd7fe91 | ||
|
|
eb7fc333ee | ||
|
|
fd155d9705 | ||
|
|
2bf5b9347e | ||
|
|
efb633969e | ||
|
|
973bbbbac7 | ||
|
|
358522c0b5 | ||
|
|
8766956abb | ||
|
|
d89c25cd82 | ||
|
|
ba4f77468f |
@@ -15,6 +15,7 @@ environment:
|
|||||||
matrix:
|
matrix:
|
||||||
- nodejs_version: "10"
|
- nodejs_version: "10"
|
||||||
- nodejs_version: "12"
|
- nodejs_version: "12"
|
||||||
|
- nodejs_version: "14"
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
- x86
|
- x86
|
||||||
|
|||||||
@@ -1,10 +1,23 @@
|
|||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
root: true
|
root: true
|
||||||
extends: semistandard
|
extends: '@cordova/eslint-config/browser'
|
||||||
rules:
|
|
||||||
indent:
|
overrides:
|
||||||
- error
|
- files: [tests/**/*.js]
|
||||||
- 4
|
extends: '@cordova/eslint-config/node-tests'
|
||||||
camelcase: off
|
|
||||||
padded-blocks: off
|
|
||||||
operator-linebreak: off
|
|
||||||
no-throw-literal: off
|
|
||||||
|
|||||||
11
.travis.yml
11
.travis.yml
@@ -13,17 +13,17 @@ env:
|
|||||||
global:
|
global:
|
||||||
- SAUCE_USERNAME=snay
|
- SAUCE_USERNAME=snay
|
||||||
- TRAVIS_NODE_VERSION=12
|
- TRAVIS_NODE_VERSION=12
|
||||||
- ANDROID_API_LEVEL=28
|
- ANDROID_API_LEVEL=29
|
||||||
- ANDROID_BUILD_TOOLS_VERSION=28.0.3
|
- ANDROID_BUILD_TOOLS_VERSION=29.0.2
|
||||||
|
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js: 12
|
node_js: 14
|
||||||
|
|
||||||
# yaml anchor/alias: https://medium.com/@tommyvn/travis-yml-dry-with-anchors-8b6a3ac1b027
|
# yaml anchor/alias: https://medium.com/@tommyvn/travis-yml-dry-with-anchors-8b6a3ac1b027
|
||||||
|
|
||||||
_ios: &_ios
|
_ios: &_ios
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode10.3
|
osx_image: xcode11.6
|
||||||
|
|
||||||
_android: &_android
|
_android: &_android
|
||||||
language: android
|
language: android
|
||||||
@@ -43,7 +43,8 @@ matrix:
|
|||||||
include:
|
include:
|
||||||
# additional tests
|
# additional tests
|
||||||
- env: ADDITIONAL_TESTS_DIR=./tests/ios
|
- env: ADDITIONAL_TESTS_DIR=./tests/ios
|
||||||
language: objective-c
|
os: osx
|
||||||
|
osx_image: xcode11.5
|
||||||
|
|
||||||
# local tests, without saucelabs
|
# local tests, without saucelabs
|
||||||
- env: PLATFORM=local/browser
|
- env: PLATFORM=local/browser
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -276,19 +276,14 @@ Optional parameters to customize the camera settings.
|
|||||||
|
|
||||||
### Camera.DestinationType : <code>enum</code>
|
### Camera.DestinationType : <code>enum</code>
|
||||||
Defines the output format of `Camera.getPicture` call.
|
Defines the output format of `Camera.getPicture` call.
|
||||||
_Note:_ On iOS passing `DestinationType.NATIVE_URI` along with
|
|
||||||
`PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM` will
|
|
||||||
disable any image modifications (resize, quality change, cropping, etc.) due
|
|
||||||
to implementation specific.
|
|
||||||
|
|
||||||
**Kind**: static enum property of <code>[Camera](#module_Camera)</code>
|
**Kind**: static enum property of <code>[Camera](#module_Camera)</code>
|
||||||
**Properties**
|
**Properties**
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| DATA_URL | <code>number</code> | <code>0</code> | Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI or NATIVE_URI if possible |
|
| DATA_URL | <code>number</code> | <code>0</code> | Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI if possible |
|
||||||
| FILE_URI | <code>number</code> | <code>1</code> | Return file uri (content://media/external/images/media/2 for Android) |
|
| FILE_URI | <code>number</code> | <code>1</code> | Return file uri (content://media/external/images/media/2 for Android) |
|
||||||
| NATIVE_URI | <code>number</code> | <code>2</code> | Return native uri (eg. asset-library://... for iOS) |
|
|
||||||
|
|
||||||
<a name="module_Camera.EncodingType"></a>
|
<a name="module_Camera.EncodingType"></a>
|
||||||
|
|
||||||
@@ -317,9 +312,6 @@ to implementation specific.
|
|||||||
|
|
||||||
### Camera.PictureSourceType : <code>enum</code>
|
### Camera.PictureSourceType : <code>enum</code>
|
||||||
Defines the output format of `Camera.getPicture` call.
|
Defines the output format of `Camera.getPicture` call.
|
||||||
_Note:_ On iOS passing `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM`
|
|
||||||
along with `DestinationType.NATIVE_URI` will disable any image modifications (resize, quality
|
|
||||||
change, cropping, etc.) due to implementation specific.
|
|
||||||
|
|
||||||
**Kind**: static enum property of <code>[Camera](#module_Camera)</code>
|
**Kind**: static enum property of <code>[Camera](#module_Camera)</code>
|
||||||
**Properties**
|
**Properties**
|
||||||
@@ -435,7 +427,7 @@ Take a photo and retrieve it as a Base64-encoded image:
|
|||||||
* Warning: Using DATA_URL is not recommended! The DATA_URL destination
|
* Warning: Using DATA_URL is not recommended! The DATA_URL destination
|
||||||
* type is very memory intensive, even with a low quality setting. Using it
|
* type is very memory intensive, even with a low quality setting. Using it
|
||||||
* can result in out of memory errors and application crashes. Use FILE_URI
|
* can result in out of memory errors and application crashes. Use FILE_URI
|
||||||
* or NATIVE_URI instead.
|
* instead.
|
||||||
*/
|
*/
|
||||||
navigator.camera.getPicture(onSuccess, onFail, { quality: 25,
|
navigator.camera.getPicture(onSuccess, onFail, { quality: 25,
|
||||||
destinationType: Camera.DestinationType.DATA_URL
|
destinationType: Camera.DestinationType.DATA_URL
|
||||||
@@ -508,9 +500,6 @@ More information about Windows Phone 8.1 picker APIs is here: [How to continue y
|
|||||||
|
|
||||||
- When using `destinationType.FILE_URI`, photos are saved in the application's temporary directory. The contents of the application's temporary directory is deleted when the application ends.
|
- When using `destinationType.FILE_URI`, photos are saved in the application's temporary directory. The contents of the application's temporary directory is deleted when the application ends.
|
||||||
|
|
||||||
- When using `destinationType.NATIVE_URI` and `sourceType.CAMERA`, photos are saved in the saved photo album regardless on the value of `saveToPhotoAlbum` parameter.
|
|
||||||
|
|
||||||
- When using `destinationType.NATIVE_URI` and `sourceType.PHOTOLIBRARY` or `sourceType.SAVEDPHOTOALBUM`, all editing options are ignored and link is returned to original picture.
|
|
||||||
|
|
||||||
[android_lifecycle]: http://cordova.apache.org/docs/en/dev/guide/platforms/android/lifecycle.html
|
[android_lifecycle]: http://cordova.apache.org/docs/en/dev/guide/platforms/android/lifecycle.html
|
||||||
|
|
||||||
|
|||||||
@@ -20,18 +20,45 @@
|
|||||||
-->
|
-->
|
||||||
# Release Notes
|
# Release Notes
|
||||||
|
|
||||||
### 4.2.0 (May 07, 2020)
|
### 5.0.2 (May 11, 2021)
|
||||||
* Cache images in device storage, devices have enough space now.
|
* [GH-728](https://github.com/apache/cordova-plugin-camera/pull/728) plugin release preparation - audit fix
|
||||||
* docs(readme): app renamed to Google Photos
|
* [GH-700](https://github.com/apache/cordova-plugin-camera/pull/700) Bugfix [issue 665](https://github.com/apache/cordova-plugin-camera/issues/665) - app crashes after taking a picture due to a bug in the camera plugin when app is resumed
|
||||||
|
* [GH-691](https://github.com/apache/cordova-plugin-camera/pull/691) ci: add node-14.x to workflow (#691)
|
||||||
|
|
||||||
|
### 5.0.1 (Nov 04, 2020)
|
||||||
|
|
||||||
|
* [GH-686](https://github.com/apache/cordova-plugin-camera/pull/686) chore(android): add missing apache license header
|
||||||
|
* [GH-685](https://github.com/apache/cordova-plugin-camera/pull/685) fix(ios): correctly append exif on **iOS** 14
|
||||||
|
* [GH-669](https://github.com/apache/cordova-plugin-camera/pull/669) fix(android): save to photo gallery - fixes issues [#341](https://github.com/apache/cordova-plugin-camera/pull/341) & [#577](https://github.com/apache/cordova-plugin-camera/pull/577)
|
||||||
|
* [GH-672](https://github.com/apache/cordova-plugin-camera/pull/672) chore: Fix JIRA links in RELEASENOTES.md
|
||||||
|
* [GH-664](https://github.com/apache/cordova-plugin-camera/pull/664) chore: Update RELEASENOTES
|
||||||
|
|
||||||
|
### 5.0.0 (Sep 14, 2020)
|
||||||
|
|
||||||
|
* [GH-648](https://github.com/apache/cordova-plugin-camera/pull/648) ci(travis): update osx xcode image
|
||||||
|
* [GH-637](https://github.com/apache/cordova-plugin-camera/pull/637) breaking: remove `NATIVE_URI` DestinationType
|
||||||
|
* [GH-628](https://github.com/apache/cordova-plugin-camera/pull/628) breaking: bump project requirements
|
||||||
|
* [GH-634](https://github.com/apache/cordova-plugin-camera/pull/634) chore: remove deprecated `file-transfer` plugin
|
||||||
|
* [GH-632](https://github.com/apache/cordova-plugin-camera/pull/632) fix(android): return error if file url is null
|
||||||
|
* [GH-510](https://github.com/apache/cordova-plugin-camera/pull/510) fix(android): use provider prefix to avoid conflicts other plugin providers
|
||||||
|
* [GH-617](https://github.com/apache/cordova-plugin-camera/pull/617) breaking(android): stop using `CordovaUri` helper class
|
||||||
|
* [GH-630](https://github.com/apache/cordova-plugin-camera/pull/630) chore: add `package-lock.json`
|
||||||
|
* [GH-631](https://github.com/apache/cordova-plugin-camera/pull/631) chore(package): use short notation
|
||||||
|
* [GH-629](https://github.com/apache/cordova-plugin-camera/pull/629) feat: migrate to `@cordova/eslint-config@3.x`
|
||||||
|
* [GH-626](https://github.com/apache/cordova-plugin-camera/pull/626) ci: fix additional tests
|
||||||
|
* [GH-627](https://github.com/apache/cordova-plugin-camera/pull/627) breaking: bump version 5.0.0-dev
|
||||||
|
* [GH-612](https://github.com/apache/cordova-plugin-camera/pull/612) fix(ios): `tempFilePath` called twice if using `CameraUsesGeolocation`
|
||||||
|
* [GH-588](https://github.com/apache/cordova-plugin-camera/pull/588) Cache images in device storage, devices have enough space now.
|
||||||
|
* [GH-508](https://github.com/apache/cordova-plugin-camera/pull/508) docs(readme): app renamed to Google Photos
|
||||||
* chore(asf): update git notification settings
|
* chore(asf): update git notification settings
|
||||||
* fix(ios): return copy of video when picking from gallery on **iOS** 13 (#580)
|
* [GH-580](https://github.com/apache/cordova-plugin-camera/pull/580) fix(ios): return copy of video when picking from gallery on **iOS** 13
|
||||||
* Update CONTRIBUTING.md
|
* Update CONTRIBUTING.md
|
||||||
* Fix UI API called on a background thread (#550, #530, #447) (#551)
|
* [GH-551](https://github.com/apache/cordova-plugin-camera/pull/551) Fix UI API called on a background thread
|
||||||
* ci: updates Node.js versions (#576)
|
* [GH-576](https://github.com/apache/cordova-plugin-camera/pull/576) ci: updates Node.js versions
|
||||||
* chore(npm): adds ignore list (#575)
|
* [GH-575](https://github.com/apache/cordova-plugin-camera/pull/575) chore(npm): adds ignore list
|
||||||
* docs(README): remove confusing comment (#513)
|
* [GH-513](https://github.com/apache/cordova-plugin-camera/pull/513) docs(README): remove confusing comment
|
||||||
* docs(README): remove orphan **Windows** phone 7 note (#512)
|
* [GH-512](https://github.com/apache/cordova-plugin-camera/pull/512) docs(README): remove orphan **Windows** phone 7 note
|
||||||
* ImagePicker returning same image (#306)
|
* [GH-306](https://github.com/apache/cordova-plugin-camera/pull/306) ImagePicker returning same image
|
||||||
|
|
||||||
### 4.1.0 (Jun 27, 2019)
|
### 4.1.0 (Jun 27, 2019)
|
||||||
|
|
||||||
@@ -48,23 +75,23 @@
|
|||||||
- fix(ios): fixes UIImagePickerController cancel handling for iOS11+ ([#377](https://github.com/apache/cordova-plugin-camera/issues/377)) ([`24c8b6c`](https://github.com/apache/cordova-plugin-camera/commit/24c8b6c))
|
- fix(ios): fixes UIImagePickerController cancel handling for iOS11+ ([#377](https://github.com/apache/cordova-plugin-camera/issues/377)) ([`24c8b6c`](https://github.com/apache/cordova-plugin-camera/commit/24c8b6c))
|
||||||
- docs: Remove deprecated platforms from docs ([#394](https://github.com/apache/cordova-plugin-camera/issues/394)) ([`7ddb3df`](https://github.com/apache/cordova-plugin-camera/commit/7ddb3df))
|
- docs: Remove deprecated platforms from docs ([#394](https://github.com/apache/cordova-plugin-camera/issues/394)) ([`7ddb3df`](https://github.com/apache/cordova-plugin-camera/commit/7ddb3df))
|
||||||
- fix(android): return DATA_URL for ALLMEDIA if it's an image ([#382](https://github.com/apache/cordova-plugin-camera/issues/382)) ([`60e7795`](https://github.com/apache/cordova-plugin-camera/commit/60e7795))
|
- fix(android): return DATA_URL for ALLMEDIA if it's an image ([#382](https://github.com/apache/cordova-plugin-camera/issues/382)) ([`60e7795`](https://github.com/apache/cordova-plugin-camera/commit/60e7795))
|
||||||
- refactor(ios): [CB-13813](https://issues.apache.org/jira/browse/13813): Remove old iOS code ([#381](https://github.com/apache/cordova-plugin-camera/issues/381)) ([`ce77aab`](https://github.com/apache/cordova-plugin-camera/commit/ce77aab))
|
- refactor(ios): [CB-13813](https://issues.apache.org/jira/browse/CB-13813): Remove old iOS code ([#381](https://github.com/apache/cordova-plugin-camera/issues/381)) ([`ce77aab`](https://github.com/apache/cordova-plugin-camera/commit/ce77aab))
|
||||||
- feat(ios): [CB-13865](https://issues.apache.org/jira/browse/13865): (Ipad) Making popover Window Size configurable using popoverOptions - imagePicker ([#314](https://github.com/apache/cordova-plugin-camera/issues/314)) ([`cd72047`](https://github.com/apache/cordova-plugin-camera/commit/cd72047))
|
- feat(ios): [CB-13865](https://issues.apache.org/jira/browse/CB-13865): (Ipad) Making popover Window Size configurable using popoverOptions - imagePicker ([#314](https://github.com/apache/cordova-plugin-camera/issues/314)) ([`cd72047`](https://github.com/apache/cordova-plugin-camera/commit/cd72047))
|
||||||
- chore(types): [CB-13837](https://issues.apache.org/jira/browse/13837): fix TypeScript Definition for CameraPopoverOptions ([#379](https://github.com/apache/cordova-plugin-camera/issues/379)) ([`86b0bf2`](https://github.com/apache/cordova-plugin-camera/commit/86b0bf2))
|
- chore(types): [CB-13837](https://issues.apache.org/jira/browse/CB-13837): fix TypeScript Definition for CameraPopoverOptions ([#379](https://github.com/apache/cordova-plugin-camera/issues/379)) ([`86b0bf2`](https://github.com/apache/cordova-plugin-camera/commit/86b0bf2))
|
||||||
- docs(android): clarify android quirk of cameraDirection ([`a5a3d88`](https://github.com/apache/cordova-plugin-camera/commit/a5a3d88), [`bfbe4a1`](https://github.com/apache/cordova-plugin-camera/commit/bfbe4a1))
|
- docs(android): clarify android quirk of cameraDirection ([`a5a3d88`](https://github.com/apache/cordova-plugin-camera/commit/a5a3d88), [`bfbe4a1`](https://github.com/apache/cordova-plugin-camera/commit/bfbe4a1))
|
||||||
- chore(release): Bump minor version ([#370](https://github.com/apache/cordova-plugin-camera/issues/370)) ([`eed4433`](https://github.com/apache/cordova-plugin-camera/commit/eed4433))
|
- chore(release): Bump minor version ([#370](https://github.com/apache/cordova-plugin-camera/issues/370)) ([`eed4433`](https://github.com/apache/cordova-plugin-camera/commit/eed4433))
|
||||||
- build: Remove automatic README generation ([#365](https://github.com/apache/cordova-plugin-camera/issues/365)) ([`07e8574`](https://github.com/apache/cordova-plugin-camera/commit/07e8574))
|
- build: Remove automatic README generation ([#365](https://github.com/apache/cordova-plugin-camera/issues/365)) ([`07e8574`](https://github.com/apache/cordova-plugin-camera/commit/07e8574))
|
||||||
- docs: remove JIRA link ([`bcb26fb`](https://github.com/apache/cordova-plugin-camera/commit/bcb26fb))
|
- docs: remove JIRA link ([`bcb26fb`](https://github.com/apache/cordova-plugin-camera/commit/bcb26fb))
|
||||||
- ci(travis): also accept terms for android sdk `android-27` ([`a346212`](https://github.com/apache/cordova-plugin-camera/commit/a346212))
|
- ci(travis): also accept terms for android sdk `android-27` ([`a346212`](https://github.com/apache/cordova-plugin-camera/commit/a346212))
|
||||||
- docs: remove outdated docs translations that haven't been touched for 3 years ([`403682b`](https://github.com/apache/cordova-plugin-camera/commit/403682b))
|
- docs: remove outdated docs translations that haven't been touched for 3 years ([`403682b`](https://github.com/apache/cordova-plugin-camera/commit/403682b))
|
||||||
- fix(android): [CB-14097](https://issues.apache.org/jira/browse/14097): Fix crash when selecting some files with getPicture ([#322](https://github.com/apache/cordova-plugin-camera/issues/322)) ([`5c23b65`](https://github.com/apache/cordova-plugin-camera/commit/5c23b65))
|
- fix(android): [CB-14097](https://issues.apache.org/jira/browse/CB-14097): Fix crash when selecting some files with getPicture ([#322](https://github.com/apache/cordova-plugin-camera/issues/322)) ([`5c23b65`](https://github.com/apache/cordova-plugin-camera/commit/5c23b65))
|
||||||
- fix(browser): [CB-13384](https://issues.apache.org/jira/browse/13384): Added deprecation of video.src compatibility ([#288](https://github.com/apache/cordova-plugin-camera/issues/288)) ([`5163d38`](https://github.com/apache/cordova-plugin-camera/commit/5163d38))
|
- fix(browser): [CB-13384](https://issues.apache.org/jira/browse/CB-13384): Added deprecation of video.src compatibility ([#288](https://github.com/apache/cordova-plugin-camera/issues/288)) ([`5163d38`](https://github.com/apache/cordova-plugin-camera/commit/5163d38))
|
||||||
- fix(browser): Remove audio flag from getUserMedia ([#284](https://github.com/apache/cordova-plugin-camera/issues/284)) ([`36343a8`](https://github.com/apache/cordova-plugin-camera/commit/36343a8))
|
- fix(browser): Remove audio flag from getUserMedia ([#284](https://github.com/apache/cordova-plugin-camera/issues/284)) ([`36343a8`](https://github.com/apache/cordova-plugin-camera/commit/36343a8))
|
||||||
- docs: replace warning emoji with warning unicode ([#317](https://github.com/apache/cordova-plugin-camera/issues/317)) ([`ead7d5e`](https://github.com/apache/cordova-plugin-camera/commit/ead7d5e))
|
- docs: replace warning emoji with warning unicode ([#317](https://github.com/apache/cordova-plugin-camera/issues/317)) ([`ead7d5e`](https://github.com/apache/cordova-plugin-camera/commit/ead7d5e))
|
||||||
- feat(android): Update engines to use variables ([#323](https://github.com/apache/cordova-plugin-camera/issues/323)) ([`6899c5e`](https://github.com/apache/cordova-plugin-camera/commit/6899c5e))
|
- feat(android): Update engines to use variables ([#323](https://github.com/apache/cordova-plugin-camera/issues/323)) ([`6899c5e`](https://github.com/apache/cordova-plugin-camera/commit/6899c5e))
|
||||||
- feat(android): [CB-14017](https://issues.apache.org/jira/browse/14017): Make com.android.support:support-v4 version configurable ([#318](https://github.com/apache/cordova-plugin-camera/issues/318)) ([`e334656`](https://github.com/apache/cordova-plugin-camera/commit/e334656))
|
- feat(android): [CB-14017](https://issues.apache.org/jira/browse/CB-14017): Make com.android.support:support-v4 version configurable ([#318](https://github.com/apache/cordova-plugin-camera/issues/318)) ([`e334656`](https://github.com/apache/cordova-plugin-camera/commit/e334656))
|
||||||
- refactor(android): [CB-14047](https://issues.apache.org/jira/browse/14047): CameraLauncher: Replacing Repeated String literals with final variables ([#319](https://github.com/apache/cordova-plugin-camera/issues/319)) ([`5ec121b`](https://github.com/apache/cordova-plugin-camera/commit/5ec121b))
|
- refactor(android): [CB-14047](https://issues.apache.org/jira/browse/CB-14047): CameraLauncher: Replacing Repeated String literals with final variables ([#319](https://github.com/apache/cordova-plugin-camera/issues/319)) ([`5ec121b`](https://github.com/apache/cordova-plugin-camera/commit/5ec121b))
|
||||||
- fix(windows): [CB-11714](https://issues.apache.org/jira/browse/11714): added extra check for content-type in savePhoto() without options.targetWidth/Height ([#242](https://github.com/apache/cordova-plugin-camera/issues/242)) ([`a201722`](https://github.com/apache/cordova-plugin-camera/commit/a201722), [`dc73954`](https://github.com/apache/cordova-plugin-camera/commit/dc73954), [`dca4b9c`](https://github.com/apache/cordova-plugin-camera/commit/dca4b9c), [`c1b9772`](https://github.com/apache/cordova-plugin-camera/commit/c1b9772), [`eb57b02`](https://github.com/apache/cordova-plugin-camera/commit/eb57b02))
|
- fix(windows): [CB-11714](https://issues.apache.org/jira/browse/CB-11714): added extra check for content-type in savePhoto() without options.targetWidth/Height ([#242](https://github.com/apache/cordova-plugin-camera/issues/242)) ([`a201722`](https://github.com/apache/cordova-plugin-camera/commit/a201722), [`dc73954`](https://github.com/apache/cordova-plugin-camera/commit/dc73954), [`dca4b9c`](https://github.com/apache/cordova-plugin-camera/commit/dca4b9c), [`c1b9772`](https://github.com/apache/cordova-plugin-camera/commit/c1b9772), [`eb57b02`](https://github.com/apache/cordova-plugin-camera/commit/eb57b02))
|
||||||
|
|
||||||
|
|
||||||
### 4.0.3 (Apr 12, 2018)
|
### 4.0.3 (Apr 12, 2018)
|
||||||
|
|||||||
1724
package-lock.json
generated
Normal file
1724
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cordova-plugin-camera",
|
"name": "cordova-plugin-camera",
|
||||||
"version": "4.2.0",
|
"version": "5.0.2",
|
||||||
"description": "Cordova Camera Plugin",
|
"description": "Cordova Camera Plugin",
|
||||||
"types": "./types/index.d.ts",
|
"types": "./types/index.d.ts",
|
||||||
"cordova": {
|
"cordova": {
|
||||||
@@ -13,13 +13,8 @@
|
|||||||
"osx"
|
"osx"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": "github:apache/cordova-plugin-camera",
|
||||||
"type": "git",
|
"bugs": "https://github.com/apache/cordova-plugin-camera/issues",
|
||||||
"url": "https://github.com/apache/cordova-plugin-camera"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/apache/cordova-plugin-camera/issues"
|
|
||||||
},
|
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cordova",
|
"cordova",
|
||||||
"camera",
|
"camera",
|
||||||
@@ -31,8 +26,8 @@
|
|||||||
"cordova-osx"
|
"cordova-osx"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "npm run eslint",
|
"test": "npm run lint",
|
||||||
"eslint": "node node_modules/eslint/bin/eslint www && node node_modules/eslint/bin/eslint src && node node_modules/eslint/bin/eslint tests"
|
"lint": "eslint ."
|
||||||
},
|
},
|
||||||
"author": "Apache Software Foundation",
|
"author": "Apache Software Foundation",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@@ -46,17 +41,16 @@
|
|||||||
"cordova": ">=7.1.0"
|
"cordova": ">=7.1.0"
|
||||||
},
|
},
|
||||||
"5.0.0": {
|
"5.0.0": {
|
||||||
|
"cordova-android": ">=9.0.0",
|
||||||
|
"cordova-ios": ">=5.1.0",
|
||||||
|
"cordova": ">=9.0.0"
|
||||||
|
},
|
||||||
|
"6.0.0": {
|
||||||
"cordova": ">100"
|
"cordova": ">100"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^4.3.0",
|
"@cordova/eslint-config": "^3.0.0"
|
||||||
"eslint-config-semistandard": "^11.0.0",
|
|
||||||
"eslint-config-standard": "^10.2.1",
|
|
||||||
"eslint-plugin-import": "^2.3.0",
|
|
||||||
"eslint-plugin-node": "^5.0.0",
|
|
||||||
"eslint-plugin-promise": "^3.5.0",
|
|
||||||
"eslint-plugin-standard": "^3.0.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
plugin.xml
17
plugin.xml
@@ -21,7 +21,7 @@
|
|||||||
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
id="cordova-plugin-camera"
|
id="cordova-plugin-camera"
|
||||||
version="4.2.0">
|
version="5.0.2">
|
||||||
<name>Camera</name>
|
<name>Camera</name>
|
||||||
<description>Cordova Camera Plugin</description>
|
<description>Cordova Camera Plugin</description>
|
||||||
<license>Apache 2.0</license>
|
<license>Apache 2.0</license>
|
||||||
@@ -30,8 +30,9 @@
|
|||||||
<issue>https://github.com/apache/cordova-plugin-camera/issues</issue>
|
<issue>https://github.com/apache/cordova-plugin-camera/issues</issue>
|
||||||
|
|
||||||
<engines>
|
<engines>
|
||||||
<engine name="cordova" version=">=7.1.0"/>
|
<engine name="cordova" version=">=9.0.0"/>
|
||||||
<engine name="cordova-android" version=">=6.3.0" />
|
<engine name="cordova-android" version=">=9.0.0" />
|
||||||
|
<engine name="cordova-ios" version=">=5.1.0" />
|
||||||
</engines>
|
</engines>
|
||||||
|
|
||||||
<js-module src="www/CameraConstants.js" name="Camera">
|
<js-module src="www/CameraConstants.js" name="Camera">
|
||||||
@@ -59,7 +60,7 @@
|
|||||||
<config-file target="AndroidManifest.xml" parent="application">
|
<config-file target="AndroidManifest.xml" parent="application">
|
||||||
<provider
|
<provider
|
||||||
android:name="org.apache.cordova.camera.FileProvider"
|
android:name="org.apache.cordova.camera.FileProvider"
|
||||||
android:authorities="${applicationId}.provider"
|
android:authorities="${applicationId}.cordova.plugin.camera.provider"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:grantUriPermissions="true" >
|
android:grantUriPermissions="true" >
|
||||||
<meta-data
|
<meta-data
|
||||||
@@ -69,10 +70,10 @@
|
|||||||
</config-file>
|
</config-file>
|
||||||
|
|
||||||
<source-file src="src/android/CameraLauncher.java" target-dir="src/org/apache/cordova/camera" />
|
<source-file src="src/android/CameraLauncher.java" target-dir="src/org/apache/cordova/camera" />
|
||||||
<source-file src="src/android/CordovaUri.java" target-dir="src/org/apache/cordova/camera" />
|
|
||||||
<source-file src="src/android/FileHelper.java" target-dir="src/org/apache/cordova/camera" />
|
<source-file src="src/android/FileHelper.java" target-dir="src/org/apache/cordova/camera" />
|
||||||
<source-file src="src/android/ExifHelper.java" target-dir="src/org/apache/cordova/camera" />
|
<source-file src="src/android/ExifHelper.java" target-dir="src/org/apache/cordova/camera" />
|
||||||
<source-file src="src/android/FileProvider.java" target-dir="src/org/apache/cordova/camera" />
|
<source-file src="src/android/FileProvider.java" target-dir="src/org/apache/cordova/camera" />
|
||||||
|
<source-file src="src/android/GalleryPathVO.java" target-dir="src/org/apache/cordova/camera" />
|
||||||
<source-file src="src/android/xml/camera_provider_paths.xml" target-dir="res/xml" />
|
<source-file src="src/android/xml/camera_provider_paths.xml" target-dir="res/xml" />
|
||||||
|
|
||||||
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
||||||
@@ -151,12 +152,12 @@
|
|||||||
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
||||||
<clobbers target="CameraPopoverHandle" />
|
<clobbers target="CameraPopoverHandle" />
|
||||||
</js-module>
|
</js-module>
|
||||||
|
|
||||||
<header-file src="src/osx/CDVCamera.h" />
|
<header-file src="src/osx/CDVCamera.h" />
|
||||||
<source-file src="src/osx/CDVCamera.m" />
|
<source-file src="src/osx/CDVCamera.m" />
|
||||||
|
|
||||||
<framework src="Quartz.framework" />
|
<framework src="Quartz.framework" />
|
||||||
<framework src="AppKit.framework" />
|
<framework src="AppKit.framework" />
|
||||||
</platform>
|
</platform>
|
||||||
|
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package org.apache.cordova.camera;
|
|||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@@ -34,6 +35,7 @@ import android.media.ExifInterface;
|
|||||||
import android.media.MediaScannerConnection;
|
import android.media.MediaScannerConnection;
|
||||||
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
|
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
@@ -51,7 +53,6 @@ import org.json.JSONException;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -69,7 +70,6 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
|
|
||||||
private static final int DATA_URL = 0; // Return base64 encoded string
|
private static final int DATA_URL = 0; // Return base64 encoded string
|
||||||
private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android)
|
private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android)
|
||||||
private static final int NATIVE_URI = 2; // On Android, this is the same as FILE_URI
|
|
||||||
|
|
||||||
private static final int PHOTOLIBRARY = 0; // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
|
private static final int PHOTOLIBRARY = 0; // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
|
||||||
private static final int CAMERA = 1; // Take picture from camera
|
private static final int CAMERA = 1; // Take picture from camera
|
||||||
@@ -92,6 +92,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
private static final String GET_All = "Get All";
|
private static final String GET_All = "Get All";
|
||||||
private static final String CROPPED_URI_KEY = "croppedUri";
|
private static final String CROPPED_URI_KEY = "croppedUri";
|
||||||
private static final String IMAGE_URI_KEY = "imageUri";
|
private static final String IMAGE_URI_KEY = "imageUri";
|
||||||
|
private static final String IMAGE_FILE_PATH_KEY = "imageFilePath";
|
||||||
|
|
||||||
private static final String TAKE_PICTURE_ACTION = "takePicture";
|
private static final String TAKE_PICTURE_ACTION = "takePicture";
|
||||||
|
|
||||||
@@ -109,7 +110,8 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
private int mQuality; // Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
|
private int mQuality; // Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
|
||||||
private int targetWidth; // desired width of the image
|
private int targetWidth; // desired width of the image
|
||||||
private int targetHeight; // desired height of the image
|
private int targetHeight; // desired height of the image
|
||||||
private CordovaUri imageUri; // Uri of captured image
|
private Uri imageUri; // Uri of captured image
|
||||||
|
private String imageFilePath; // File where the image is stored
|
||||||
private int encodingType; // Type of encoding to use
|
private int encodingType; // Type of encoding to use
|
||||||
private int mediaType; // What type of media to retrieve
|
private int mediaType; // What type of media to retrieve
|
||||||
private int destType; // Source type (needs to be saved for the permission handling)
|
private int destType; // Source type (needs to be saved for the permission handling)
|
||||||
@@ -127,6 +129,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
private MediaScannerConnection conn; // Used to update gallery app with newly-written files
|
private MediaScannerConnection conn; // Used to update gallery app with newly-written files
|
||||||
private Uri scanMe; // Uri of image to be added to content store
|
private Uri scanMe; // Uri of image to be added to content store
|
||||||
private Uri croppedUri;
|
private Uri croppedUri;
|
||||||
|
private String croppedFilePath;
|
||||||
private ExifHelper exifData; // Exif data from source
|
private ExifHelper exifData; // Exif data from source
|
||||||
private String applicationId;
|
private String applicationId;
|
||||||
|
|
||||||
@@ -290,10 +293,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
|
|
||||||
// Specify file so that large image is captured and returned
|
// Specify file so that large image is captured and returned
|
||||||
File photo = createCaptureFile(encodingType);
|
File photo = createCaptureFile(encodingType);
|
||||||
this.imageUri = new CordovaUri(FileProvider.getUriForFile(cordova.getActivity(),
|
this.imageFilePath = photo.getAbsolutePath();
|
||||||
applicationId + ".provider",
|
this.imageUri = FileProvider.getUriForFile(cordova.getActivity(),
|
||||||
photo));
|
applicationId + ".cordova.plugin.camera.provider",
|
||||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri.getCorrectUri());
|
photo);
|
||||||
|
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
|
||||||
//We can write to this URI, this will hopefully allow us to write files to get to the next step
|
//We can write to this URI, this will hopefully allow us to write files to get to the next step
|
||||||
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||||
|
|
||||||
@@ -360,6 +364,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
String title = GET_PICTURE;
|
String title = GET_PICTURE;
|
||||||
croppedUri = null;
|
croppedUri = null;
|
||||||
|
croppedFilePath = null;
|
||||||
if (this.mediaType == PICTURE) {
|
if (this.mediaType == PICTURE) {
|
||||||
intent.setType("image/*");
|
intent.setType("image/*");
|
||||||
if (this.allowEdit) {
|
if (this.allowEdit) {
|
||||||
@@ -375,8 +380,9 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
intent.putExtra("aspectX", 1);
|
intent.putExtra("aspectX", 1);
|
||||||
intent.putExtra("aspectY", 1);
|
intent.putExtra("aspectY", 1);
|
||||||
}
|
}
|
||||||
File photo = createCaptureFile(JPEG);
|
File croppedFile = createCaptureFile(JPEG);
|
||||||
croppedUri = Uri.fromFile(photo);
|
croppedFilePath = croppedFile.getAbsolutePath();
|
||||||
|
croppedUri = Uri.fromFile(croppedFile);
|
||||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, croppedUri);
|
intent.putExtra(MediaStore.EXTRA_OUTPUT, croppedUri);
|
||||||
} else {
|
} else {
|
||||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||||
@@ -401,57 +407,57 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* Brings up the UI to perform crop on passed image URI
|
||||||
* Brings up the UI to perform crop on passed image URI
|
*
|
||||||
*
|
* @param picUri
|
||||||
* @param picUri
|
*/
|
||||||
*/
|
private void performCrop(Uri picUri, int destType, Intent cameraIntent) {
|
||||||
private void performCrop(Uri picUri, int destType, Intent cameraIntent) {
|
try {
|
||||||
try {
|
Intent cropIntent = new Intent("com.android.camera.action.CROP");
|
||||||
Intent cropIntent = new Intent("com.android.camera.action.CROP");
|
// indicate image type and Uri
|
||||||
// indicate image type and Uri
|
cropIntent.setDataAndType(picUri, "image/*");
|
||||||
cropIntent.setDataAndType(picUri, "image/*");
|
// set crop properties
|
||||||
// set crop properties
|
cropIntent.putExtra("crop", "true");
|
||||||
cropIntent.putExtra("crop", "true");
|
|
||||||
|
|
||||||
|
|
||||||
// indicate output X and Y
|
// indicate output X and Y
|
||||||
if (targetWidth > 0) {
|
if (targetWidth > 0) {
|
||||||
cropIntent.putExtra("outputX", targetWidth);
|
cropIntent.putExtra("outputX", targetWidth);
|
||||||
|
}
|
||||||
|
if (targetHeight > 0) {
|
||||||
|
cropIntent.putExtra("outputY", targetHeight);
|
||||||
|
}
|
||||||
|
if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) {
|
||||||
|
cropIntent.putExtra("aspectX", 1);
|
||||||
|
cropIntent.putExtra("aspectY", 1);
|
||||||
|
}
|
||||||
|
// create new file handle to get full resolution crop
|
||||||
|
croppedFilePath = createCaptureFile(this.encodingType, System.currentTimeMillis() + "").getAbsolutePath();
|
||||||
|
croppedUri = Uri.parse(croppedFilePath);
|
||||||
|
cropIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
cropIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||||
|
cropIntent.putExtra("output", croppedUri);
|
||||||
|
|
||||||
|
|
||||||
|
// start the activity - we handle returning in onActivityResult
|
||||||
|
|
||||||
|
if (this.cordova != null) {
|
||||||
|
this.cordova.startActivityForResult((CordovaPlugin) this,
|
||||||
|
cropIntent, CROP_CAMERA + destType);
|
||||||
|
}
|
||||||
|
} catch (ActivityNotFoundException anfe) {
|
||||||
|
LOG.e(LOG_TAG, "Crop operation not supported on this device");
|
||||||
|
try {
|
||||||
|
processResultFromCamera(destType, cameraIntent);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
LOG.e(LOG_TAG, "Unable to write to file");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (targetHeight > 0) {
|
|
||||||
cropIntent.putExtra("outputY", targetHeight);
|
|
||||||
}
|
|
||||||
if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) {
|
|
||||||
cropIntent.putExtra("aspectX", 1);
|
|
||||||
cropIntent.putExtra("aspectY", 1);
|
|
||||||
}
|
|
||||||
// create new file handle to get full resolution crop
|
|
||||||
croppedUri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
|
|
||||||
cropIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
||||||
cropIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
||||||
cropIntent.putExtra("output", croppedUri);
|
|
||||||
|
|
||||||
|
|
||||||
// start the activity - we handle returning in onActivityResult
|
|
||||||
|
|
||||||
if (this.cordova != null) {
|
|
||||||
this.cordova.startActivityForResult((CordovaPlugin) this,
|
|
||||||
cropIntent, CROP_CAMERA + destType);
|
|
||||||
}
|
|
||||||
} catch (ActivityNotFoundException anfe) {
|
|
||||||
LOG.e(LOG_TAG, "Crop operation not supported on this device");
|
|
||||||
try {
|
|
||||||
processResultFromCamera(destType, cameraIntent);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
LOG.e(LOG_TAG, "Unable to write to file");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies all needed transformation to the image received from the camera.
|
* Applies all needed transformation to the image received from the camera.
|
||||||
@@ -466,8 +472,8 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
ExifHelper exif = new ExifHelper();
|
ExifHelper exif = new ExifHelper();
|
||||||
|
|
||||||
String sourcePath = (this.allowEdit && this.croppedUri != null) ?
|
String sourcePath = (this.allowEdit && this.croppedUri != null) ?
|
||||||
FileHelper.stripFileProtocol(this.croppedUri.toString()) :
|
this.croppedFilePath :
|
||||||
this.imageUri.getFilePath();
|
this.imageFilePath;
|
||||||
|
|
||||||
|
|
||||||
if (this.encodingType == JPEG) {
|
if (this.encodingType == JPEG) {
|
||||||
@@ -489,16 +495,18 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
// in the gallery and the modified image is saved in the temporary
|
// in the gallery and the modified image is saved in the temporary
|
||||||
// directory
|
// directory
|
||||||
if (this.saveToPhotoAlbum) {
|
if (this.saveToPhotoAlbum) {
|
||||||
galleryUri = Uri.fromFile(new File(getPicturesPath()));
|
GalleryPathVO galleryPathVO = getPicturesPath();
|
||||||
|
galleryUri = Uri.fromFile(new File(galleryPathVO.getGalleryPath()));
|
||||||
|
|
||||||
if (this.allowEdit && this.croppedUri != null) {
|
if (this.allowEdit && this.croppedUri != null) {
|
||||||
writeUncompressedImage(croppedUri, galleryUri);
|
writeUncompressedImage(croppedUri, galleryUri);
|
||||||
} else {
|
} else {
|
||||||
Uri imageUri = this.imageUri.getFileUri();
|
if (Build.VERSION.SDK_INT <= 28) { // Between LOLLIPOP_MR1 and P, can be changed later to the constant Build.VERSION_CODES.P
|
||||||
writeUncompressedImage(imageUri, galleryUri);
|
writeTakenPictureToGalleryLowerThanAndroidQ(galleryUri);
|
||||||
|
} else { // Android Q or higher
|
||||||
|
writeTakenPictureToGalleryStartingFromAndroidQ(galleryPathVO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshGallery(galleryUri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If sending base64 image back
|
// If sending base64 image back
|
||||||
@@ -526,7 +534,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If sending filename back
|
// If sending filename back
|
||||||
else if (destType == FILE_URI || destType == NATIVE_URI) {
|
else if (destType == FILE_URI) {
|
||||||
// If all this is true we shouldn't compress the image.
|
// If all this is true we shouldn't compress the image.
|
||||||
if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 &&
|
if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 &&
|
||||||
!this.correctOrientation) {
|
!this.correctOrientation) {
|
||||||
@@ -539,10 +547,10 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
|
Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
|
||||||
|
|
||||||
if (this.allowEdit && this.croppedUri != null) {
|
if (this.allowEdit && this.croppedUri != null) {
|
||||||
Uri croppedUri = Uri.fromFile(new File(getFileNameFromUri(this.croppedUri)));
|
Uri croppedUri = Uri.parse(croppedFilePath);
|
||||||
writeUncompressedImage(croppedUri, uri);
|
writeUncompressedImage(croppedUri, uri);
|
||||||
} else {
|
} else {
|
||||||
Uri imageUri = this.imageUri.getFileUri();
|
Uri imageUri = this.imageUri;
|
||||||
writeUncompressedImage(imageUri, uri);
|
writeUncompressedImage(imageUri, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,9 +570,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
|
|
||||||
// Add compressed version of captured image to returned media store Uri
|
// Add compressed version of captured image to returned media store Uri
|
||||||
OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri);
|
OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri);
|
||||||
CompressFormat compressFormat = encodingType == JPEG ?
|
CompressFormat compressFormat = getCompressFormatForEncodingType(encodingType);
|
||||||
CompressFormat.JPEG :
|
|
||||||
CompressFormat.PNG;
|
|
||||||
|
|
||||||
bitmap.compress(compressFormat, this.mQuality, os);
|
bitmap.compress(compressFormat, this.mQuality, os);
|
||||||
os.close();
|
os.close();
|
||||||
@@ -588,22 +594,45 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cleanup(FILE_URI, this.imageUri.getFileUri(), galleryUri, bitmap);
|
this.cleanup(FILE_URI, this.imageUri, galleryUri, bitmap);
|
||||||
bitmap = null;
|
bitmap = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPicturesPath() {
|
private void writeTakenPictureToGalleryLowerThanAndroidQ(Uri galleryUri) throws IOException {
|
||||||
|
writeUncompressedImage(imageUri, galleryUri);
|
||||||
|
refreshGallery(galleryUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeTakenPictureToGalleryStartingFromAndroidQ(GalleryPathVO galleryPathVO) throws IOException {
|
||||||
|
// Starting from Android Q, working with the ACTION_MEDIA_SCANNER_SCAN_FILE intent is deprecated
|
||||||
|
// https://developer.android.com/reference/android/content/Intent#ACTION_MEDIA_SCANNER_SCAN_FILE
|
||||||
|
// we must start working with the MediaStore from Android Q on.
|
||||||
|
ContentResolver resolver = this.cordova.getActivity().getContentResolver();
|
||||||
|
ContentValues contentValues = new ContentValues();
|
||||||
|
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, galleryPathVO.getGalleryFileName());
|
||||||
|
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, getMimetypeForFormat(encodingType));
|
||||||
|
Uri galleryOutputUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
|
||||||
|
|
||||||
|
InputStream fileStream = org.apache.cordova.camera.FileHelper.getInputStreamFromUriString(imageUri.toString(), cordova);
|
||||||
|
writeUncompressedImage(fileStream, galleryOutputUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompressFormat getCompressFormatForEncodingType(int encodingType) {
|
||||||
|
return encodingType == JPEG ? CompressFormat.JPEG : CompressFormat.PNG;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GalleryPathVO getPicturesPath() {
|
||||||
String timeStamp = new SimpleDateFormat(TIME_FORMAT).format(new Date());
|
String timeStamp = new SimpleDateFormat(TIME_FORMAT).format(new Date());
|
||||||
String imageFileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? JPEG_EXTENSION : PNG_EXTENSION);
|
String imageFileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? JPEG_EXTENSION : PNG_EXTENSION);
|
||||||
File storageDir = Environment.getExternalStoragePublicDirectory(
|
File storageDir = Environment.getExternalStoragePublicDirectory(
|
||||||
Environment.DIRECTORY_PICTURES);
|
Environment.DIRECTORY_PICTURES);
|
||||||
storageDir.mkdirs();
|
storageDir.mkdirs();
|
||||||
String galleryPath = storageDir.getAbsolutePath() + "/" + imageFileName;
|
return new GalleryPathVO(storageDir.getAbsolutePath(), imageFileName);
|
||||||
return galleryPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshGallery(Uri contentUri) {
|
private void refreshGallery(Uri contentUri) {
|
||||||
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
|
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
|
||||||
|
// Starting from Android Q, working with the ACTION_MEDIA_SCANNER_SCAN_FILE intent is deprecated
|
||||||
mediaScanIntent.setData(contentUri);
|
mediaScanIntent.setData(contentUri);
|
||||||
this.cordova.getActivity().sendBroadcast(mediaScanIntent);
|
this.cordova.getActivity().sendBroadcast(mediaScanIntent);
|
||||||
}
|
}
|
||||||
@@ -635,9 +664,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
String modifiedPath = getTempDirectoryPath() + "/" + fileName;
|
String modifiedPath = getTempDirectoryPath() + "/" + fileName;
|
||||||
|
|
||||||
OutputStream os = new FileOutputStream(modifiedPath);
|
OutputStream os = new FileOutputStream(modifiedPath);
|
||||||
CompressFormat compressFormat = this.encodingType == JPEG ?
|
CompressFormat compressFormat = getCompressFormatForEncodingType(this.encodingType);
|
||||||
CompressFormat.JPEG :
|
|
||||||
CompressFormat.PNG;
|
|
||||||
|
|
||||||
bitmap.compress(compressFormat, this.mQuality, os);
|
bitmap.compress(compressFormat, this.mQuality, os);
|
||||||
os.close();
|
os.close();
|
||||||
@@ -674,74 +701,80 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int rotate = 0;
|
|
||||||
|
|
||||||
String fileLocation = FileHelper.getRealPath(uri, this.cordova);
|
String fileLocation = FileHelper.getRealPath(uri, this.cordova);
|
||||||
LOG.d(LOG_TAG, "File location is: " + fileLocation);
|
LOG.d(LOG_TAG, "File location is: " + fileLocation);
|
||||||
|
|
||||||
String uriString = uri.toString();
|
String uriString = uri.toString();
|
||||||
|
String finalLocation = fileLocation != null ? fileLocation : uriString;
|
||||||
String mimeType = FileHelper.getMimeType(uriString, this.cordova);
|
String mimeType = FileHelper.getMimeType(uriString, this.cordova);
|
||||||
|
|
||||||
// If you ask for video or the selected file doesn't have JPEG or PNG mime type
|
if (finalLocation == null) {
|
||||||
// there will be no attempt to resize any returned data
|
this.failPicture("Error retrieving result.");
|
||||||
if (this.mediaType == VIDEO || !(JPEG_MIME_TYPE.equalsIgnoreCase(mimeType) || PNG_MIME_TYPE.equalsIgnoreCase(mimeType))) {
|
} else {
|
||||||
this.callbackContext.success(fileLocation);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
// This is a special case to just return the path as no scaling,
|
// If you ask for video or the selected file doesn't have JPEG or PNG mime type
|
||||||
// rotating, nor compressing needs to be done
|
// there will be no attempt to resize any returned data
|
||||||
if (this.targetHeight == -1 && this.targetWidth == -1 &&
|
if (this.mediaType == VIDEO || !(JPEG_MIME_TYPE.equalsIgnoreCase(mimeType) || PNG_MIME_TYPE.equalsIgnoreCase(mimeType))) {
|
||||||
(destType == FILE_URI || destType == NATIVE_URI) && !this.correctOrientation &&
|
this.callbackContext.success(finalLocation);
|
||||||
mimeType != null && mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType)))
|
}
|
||||||
{
|
else {
|
||||||
this.callbackContext.success(uriString);
|
|
||||||
} else {
|
|
||||||
Bitmap bitmap = null;
|
|
||||||
try {
|
|
||||||
bitmap = getScaledAndRotatedBitmap(uriString);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if (bitmap == null) {
|
|
||||||
LOG.d(LOG_TAG, "I either have a null image path or bitmap");
|
|
||||||
this.failPicture("Unable to create bitmap!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If sending base64 image back
|
// This is a special case to just return the path as no scaling,
|
||||||
if (destType == DATA_URL) {
|
// rotating, nor compressing needs to be done
|
||||||
this.processPicture(bitmap, this.encodingType);
|
if (this.targetHeight == -1 && this.targetWidth == -1 &&
|
||||||
}
|
destType == FILE_URI && !this.correctOrientation &&
|
||||||
|
mimeType != null && mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType)))
|
||||||
// If sending filename back
|
{
|
||||||
else if (destType == FILE_URI || destType == NATIVE_URI) {
|
this.callbackContext.success(finalLocation);
|
||||||
// Did we modify the image?
|
} else {
|
||||||
if ( (this.targetHeight > 0 && this.targetWidth > 0) ||
|
Bitmap bitmap = null;
|
||||||
(this.correctOrientation && this.orientationCorrected) ||
|
try {
|
||||||
!mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType)))
|
bitmap = getScaledAndRotatedBitmap(uriString);
|
||||||
{
|
} catch (IOException e) {
|
||||||
try {
|
e.printStackTrace();
|
||||||
String modifiedPath = this.outputModifiedBitmap(bitmap, uri);
|
|
||||||
// The modified image is cached by the app in order to get around this and not have to delete you
|
|
||||||
// application cache I'm adding the current system time to the end of the file url.
|
|
||||||
this.callbackContext.success("file://" + modifiedPath + "?" + System.currentTimeMillis());
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
this.failPicture("Error retrieving image.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.callbackContext.success(fileLocation);
|
|
||||||
}
|
}
|
||||||
|
if (bitmap == null) {
|
||||||
|
LOG.d(LOG_TAG, "I either have a null image path or bitmap");
|
||||||
|
this.failPicture("Unable to create bitmap!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If sending base64 image back
|
||||||
|
if (destType == DATA_URL) {
|
||||||
|
this.processPicture(bitmap, this.encodingType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If sending filename back
|
||||||
|
else if (destType == FILE_URI) {
|
||||||
|
// Did we modify the image?
|
||||||
|
if ( (this.targetHeight > 0 && this.targetWidth > 0) ||
|
||||||
|
(this.correctOrientation && this.orientationCorrected) ||
|
||||||
|
!mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType)))
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
String modifiedPath = this.outputModifiedBitmap(bitmap, uri);
|
||||||
|
// The modified image is cached by the app in order to get around this and not have to delete you
|
||||||
|
// application cache I'm adding the current system time to the end of the file url.
|
||||||
|
this.callbackContext.success("file://" + modifiedPath + "?" + System.currentTimeMillis());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
this.failPicture("Error retrieving image.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.callbackContext.success(finalLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bitmap != null) {
|
||||||
|
bitmap.recycle();
|
||||||
|
bitmap = null;
|
||||||
|
}
|
||||||
|
System.gc();
|
||||||
}
|
}
|
||||||
if (bitmap != null) {
|
|
||||||
bitmap.recycle();
|
|
||||||
bitmap = null;
|
|
||||||
}
|
|
||||||
System.gc();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -789,7 +822,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
try {
|
try {
|
||||||
if (this.allowEdit) {
|
if (this.allowEdit) {
|
||||||
Uri tmpFile = FileProvider.getUriForFile(cordova.getActivity(),
|
Uri tmpFile = FileProvider.getUriForFile(cordova.getActivity(),
|
||||||
applicationId + ".provider",
|
applicationId + ".cordova.plugin.camera.provider",
|
||||||
createCaptureFile(this.encodingType));
|
createCaptureFile(this.encodingType));
|
||||||
performCrop(tmpFile, destType, intent);
|
performCrop(tmpFile, destType, intent);
|
||||||
} else {
|
} else {
|
||||||
@@ -888,34 +921,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
private void writeUncompressedImage(Uri src, Uri dest) throws FileNotFoundException,
|
private void writeUncompressedImage(Uri src, Uri dest) throws FileNotFoundException,
|
||||||
IOException {
|
IOException {
|
||||||
|
|
||||||
FileInputStream fis = new FileInputStream(FileHelper.stripFileProtocol(src.toString()));
|
InputStream fis = FileHelper.getInputStreamFromUriString(src.toString(), cordova);
|
||||||
writeUncompressedImage(fis, dest);
|
writeUncompressedImage(fis, dest);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create entry in media store for image
|
|
||||||
*
|
|
||||||
* @return uri
|
|
||||||
*/
|
|
||||||
private Uri getUriFromMediaStore() {
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
values.put(MediaStore.Images.Media.MIME_TYPE, JPEG_MIME_TYPE);
|
|
||||||
Uri uri;
|
|
||||||
try {
|
|
||||||
uri = this.cordova.getActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
LOG.d(LOG_TAG, "Can't write to external media storage.");
|
|
||||||
try {
|
|
||||||
uri = this.cordova.getActivity().getContentResolver().insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
|
|
||||||
} catch (RuntimeException ex) {
|
|
||||||
LOG.d(LOG_TAG, "Can't write to internal media storage.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a scaled and rotated bitmap based on the target width and height
|
* Return a scaled and rotated bitmap based on the target width and height
|
||||||
*
|
*
|
||||||
@@ -1246,9 +1256,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
*/
|
*/
|
||||||
public void processPicture(Bitmap bitmap, int encodingType) {
|
public void processPicture(Bitmap bitmap, int encodingType) {
|
||||||
ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream();
|
ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream();
|
||||||
CompressFormat compressFormat = encodingType == JPEG ?
|
CompressFormat compressFormat = getCompressFormatForEncodingType(encodingType);
|
||||||
CompressFormat.JPEG :
|
|
||||||
CompressFormat.PNG;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (bitmap.compress(compressFormat, mQuality, jpeg_data)) {
|
if (bitmap.compress(compressFormat, mQuality, jpeg_data)) {
|
||||||
@@ -1336,11 +1344,15 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
state.putBoolean("saveToPhotoAlbum", this.saveToPhotoAlbum);
|
state.putBoolean("saveToPhotoAlbum", this.saveToPhotoAlbum);
|
||||||
|
|
||||||
if (this.croppedUri != null) {
|
if (this.croppedUri != null) {
|
||||||
state.putString(CROPPED_URI_KEY, this.croppedUri.toString());
|
state.putString(CROPPED_URI_KEY, this.croppedFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.imageUri != null) {
|
if (this.imageUri != null) {
|
||||||
state.putString(IMAGE_URI_KEY, this.imageUri.getFileUri().toString());
|
state.putString(IMAGE_URI_KEY, this.imageFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.imageFilePath != null) {
|
||||||
|
state.putString(IMAGE_FILE_PATH_KEY, this.imageFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
@@ -1365,28 +1377,13 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
|
|
||||||
if (state.containsKey(IMAGE_URI_KEY)) {
|
if (state.containsKey(IMAGE_URI_KEY)) {
|
||||||
//I have no idea what type of URI is being passed in
|
//I have no idea what type of URI is being passed in
|
||||||
this.imageUri = new CordovaUri(Uri.parse(state.getString(IMAGE_URI_KEY)));
|
this.imageUri = Uri.parse(state.getString(IMAGE_URI_KEY));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.containsKey(IMAGE_FILE_PATH_KEY)) {
|
||||||
|
this.imageFilePath = state.getString(IMAGE_FILE_PATH_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.callbackContext = callbackContext;
|
this.callbackContext = callbackContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This is dirty, but it does the job.
|
|
||||||
*
|
|
||||||
* Since the FilesProvider doesn't really provide you a way of getting a URL from the file,
|
|
||||||
* and since we actually need the Camera to create the file for us most of the time, we don't
|
|
||||||
* actually write the file, just generate the location based on a timestamp, we need to get it
|
|
||||||
* back from the Intent.
|
|
||||||
*
|
|
||||||
* However, the FilesProvider preserves the path, so we can at least write to it from here, since
|
|
||||||
* we own the context in this case.
|
|
||||||
*/
|
|
||||||
private String getFileNameFromUri(Uri uri) {
|
|
||||||
String fullUri = uri.toString();
|
|
||||||
String partial_path = fullUri.split("external_files")[1];
|
|
||||||
File external_storage = Environment.getExternalStorageDirectory();
|
|
||||||
String path = external_storage.getAbsolutePath() + partial_path;
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
or more contributor license agreements. See the NOTICE file
|
|
||||||
distributed with this work for additional information
|
|
||||||
regarding copyright ownership. The ASF licenses this file
|
|
||||||
to you under the Apache License, Version 2.0 (the
|
|
||||||
"License"); you may not use this file except in compliance
|
|
||||||
with the License. You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing,
|
|
||||||
software distributed under the License is distributed on an
|
|
||||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
KIND, either express or implied. See the License for the
|
|
||||||
specific language governing permissions and limitations
|
|
||||||
under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.cordova.camera;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.support.v4.content.FileProvider;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This class exists because Andorid FilesProvider doesn't work on Android 4.4.4 and below and throws
|
|
||||||
* weird errors. I'm not sure why writing to shared cache directories is somehow verboten, but it is
|
|
||||||
* and this error is irritating for a Compatibility library to have.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class CordovaUri {
|
|
||||||
|
|
||||||
private Uri androidUri;
|
|
||||||
private String fileName;
|
|
||||||
private Uri fileUri;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We always expect a FileProvider string to be passed in for the file that we create
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
CordovaUri (Uri inputUri)
|
|
||||||
{
|
|
||||||
//Determine whether the file is a content or file URI
|
|
||||||
if(inputUri.getScheme().equals("content"))
|
|
||||||
{
|
|
||||||
androidUri = inputUri;
|
|
||||||
fileName = getFileNameFromUri(androidUri);
|
|
||||||
fileUri = Uri.parse("file://" + fileName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fileUri = inputUri;
|
|
||||||
fileName = FileHelper.stripFileProtocol(inputUri.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Uri getFileUri()
|
|
||||||
{
|
|
||||||
return fileUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFilePath()
|
|
||||||
{
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This only gets called by takePicture
|
|
||||||
*/
|
|
||||||
|
|
||||||
public Uri getCorrectUri()
|
|
||||||
{
|
|
||||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
|
||||||
return androidUri;
|
|
||||||
else
|
|
||||||
return fileUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is dirty, but it does the job.
|
|
||||||
*
|
|
||||||
* Since the FilesProvider doesn't really provide you a way of getting a URL from the file,
|
|
||||||
* and since we actually need the Camera to create the file for us most of the time, we don't
|
|
||||||
* actually write the file, just generate the location based on a timestamp, we need to get it
|
|
||||||
* back from the Intent.
|
|
||||||
*
|
|
||||||
* However, the FilesProvider preserves the path, so we can at least write to it from here, since
|
|
||||||
* we own the context in this case.
|
|
||||||
*/
|
|
||||||
|
|
||||||
private String getFileNameFromUri(Uri uri) {
|
|
||||||
String fullUri = uri.toString();
|
|
||||||
String partial_path = fullUri.split("external_files")[1];
|
|
||||||
File external_storage = Environment.getExternalStorageDirectory();
|
|
||||||
String path = external_storage.getAbsolutePath() + partial_path;
|
|
||||||
return path;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -50,16 +50,7 @@ public class FileHelper {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public static String getRealPath(Uri uri, CordovaInterface cordova) {
|
public static String getRealPath(Uri uri, CordovaInterface cordova) {
|
||||||
String realPath = null;
|
return FileHelper.getRealPathFromURI(cordova.getActivity(), uri);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < 11)
|
|
||||||
realPath = FileHelper.getRealPathFromURI_BelowAPI11(cordova.getActivity(), uri);
|
|
||||||
|
|
||||||
// SDK >= 11
|
|
||||||
else
|
|
||||||
realPath = FileHelper.getRealPathFromURI_API11_And_Above(cordova.getActivity(), uri);
|
|
||||||
|
|
||||||
return realPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,11 +66,9 @@ public class FileHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
public static String getRealPathFromURI_API11_And_Above(final Context context, final Uri uri) {
|
public static String getRealPathFromURI(final Context context, final Uri uri) {
|
||||||
|
|
||||||
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
|
|
||||||
// DocumentProvider
|
// DocumentProvider
|
||||||
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
|
if (DocumentsContract.isDocumentUri(context, uri)) {
|
||||||
|
|
||||||
// ExternalStorageProvider
|
// ExternalStorageProvider
|
||||||
if (isExternalStorageDocument(uri)) {
|
if (isExternalStorageDocument(uri)) {
|
||||||
|
|||||||
43
src/android/GalleryPathVO.java
Normal file
43
src/android/GalleryPathVO.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.cordova.camera;
|
||||||
|
|
||||||
|
public class GalleryPathVO {
|
||||||
|
private final String galleryPath;
|
||||||
|
private String picturesDirectory;
|
||||||
|
private String galleryFileName;
|
||||||
|
|
||||||
|
public GalleryPathVO(String picturesDirectory, String galleryFileName) {
|
||||||
|
this.picturesDirectory = picturesDirectory;
|
||||||
|
this.galleryFileName = galleryFileName;
|
||||||
|
this.galleryPath = this.picturesDirectory + "/" + this.galleryFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGalleryPath() {
|
||||||
|
return galleryPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPicturesDirectory() {
|
||||||
|
return picturesDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGalleryFileName() {
|
||||||
|
return galleryFileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,5 +17,5 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<external-path name="external_files" path="."/>
|
<cache-path name="cache_files" path="." />
|
||||||
</paths>
|
</paths>
|
||||||
@@ -112,7 +112,7 @@ function capture (success, errorCallback, opts) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (navigator.getUserMedia) {
|
if (navigator.getUserMedia) {
|
||||||
navigator.getUserMedia({video: true, audio: false}, successCallback, errorCallback);
|
navigator.getUserMedia({ video: true, audio: false }, successCallback, errorCallback);
|
||||||
} else {
|
} else {
|
||||||
alert('Browser does not support camera :(');
|
alert('Browser does not support camera :(');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,7 @@
|
|||||||
|
|
||||||
enum CDVDestinationType {
|
enum CDVDestinationType {
|
||||||
DestinationTypeDataUrl = 0,
|
DestinationTypeDataUrl = 0,
|
||||||
DestinationTypeFileUri,
|
DestinationTypeFileUri
|
||||||
DestinationTypeNativeUri
|
|
||||||
};
|
};
|
||||||
typedef NSUInteger CDVDestinationType;
|
typedef NSUInteger CDVDestinationType;
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ static NSString* toBase64(NSData* data) {
|
|||||||
[weakSelf sendNoPermissionResult:command.callbackId];
|
[weakSelf sendNoPermissionResult:command.callbackId];
|
||||||
}]];
|
}]];
|
||||||
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Settings", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Settings", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
|
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
|
||||||
[weakSelf sendNoPermissionResult:command.callbackId];
|
[weakSelf sendNoPermissionResult:command.callbackId];
|
||||||
}]];
|
}]];
|
||||||
[weakSelf.viewController presentViewController:alertController animated:YES completion:nil];
|
[weakSelf.viewController presentViewController:alertController animated:YES completion:nil];
|
||||||
@@ -383,6 +383,7 @@ static NSString* toBase64(NSData* data) {
|
|||||||
}
|
}
|
||||||
[[self locationManager] startUpdatingLocation];
|
[[self locationManager] startUpdatingLocation];
|
||||||
}
|
}
|
||||||
|
data = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -396,15 +397,10 @@ static NSString* toBase64(NSData* data) {
|
|||||||
- (NSString*)tempFilePath:(NSString*)extension
|
- (NSString*)tempFilePath:(NSString*)extension
|
||||||
{
|
{
|
||||||
NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
|
NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
|
||||||
NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by Apple (vs [NSFileManager defaultManager]) to be threadsafe
|
|
||||||
NSString* filePath;
|
|
||||||
|
|
||||||
// unique file name
|
// unique file name
|
||||||
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
|
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
|
||||||
NSNumber *timeStampObj = [NSNumber numberWithDouble: timeStamp];
|
NSNumber *timeStampObj = [NSNumber numberWithDouble: timeStamp];
|
||||||
do {
|
NSString* filePath = [NSString stringWithFormat:@"%@/%@%ld.%@", docsPath, CDV_PHOTO_PREFIX, [timeStampObj longValue], extension];
|
||||||
filePath = [NSString stringWithFormat:@"%@/%@%ld.%@", docsPath, CDV_PHOTO_PREFIX, [timeStampObj longValue], extension];
|
|
||||||
} while ([fileMgr fileExistsAtPath:filePath]);
|
|
||||||
|
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
@@ -444,33 +440,16 @@ static NSString* toBase64(NSData* data) {
|
|||||||
UIImage* image = nil;
|
UIImage* image = nil;
|
||||||
|
|
||||||
switch (options.destinationType) {
|
switch (options.destinationType) {
|
||||||
case DestinationTypeNativeUri:
|
case DestinationTypeDataUrl:
|
||||||
{
|
{
|
||||||
NSURL* url = [info objectForKey:UIImagePickerControllerReferenceURL];
|
image = [self retrieveImage:info options:options];
|
||||||
saveToPhotoAlbum = NO;
|
NSData* data = [self processImage:image info:info options:options];
|
||||||
// If, for example, we use sourceType = Camera, URL might be nil because image is stored in memory.
|
if (data) {
|
||||||
// In this case we must save image to device before obtaining an URI.
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:toBase64(data)];
|
||||||
if (url == nil) {
|
|
||||||
image = [self retrieveImage:info options:options];
|
|
||||||
ALAssetsLibrary* library = [ALAssetsLibrary new];
|
|
||||||
[library writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)(image.imageOrientation) completionBlock:^(NSURL *assetURL, NSError *error) {
|
|
||||||
CDVPluginResult* resultToReturn = nil;
|
|
||||||
if (error) {
|
|
||||||
resultToReturn = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]];
|
|
||||||
} else {
|
|
||||||
NSString* nativeUri = [[self urlTransformer:assetURL] absoluteString];
|
|
||||||
resultToReturn = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:nativeUri];
|
|
||||||
}
|
|
||||||
completion(resultToReturn);
|
|
||||||
}];
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
NSString* nativeUri = [[self urlTransformer:url] absoluteString];
|
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:nativeUri];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DestinationTypeFileUri:
|
default: // DestinationTypeFileUri
|
||||||
{
|
{
|
||||||
image = [self retrieveImage:info options:options];
|
image = [self retrieveImage:info options:options];
|
||||||
NSData* data = [self processImage:image info:info options:options];
|
NSData* data = [self processImage:image info:info options:options];
|
||||||
@@ -489,22 +468,10 @@ static NSString* toBase64(NSData* data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DestinationTypeDataUrl:
|
|
||||||
{
|
|
||||||
image = [self retrieveImage:info options:options];
|
|
||||||
NSData* data = [self processImage:image info:info options:options];
|
|
||||||
if (data) {
|
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:toBase64(data)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (saveToPhotoAlbum && image) {
|
if (saveToPhotoAlbum && image) {
|
||||||
ALAssetsLibrary* library = [ALAssetsLibrary new];
|
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
|
||||||
[library writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)(image.imageOrientation) completionBlock:nil];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
completion(result);
|
completion(result);
|
||||||
@@ -580,10 +547,8 @@ static NSString* toBase64(NSData* data) {
|
|||||||
|
|
||||||
dispatch_block_t invoke = ^ (void) {
|
dispatch_block_t invoke = ^ (void) {
|
||||||
CDVPluginResult* result;
|
CDVPluginResult* result;
|
||||||
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera && [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] != ALAuthorizationStatusAuthorized) {
|
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera && [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] != AVAuthorizationStatusAuthorized) {
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to camera"];
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to camera"];
|
||||||
} else if (picker.sourceType != UIImagePickerControllerSourceTypeCamera && ! IsAtLeastiOSVersion(@"11.0") && [ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusAuthorized) {
|
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to assets"];
|
|
||||||
} else {
|
} else {
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No Image Selected"];
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No Image Selected"];
|
||||||
}
|
}
|
||||||
@@ -686,19 +651,26 @@ static NSString* toBase64(NSData* data) {
|
|||||||
CDVPluginResult* result = nil;
|
CDVPluginResult* result = nil;
|
||||||
|
|
||||||
if (self.metadata) {
|
if (self.metadata) {
|
||||||
CGImageSourceRef sourceImage = CGImageSourceCreateWithData((__bridge CFDataRef)self.data, NULL);
|
NSData* dataCopy = [self.data mutableCopy];
|
||||||
|
CGImageSourceRef sourceImage = CGImageSourceCreateWithData((__bridge CFDataRef)dataCopy, NULL);
|
||||||
CFStringRef sourceType = CGImageSourceGetType(sourceImage);
|
CFStringRef sourceType = CGImageSourceGetType(sourceImage);
|
||||||
|
|
||||||
CGImageDestinationRef destinationImage = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)self.data, sourceType, 1, NULL);
|
CGImageDestinationRef destinationImage = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)self.data, sourceType, 1, NULL);
|
||||||
CGImageDestinationAddImageFromSource(destinationImage, sourceImage, 0, (__bridge CFDictionaryRef)self.metadata);
|
CGImageDestinationAddImageFromSource(destinationImage, sourceImage, 0, (__bridge CFDictionaryRef)self.metadata);
|
||||||
CGImageDestinationFinalize(destinationImage);
|
CGImageDestinationFinalize(destinationImage);
|
||||||
|
|
||||||
|
dataCopy = nil;
|
||||||
CFRelease(sourceImage);
|
CFRelease(sourceImage);
|
||||||
CFRelease(destinationImage);
|
CFRelease(destinationImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (options.destinationType) {
|
switch (options.destinationType) {
|
||||||
case DestinationTypeFileUri:
|
case DestinationTypeDataUrl:
|
||||||
|
{
|
||||||
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:toBase64(self.data)];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // DestinationTypeFileUri
|
||||||
{
|
{
|
||||||
NSError* err = nil;
|
NSError* err = nil;
|
||||||
NSString* extension = self.pickerController.pictureOptions.encodingType == EncodingTypePNG ? @"png":@"jpg";
|
NSString* extension = self.pickerController.pictureOptions.encodingType == EncodingTypePNG ? @"png":@"jpg";
|
||||||
@@ -713,14 +685,6 @@ static NSString* toBase64(NSData* data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DestinationTypeDataUrl:
|
|
||||||
{
|
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:toBase64(self.data)];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DestinationTypeNativeUri:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
@@ -733,8 +697,7 @@ static NSString* toBase64(NSData* data) {
|
|||||||
self.metadata = nil;
|
self.metadata = nil;
|
||||||
|
|
||||||
if (options.saveToPhotoAlbum) {
|
if (options.saveToPhotoAlbum) {
|
||||||
ALAssetsLibrary *library = [ALAssetsLibrary new];
|
UIImageWriteToSavedPhotosAlbum([[UIImage alloc] initWithData:self.data], nil, nil, nil);
|
||||||
[library writeImageDataToSavedPhotosAlbum:self.data metadata:self.metadata completionBlock:nil];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,7 @@
|
|||||||
|
|
||||||
enum CDVDestinationType {
|
enum CDVDestinationType {
|
||||||
DestinationTypeDataUrl = 0,
|
DestinationTypeDataUrl = 0,
|
||||||
DestinationTypeFileUri,
|
DestinationTypeFileUri
|
||||||
DestinationTypeNativeUri
|
|
||||||
};
|
};
|
||||||
typedef NSUInteger CDVDestinationType;
|
typedef NSUInteger CDVDestinationType;
|
||||||
|
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ static NSMutableArray *cleanUpFiles;
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns to JavaScript a URI.
|
Returns to JavaScript a URI.
|
||||||
Called when Camera.DestinationType.FILE_URI or Camera.DestinationType.NATIVE_URI.
|
Called when Camera.DestinationType.FILE_URI.
|
||||||
*/
|
*/
|
||||||
- (void)returnUri:(NSString *)path command:(CDVInvokedUrlCommand *)command options:(CDVPictureOptions *)pictureOptions {
|
- (void)returnUri:(NSString *)path command:(CDVInvokedUrlCommand *)command options:(CDVPictureOptions *)pictureOptions {
|
||||||
NSString *protocol = (pictureOptions.destinationType == DestinationTypeFileUri) ? @"file://" : @"";
|
NSString *protocol = (pictureOptions.destinationType == DestinationTypeFileUri) ? @"file://" : @"";
|
||||||
|
|||||||
@@ -190,17 +190,13 @@ function takePictureFromFileWP (successCallback, errorCallback, args) {
|
|||||||
webUIApp.removeEventListener('activated', filePickerActivationHandler);
|
webUIApp.removeEventListener('activated', filePickerActivationHandler);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (destinationType === Camera.DestinationType.FILE_URI || destinationType === Camera.DestinationType.NATIVE_URI) {
|
if (destinationType === Camera.DestinationType.FILE_URI) {
|
||||||
if (targetHeight > 0 && targetWidth > 0) {
|
if (targetHeight > 0 && targetWidth > 0) {
|
||||||
resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType);
|
resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType);
|
||||||
} else {
|
} else {
|
||||||
var storageFolder = getAppData().localFolder;
|
var storageFolder = getAppData().localFolder;
|
||||||
file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).done(function (storageFile) {
|
file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).done(function (storageFile) {
|
||||||
if (destinationType === Camera.DestinationType.NATIVE_URI) {
|
successCallback(URL.createObjectURL(storageFile));
|
||||||
successCallback('ms-appdata:///local/' + storageFile.name);
|
|
||||||
} else {
|
|
||||||
successCallback(URL.createObjectURL(storageFile));
|
|
||||||
}
|
|
||||||
}, function () {
|
}, function () {
|
||||||
errorCallback("Can't access localStorage folder.");
|
errorCallback("Can't access localStorage folder.");
|
||||||
});
|
});
|
||||||
@@ -259,17 +255,13 @@ function takePictureFromFileWindows (successCallback, errorCallback, args) {
|
|||||||
errorCallback("User didn't choose a file.");
|
errorCallback("User didn't choose a file.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (destinationType === Camera.DestinationType.FILE_URI || destinationType === Camera.DestinationType.NATIVE_URI) {
|
if (destinationType === Camera.DestinationType.FILE_URI) {
|
||||||
if (targetHeight > 0 && targetWidth > 0) {
|
if (targetHeight > 0 && targetWidth > 0) {
|
||||||
resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType);
|
resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType);
|
||||||
} else {
|
} else {
|
||||||
var storageFolder = getAppData().localFolder;
|
var storageFolder = getAppData().localFolder;
|
||||||
file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).done(function (storageFile) {
|
file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).done(function (storageFile) {
|
||||||
if (destinationType === Camera.DestinationType.NATIVE_URI) {
|
successCallback(URL.createObjectURL(storageFile));
|
||||||
successCallback('ms-appdata:///local/' + storageFile.name);
|
|
||||||
} else {
|
|
||||||
successCallback(URL.createObjectURL(storageFile));
|
|
||||||
}
|
|
||||||
}, function () {
|
}, function () {
|
||||||
errorCallback("Can't access localStorage folder.");
|
errorCallback("Can't access localStorage folder.");
|
||||||
});
|
});
|
||||||
@@ -374,7 +366,6 @@ function takePictureFromCameraWP (successCallback, errorCallback, args) {
|
|||||||
|
|
||||||
return capture.initializeAsync(captureSettings);
|
return capture.initializeAsync(captureSettings);
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
|
|
||||||
// create focus control if available
|
// create focus control if available
|
||||||
var VideoDeviceController = capture.videoDeviceController;
|
var VideoDeviceController = capture.videoDeviceController;
|
||||||
var FocusControl = VideoDeviceController.focusControl;
|
var FocusControl = VideoDeviceController.focusControl;
|
||||||
@@ -477,7 +468,6 @@ function takePictureFromCameraWP (successCallback, errorCallback, args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function captureAction () {
|
function captureAction () {
|
||||||
|
|
||||||
var encodingProperties;
|
var encodingProperties;
|
||||||
var fileName;
|
var fileName;
|
||||||
var tempFolder = getAppData().temporaryFolder;
|
var tempFolder = getAppData().temporaryFolder;
|
||||||
@@ -715,7 +705,7 @@ function takePictureFromCameraWindows (successCallback, errorCallback, args) {
|
|||||||
|
|
||||||
if (targetWidth === -1 && targetHeight === -1) {
|
if (targetWidth === -1 && targetHeight === -1) {
|
||||||
maxRes = UIMaxRes.highestAvailable;
|
maxRes = UIMaxRes.highestAvailable;
|
||||||
// Temp fix for CB-10539
|
// Temp fix for CB-10539
|
||||||
/* else if (totalPixels <= 320 * 240) {
|
/* else if (totalPixels <= 320 * 240) {
|
||||||
maxRes = UIMaxRes.verySmallQvga;
|
maxRes = UIMaxRes.verySmallQvga;
|
||||||
} */
|
} */
|
||||||
@@ -781,7 +771,7 @@ function takePictureFromCameraWindows (successCallback, errorCallback, args) {
|
|||||||
function savePhoto (picture, options, successCallback, errorCallback) {
|
function savePhoto (picture, options, successCallback, errorCallback) {
|
||||||
// success callback for capture operation
|
// success callback for capture operation
|
||||||
var success = function (picture) {
|
var success = function (picture) {
|
||||||
if (options.destinationType === Camera.DestinationType.FILE_URI || options.destinationType === Camera.DestinationType.NATIVE_URI) {
|
if (options.destinationType === Camera.DestinationType.FILE_URI) {
|
||||||
if (options.targetHeight > 0 && options.targetWidth > 0) {
|
if (options.targetHeight > 0 && options.targetWidth > 0) {
|
||||||
resizeImage(successCallback, errorCallback, picture, options.targetWidth, options.targetHeight, options.encodingType);
|
resizeImage(successCallback, errorCallback, picture, options.targetWidth, options.targetHeight, options.encodingType);
|
||||||
} else {
|
} else {
|
||||||
@@ -812,7 +802,6 @@ function savePhoto (picture, options, successCallback, errorCallback) {
|
|||||||
|
|
||||||
if (!options.saveToPhotoAlbum) {
|
if (!options.saveToPhotoAlbum) {
|
||||||
success(picture);
|
success(picture);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
|
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
|
||||||
var saveFile = function (file) {
|
var saveFile = function (file) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cordova-plugin-camera-tests",
|
"name": "cordova-plugin-camera-tests",
|
||||||
"version": "4.2.0",
|
"version": "5.0.2",
|
||||||
"description": "",
|
"description": "",
|
||||||
"cordova": {
|
"cordova": {
|
||||||
"id": "cordova-plugin-camera-tests",
|
"id": "cordova-plugin-camera-tests",
|
||||||
|
|||||||
@@ -22,12 +22,10 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:rim="http://www.blackberry.com/ns/widgets"
|
xmlns:rim="http://www.blackberry.com/ns/widgets"
|
||||||
id="cordova-plugin-camera-tests"
|
id="cordova-plugin-camera-tests"
|
||||||
version="4.2.0">
|
version="5.0.2">
|
||||||
<name>Cordova Camera Plugin Tests</name>
|
<name>Cordova Camera Plugin Tests</name>
|
||||||
<license>Apache 2.0</license>
|
<license>Apache 2.0</license>
|
||||||
|
|
||||||
<dependency id="cordova-plugin-file-transfer" />
|
|
||||||
|
|
||||||
<js-module src="tests.js" name="tests">
|
<js-module src="tests.js" name="tests">
|
||||||
</js-module>
|
</js-module>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* globals Camera, resolveLocalFileSystemURL, FileEntry, CameraPopoverOptions, FileTransfer, FileUploadOptions, LocalFileSystem, MSApp */
|
/* globals Camera, resolveLocalFileSystemURL, FileEntry, CameraPopoverOptions, LocalFileSystem, MSApp */
|
||||||
/* eslint-env jasmine */
|
/* eslint-env jasmine */
|
||||||
|
|
||||||
exports.defineAutoTests = function () {
|
exports.defineAutoTests = function () {
|
||||||
@@ -42,10 +42,8 @@ exports.defineAutoTests = function () {
|
|||||||
it('camera.spec.2 should contain three DestinationType constants', function () {
|
it('camera.spec.2 should contain three DestinationType constants', function () {
|
||||||
expect(Camera.DestinationType.DATA_URL).toBe(0);
|
expect(Camera.DestinationType.DATA_URL).toBe(0);
|
||||||
expect(Camera.DestinationType.FILE_URI).toBe(1);
|
expect(Camera.DestinationType.FILE_URI).toBe(1);
|
||||||
expect(Camera.DestinationType.NATIVE_URI).toBe(2);
|
|
||||||
expect(navigator.camera.DestinationType.DATA_URL).toBe(0);
|
expect(navigator.camera.DestinationType.DATA_URL).toBe(0);
|
||||||
expect(navigator.camera.DestinationType.FILE_URI).toBe(1);
|
expect(navigator.camera.DestinationType.FILE_URI).toBe(1);
|
||||||
expect(navigator.camera.DestinationType.NATIVE_URI).toBe(2);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('camera.spec.3 should contain two EncodingType constants', function () {
|
it('camera.spec.3 should contain two EncodingType constants', function () {
|
||||||
@@ -140,7 +138,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
|||||||
function getPictureWin (data) {
|
function getPictureWin (data) {
|
||||||
setPicture(data);
|
setPicture(data);
|
||||||
// TODO: Fix resolveLocalFileSystemURI to work with native-uri.
|
// TODO: Fix resolveLocalFileSystemURI to work with native-uri.
|
||||||
if (pictureUrl.indexOf('file:') === 0 || pictureUrl.indexOf('content:') === 0 || pictureUrl.indexOf('ms-appdata:') === 0 || pictureUrl.indexOf('assets-library:') === 0) {
|
if (pictureUrl.indexOf('file:') === 0 || pictureUrl.indexOf('content:') === 0) {
|
||||||
resolveLocalFileSystemURL(data, function (e) {
|
resolveLocalFileSystemURL(data, function (e) {
|
||||||
fileEntry = e;
|
fileEntry = e;
|
||||||
logCallback('resolveLocalFileSystemURL()', true)(e.toURL());
|
logCallback('resolveLocalFileSystemURL()', true)(e.toURL());
|
||||||
@@ -167,26 +165,6 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function uploadImage () {
|
|
||||||
var ft = new FileTransfer();
|
|
||||||
var options = new FileUploadOptions();
|
|
||||||
options.fileKey = 'photo';
|
|
||||||
options.fileName = 'test.jpg';
|
|
||||||
options.mimeType = 'image/jpeg';
|
|
||||||
ft.onprogress = function (progressEvent) {
|
|
||||||
console.log('progress: ' + progressEvent.loaded + ' of ' + progressEvent.total);
|
|
||||||
};
|
|
||||||
var server = 'http://sheltered-retreat-43956.herokuapp.com';
|
|
||||||
|
|
||||||
ft.upload(pictureUrl, server + '/upload', win, fail, options);
|
|
||||||
function win (information_back) {
|
|
||||||
log('upload complete');
|
|
||||||
}
|
|
||||||
function fail (message) {
|
|
||||||
log('upload failed: ' + JSON.stringify(message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function logCallback (apiName, success) {
|
function logCallback (apiName, success) {
|
||||||
return function () {
|
return function () {
|
||||||
log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments)));
|
log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments)));
|
||||||
@@ -194,7 +172,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select image from library using a NATIVE_URI destination type
|
* Select image from library
|
||||||
* This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL.
|
* This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL.
|
||||||
*/
|
*/
|
||||||
function readFile () {
|
function readFile () {
|
||||||
@@ -237,7 +215,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy image from library using a NATIVE_URI destination type
|
* Copy image from library
|
||||||
* This calls FileEntry.copyTo and FileEntry.moveTo.
|
* This calls FileEntry.copyTo and FileEntry.moveTo.
|
||||||
*/
|
*/
|
||||||
function copyImage () {
|
function copyImage () {
|
||||||
@@ -271,7 +249,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write image to library using a NATIVE_URI destination type
|
* Write image to library
|
||||||
* This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate.
|
* This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate.
|
||||||
*/
|
*/
|
||||||
function writeImage () {
|
function writeImage () {
|
||||||
@@ -305,7 +283,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove image from library using a NATIVE_URI destination type
|
* Remove image from library
|
||||||
* This calls FileEntry.remove.
|
* This calls FileEntry.remove.
|
||||||
*/
|
*/
|
||||||
function removeImage () {
|
function removeImage () {
|
||||||
@@ -378,7 +356,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
|||||||
|
|
||||||
var options = '';
|
var options = '';
|
||||||
if (typeof values === 'boolean') {
|
if (typeof values === 'boolean') {
|
||||||
values = { 'true': 1, 'false': 0 };
|
values = { true: 1, false: 0 };
|
||||||
}
|
}
|
||||||
for (var k in values) {
|
for (var k in values) {
|
||||||
var isSelected = '';
|
var isSelected = '';
|
||||||
@@ -409,9 +387,9 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
|||||||
createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault) +
|
createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault) +
|
||||||
createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault) +
|
createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault) +
|
||||||
createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault) +
|
createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault) +
|
||||||
createOptionsEl('quality', { '0': 0, '50': 50, '80': 80, '100': 100 }, camQualityDefault) +
|
createOptionsEl('quality', { 0: 0, 50: 50, 80: 80, 100: 100 }, camQualityDefault) +
|
||||||
createOptionsEl('targetWidth', { '50': 50, '200': 200, '800': 800, '2048': 2048 }) +
|
createOptionsEl('targetWidth', { 50: 50, 200: 200, 800: 800, 2048: 2048 }) +
|
||||||
createOptionsEl('targetHeight', { '50': 50, '200': 200, '800': 800, '2048': 2048 }) +
|
createOptionsEl('targetHeight', { 50: 50, 200: 200, 800: 800, 2048: 2048 }) +
|
||||||
createOptionsEl('allowEdit', true, camAllowEditDefault) +
|
createOptionsEl('allowEdit', true, camAllowEditDefault) +
|
||||||
createOptionsEl('correctOrientation', true, camCorrectOrientationDefault) +
|
createOptionsEl('correctOrientation', true, camCorrectOrientationDefault) +
|
||||||
createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault) +
|
createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault) +
|
||||||
@@ -498,10 +476,6 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
|||||||
writeImage();
|
writeImage();
|
||||||
}, 'write');
|
}, 'write');
|
||||||
|
|
||||||
createActionButton('Upload Image', function () {
|
|
||||||
uploadImage();
|
|
||||||
}, 'upload');
|
|
||||||
|
|
||||||
createActionButton('Draw Using Canvas', function () {
|
createActionButton('Draw Using Canvas', function () {
|
||||||
displayImageUsingCanvas();
|
displayImageUsingCanvas();
|
||||||
}, 'draw_canvas');
|
}, 'draw_canvas');
|
||||||
|
|||||||
3
types/index.d.ts
vendored
3
types/index.d.ts
vendored
@@ -51,8 +51,6 @@ interface CameraOptions {
|
|||||||
* Defined in navigator.camera.DestinationType. Default is FILE_URI.
|
* Defined in navigator.camera.DestinationType. Default is FILE_URI.
|
||||||
* DATA_URL : 0, Return image as base64-encoded string
|
* DATA_URL : 0, Return image as base64-encoded string
|
||||||
* FILE_URI : 1, Return image file URI
|
* FILE_URI : 1, Return image file URI
|
||||||
* NATIVE_URI : 2 Return image native URI
|
|
||||||
* (e.g., assets-library:// on iOS or content:// on Android)
|
|
||||||
*/
|
*/
|
||||||
destinationType?: number;
|
destinationType?: number;
|
||||||
/**
|
/**
|
||||||
@@ -149,7 +147,6 @@ declare var Camera: {
|
|||||||
DestinationType: {
|
DestinationType: {
|
||||||
DATA_URL: number;
|
DATA_URL: number;
|
||||||
FILE_URI: number;
|
FILE_URI: number;
|
||||||
NATIVE_URI: number
|
|
||||||
}
|
}
|
||||||
Direction: {
|
Direction: {
|
||||||
BACK: number;
|
BACK: number;
|
||||||
|
|||||||
@@ -26,20 +26,14 @@ module.exports = {
|
|||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
* Defines the output format of `Camera.getPicture` call.
|
* Defines the output format of `Camera.getPicture` call.
|
||||||
* _Note:_ On iOS passing `DestinationType.NATIVE_URI` along with
|
|
||||||
* `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM` will
|
|
||||||
* disable any image modifications (resize, quality change, cropping, etc.) due
|
|
||||||
* to implementation specific.
|
|
||||||
*
|
*
|
||||||
* @enum {number}
|
* @enum {number}
|
||||||
*/
|
*/
|
||||||
DestinationType: {
|
DestinationType: {
|
||||||
/** Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI or NATIVE_URI if possible */
|
/** Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI if possible */
|
||||||
DATA_URL: 0,
|
DATA_URL: 0,
|
||||||
/** Return file uri (content://media/external/images/media/2 for Android) */
|
/** Return file uri (content://media/external/images/media/2 for Android) */
|
||||||
FILE_URI: 1,
|
FILE_URI: 1
|
||||||
/** Return native uri (eg. asset-library://... for iOS) */
|
|
||||||
NATIVE_URI: 2
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* @enum {number}
|
* @enum {number}
|
||||||
@@ -64,9 +58,6 @@ module.exports = {
|
|||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
* Defines the output format of `Camera.getPicture` call.
|
* Defines the output format of `Camera.getPicture` call.
|
||||||
* _Note:_ On iOS passing `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM`
|
|
||||||
* along with `DestinationType.NATIVE_URI` will disable any image modifications (resize, quality
|
|
||||||
* change, cropping, etc.) due to implementation specific.
|
|
||||||
*
|
*
|
||||||
* @enum {number}
|
* @enum {number}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ var CameraPopoverHandle = function () {
|
|||||||
* @param {module:CameraPopoverOptions} popoverOptions
|
* @param {module:CameraPopoverOptions} popoverOptions
|
||||||
*/
|
*/
|
||||||
this.setPosition = function (popoverOptions) {
|
this.setPosition = function (popoverOptions) {
|
||||||
var args = [ popoverOptions ];
|
var args = [popoverOptions];
|
||||||
exec(null, null, 'Camera', 'repositionPopover', args);
|
exec(null, null, 'Camera', 'repositionPopover', args);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user