mirror of
https://github.com/apache/cordova-plugin-camera.git
synced 2026-02-03 00:06:46 +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:
|
||||
- nodejs_version: "10"
|
||||
- nodejs_version: "12"
|
||||
- nodejs_version: "14"
|
||||
|
||||
platform:
|
||||
- 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
|
||||
extends: semistandard
|
||||
rules:
|
||||
indent:
|
||||
- error
|
||||
- 4
|
||||
camelcase: off
|
||||
padded-blocks: off
|
||||
operator-linebreak: off
|
||||
no-throw-literal: off
|
||||
extends: '@cordova/eslint-config/browser'
|
||||
|
||||
overrides:
|
||||
- files: [tests/**/*.js]
|
||||
extends: '@cordova/eslint-config/node-tests'
|
||||
|
||||
11
.travis.yml
11
.travis.yml
@@ -13,17 +13,17 @@ env:
|
||||
global:
|
||||
- SAUCE_USERNAME=snay
|
||||
- TRAVIS_NODE_VERSION=12
|
||||
- ANDROID_API_LEVEL=28
|
||||
- ANDROID_BUILD_TOOLS_VERSION=28.0.3
|
||||
- ANDROID_API_LEVEL=29
|
||||
- ANDROID_BUILD_TOOLS_VERSION=29.0.2
|
||||
|
||||
language: node_js
|
||||
node_js: 12
|
||||
node_js: 14
|
||||
|
||||
# yaml anchor/alias: https://medium.com/@tommyvn/travis-yml-dry-with-anchors-8b6a3ac1b027
|
||||
|
||||
_ios: &_ios
|
||||
os: osx
|
||||
osx_image: xcode10.3
|
||||
osx_image: xcode11.6
|
||||
|
||||
_android: &_android
|
||||
language: android
|
||||
@@ -43,7 +43,8 @@ matrix:
|
||||
include:
|
||||
# additional tests
|
||||
- env: ADDITIONAL_TESTS_DIR=./tests/ios
|
||||
language: objective-c
|
||||
os: osx
|
||||
osx_image: xcode11.5
|
||||
|
||||
# local tests, without saucelabs
|
||||
- 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>
|
||||
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>
|
||||
**Properties**
|
||||
|
||||
| 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) |
|
||||
| NATIVE_URI | <code>number</code> | <code>2</code> | Return native uri (eg. asset-library://... for iOS) |
|
||||
|
||||
<a name="module_Camera.EncodingType"></a>
|
||||
|
||||
@@ -317,9 +312,6 @@ to implementation specific.
|
||||
|
||||
### Camera.PictureSourceType : <code>enum</code>
|
||||
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>
|
||||
**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
|
||||
* 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
|
||||
* or NATIVE_URI instead.
|
||||
* instead.
|
||||
*/
|
||||
navigator.camera.getPicture(onSuccess, onFail, { quality: 25,
|
||||
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.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
|
||||
|
||||
|
||||
@@ -20,18 +20,45 @@
|
||||
-->
|
||||
# Release Notes
|
||||
|
||||
### 4.2.0 (May 07, 2020)
|
||||
* Cache images in device storage, devices have enough space now.
|
||||
* docs(readme): app renamed to Google Photos
|
||||
### 5.0.2 (May 11, 2021)
|
||||
* [GH-728](https://github.com/apache/cordova-plugin-camera/pull/728) plugin release preparation - audit fix
|
||||
* [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
|
||||
* 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
|
||||
* Fix UI API called on a background thread (#550, #530, #447) (#551)
|
||||
* ci: updates Node.js versions (#576)
|
||||
* chore(npm): adds ignore list (#575)
|
||||
* docs(README): remove confusing comment (#513)
|
||||
* docs(README): remove orphan **Windows** phone 7 note (#512)
|
||||
* ImagePicker returning same image (#306)
|
||||
* [GH-551](https://github.com/apache/cordova-plugin-camera/pull/551) Fix UI API called on a background thread
|
||||
* [GH-576](https://github.com/apache/cordova-plugin-camera/pull/576) ci: updates Node.js versions
|
||||
* [GH-575](https://github.com/apache/cordova-plugin-camera/pull/575) chore(npm): adds ignore list
|
||||
* [GH-513](https://github.com/apache/cordova-plugin-camera/pull/513) docs(README): remove confusing comment
|
||||
* [GH-512](https://github.com/apache/cordova-plugin-camera/pull/512) docs(README): remove orphan **Windows** phone 7 note
|
||||
* [GH-306](https://github.com/apache/cordova-plugin-camera/pull/306) ImagePicker returning same image
|
||||
|
||||
### 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))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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/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/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))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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(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(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/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))
|
||||
- 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): [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))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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/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/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)
|
||||
|
||||
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",
|
||||
"version": "4.2.0",
|
||||
"version": "5.0.2",
|
||||
"description": "Cordova Camera Plugin",
|
||||
"types": "./types/index.d.ts",
|
||||
"cordova": {
|
||||
@@ -13,13 +13,8 @@
|
||||
"osx"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/apache/cordova-plugin-camera"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/apache/cordova-plugin-camera/issues"
|
||||
},
|
||||
"repository": "github:apache/cordova-plugin-camera",
|
||||
"bugs": "https://github.com/apache/cordova-plugin-camera/issues",
|
||||
"keywords": [
|
||||
"cordova",
|
||||
"camera",
|
||||
@@ -31,8 +26,8 @@
|
||||
"cordova-osx"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "npm run eslint",
|
||||
"eslint": "node node_modules/eslint/bin/eslint www && node node_modules/eslint/bin/eslint src && node node_modules/eslint/bin/eslint tests"
|
||||
"test": "npm run lint",
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"author": "Apache Software Foundation",
|
||||
"license": "Apache-2.0",
|
||||
@@ -46,17 +41,16 @@
|
||||
"cordova": ">=7.1.0"
|
||||
},
|
||||
"5.0.0": {
|
||||
"cordova-android": ">=9.0.0",
|
||||
"cordova-ios": ">=5.1.0",
|
||||
"cordova": ">=9.0.0"
|
||||
},
|
||||
"6.0.0": {
|
||||
"cordova": ">100"
|
||||
}
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^4.3.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"
|
||||
"@cordova/eslint-config": "^3.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
17
plugin.xml
17
plugin.xml
@@ -21,7 +21,7 @@
|
||||
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
id="cordova-plugin-camera"
|
||||
version="4.2.0">
|
||||
version="5.0.2">
|
||||
<name>Camera</name>
|
||||
<description>Cordova Camera Plugin</description>
|
||||
<license>Apache 2.0</license>
|
||||
@@ -30,8 +30,9 @@
|
||||
<issue>https://github.com/apache/cordova-plugin-camera/issues</issue>
|
||||
|
||||
<engines>
|
||||
<engine name="cordova" version=">=7.1.0"/>
|
||||
<engine name="cordova-android" version=">=6.3.0" />
|
||||
<engine name="cordova" version=">=9.0.0"/>
|
||||
<engine name="cordova-android" version=">=9.0.0" />
|
||||
<engine name="cordova-ios" version=">=5.1.0" />
|
||||
</engines>
|
||||
|
||||
<js-module src="www/CameraConstants.js" name="Camera">
|
||||
@@ -59,7 +60,7 @@
|
||||
<config-file target="AndroidManifest.xml" parent="application">
|
||||
<provider
|
||||
android:name="org.apache.cordova.camera.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:authorities="${applicationId}.cordova.plugin.camera.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true" >
|
||||
<meta-data
|
||||
@@ -69,10 +70,10 @@
|
||||
</config-file>
|
||||
|
||||
<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/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/GalleryPathVO.java" target-dir="src/org/apache/cordova/camera" />
|
||||
<source-file src="src/android/xml/camera_provider_paths.xml" target-dir="res/xml" />
|
||||
|
||||
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
||||
@@ -151,12 +152,12 @@
|
||||
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
||||
<clobbers target="CameraPopoverHandle" />
|
||||
</js-module>
|
||||
|
||||
|
||||
<header-file src="src/osx/CDVCamera.h" />
|
||||
<source-file src="src/osx/CDVCamera.m" />
|
||||
|
||||
|
||||
<framework src="Quartz.framework" />
|
||||
<framework src="AppKit.framework" />
|
||||
</platform>
|
||||
|
||||
|
||||
</plugin>
|
||||
|
||||
@@ -21,6 +21,7 @@ package org.apache.cordova.camera;
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -34,6 +35,7 @@ import android.media.ExifInterface;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.provider.MediaStore;
|
||||
@@ -51,7 +53,6 @@ import org.json.JSONException;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
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 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 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 CROPPED_URI_KEY = "croppedUri";
|
||||
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";
|
||||
|
||||
@@ -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 targetWidth; // desired width 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 mediaType; // What type of media to retrieve
|
||||
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 Uri scanMe; // Uri of image to be added to content store
|
||||
private Uri croppedUri;
|
||||
private String croppedFilePath;
|
||||
private ExifHelper exifData; // Exif data from source
|
||||
private String applicationId;
|
||||
|
||||
@@ -290,10 +293,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
|
||||
// Specify file so that large image is captured and returned
|
||||
File photo = createCaptureFile(encodingType);
|
||||
this.imageUri = new CordovaUri(FileProvider.getUriForFile(cordova.getActivity(),
|
||||
applicationId + ".provider",
|
||||
photo));
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri.getCorrectUri());
|
||||
this.imageFilePath = photo.getAbsolutePath();
|
||||
this.imageUri = FileProvider.getUriForFile(cordova.getActivity(),
|
||||
applicationId + ".cordova.plugin.camera.provider",
|
||||
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
|
||||
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
|
||||
@@ -360,6 +364,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
Intent intent = new Intent();
|
||||
String title = GET_PICTURE;
|
||||
croppedUri = null;
|
||||
croppedFilePath = null;
|
||||
if (this.mediaType == PICTURE) {
|
||||
intent.setType("image/*");
|
||||
if (this.allowEdit) {
|
||||
@@ -375,8 +380,9 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
intent.putExtra("aspectX", 1);
|
||||
intent.putExtra("aspectY", 1);
|
||||
}
|
||||
File photo = createCaptureFile(JPEG);
|
||||
croppedUri = Uri.fromFile(photo);
|
||||
File croppedFile = createCaptureFile(JPEG);
|
||||
croppedFilePath = croppedFile.getAbsolutePath();
|
||||
croppedUri = Uri.fromFile(croppedFile);
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, croppedUri);
|
||||
} else {
|
||||
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
|
||||
*
|
||||
* @param picUri
|
||||
*/
|
||||
private void performCrop(Uri picUri, int destType, Intent cameraIntent) {
|
||||
try {
|
||||
Intent cropIntent = new Intent("com.android.camera.action.CROP");
|
||||
// indicate image type and Uri
|
||||
cropIntent.setDataAndType(picUri, "image/*");
|
||||
// set crop properties
|
||||
cropIntent.putExtra("crop", "true");
|
||||
/**
|
||||
* Brings up the UI to perform crop on passed image URI
|
||||
*
|
||||
* @param picUri
|
||||
*/
|
||||
private void performCrop(Uri picUri, int destType, Intent cameraIntent) {
|
||||
try {
|
||||
Intent cropIntent = new Intent("com.android.camera.action.CROP");
|
||||
// indicate image type and Uri
|
||||
cropIntent.setDataAndType(picUri, "image/*");
|
||||
// set crop properties
|
||||
cropIntent.putExtra("crop", "true");
|
||||
|
||||
|
||||
// indicate output X and Y
|
||||
if (targetWidth > 0) {
|
||||
cropIntent.putExtra("outputX", targetWidth);
|
||||
// indicate output X and Y
|
||||
if (targetWidth > 0) {
|
||||
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.
|
||||
@@ -466,8 +472,8 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
ExifHelper exif = new ExifHelper();
|
||||
|
||||
String sourcePath = (this.allowEdit && this.croppedUri != null) ?
|
||||
FileHelper.stripFileProtocol(this.croppedUri.toString()) :
|
||||
this.imageUri.getFilePath();
|
||||
this.croppedFilePath :
|
||||
this.imageFilePath;
|
||||
|
||||
|
||||
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
|
||||
// directory
|
||||
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) {
|
||||
writeUncompressedImage(croppedUri, galleryUri);
|
||||
} else {
|
||||
Uri imageUri = this.imageUri.getFileUri();
|
||||
writeUncompressedImage(imageUri, galleryUri);
|
||||
if (Build.VERSION.SDK_INT <= 28) { // Between LOLLIPOP_MR1 and P, can be changed later to the constant Build.VERSION_CODES.P
|
||||
writeTakenPictureToGalleryLowerThanAndroidQ(galleryUri);
|
||||
} else { // Android Q or higher
|
||||
writeTakenPictureToGalleryStartingFromAndroidQ(galleryPathVO);
|
||||
}
|
||||
}
|
||||
|
||||
refreshGallery(galleryUri);
|
||||
}
|
||||
|
||||
// If sending base64 image back
|
||||
@@ -526,7 +534,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
}
|
||||
|
||||
// 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 (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 &&
|
||||
!this.correctOrientation) {
|
||||
@@ -539,10 +547,10 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
|
||||
|
||||
if (this.allowEdit && this.croppedUri != null) {
|
||||
Uri croppedUri = Uri.fromFile(new File(getFileNameFromUri(this.croppedUri)));
|
||||
Uri croppedUri = Uri.parse(croppedFilePath);
|
||||
writeUncompressedImage(croppedUri, uri);
|
||||
} else {
|
||||
Uri imageUri = this.imageUri.getFileUri();
|
||||
Uri imageUri = this.imageUri;
|
||||
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
|
||||
OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri);
|
||||
CompressFormat compressFormat = encodingType == JPEG ?
|
||||
CompressFormat.JPEG :
|
||||
CompressFormat.PNG;
|
||||
CompressFormat compressFormat = getCompressFormatForEncodingType(encodingType);
|
||||
|
||||
bitmap.compress(compressFormat, this.mQuality, os);
|
||||
os.close();
|
||||
@@ -588,22 +594,45 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
this.cleanup(FILE_URI, this.imageUri.getFileUri(), galleryUri, bitmap);
|
||||
this.cleanup(FILE_URI, this.imageUri, galleryUri, bitmap);
|
||||
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 imageFileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? JPEG_EXTENSION : PNG_EXTENSION);
|
||||
File storageDir = Environment.getExternalStoragePublicDirectory(
|
||||
Environment.DIRECTORY_PICTURES);
|
||||
storageDir.mkdirs();
|
||||
String galleryPath = storageDir.getAbsolutePath() + "/" + imageFileName;
|
||||
return galleryPath;
|
||||
return new GalleryPathVO(storageDir.getAbsolutePath(), imageFileName);
|
||||
}
|
||||
|
||||
private void refreshGallery(Uri contentUri) {
|
||||
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);
|
||||
this.cordova.getActivity().sendBroadcast(mediaScanIntent);
|
||||
}
|
||||
@@ -635,9 +664,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
String modifiedPath = getTempDirectoryPath() + "/" + fileName;
|
||||
|
||||
OutputStream os = new FileOutputStream(modifiedPath);
|
||||
CompressFormat compressFormat = this.encodingType == JPEG ?
|
||||
CompressFormat.JPEG :
|
||||
CompressFormat.PNG;
|
||||
CompressFormat compressFormat = getCompressFormatForEncodingType(this.encodingType);
|
||||
|
||||
bitmap.compress(compressFormat, this.mQuality, os);
|
||||
os.close();
|
||||
@@ -674,74 +701,80 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
return;
|
||||
}
|
||||
}
|
||||
int rotate = 0;
|
||||
|
||||
String fileLocation = FileHelper.getRealPath(uri, this.cordova);
|
||||
LOG.d(LOG_TAG, "File location is: " + fileLocation);
|
||||
|
||||
String uriString = uri.toString();
|
||||
String finalLocation = fileLocation != null ? fileLocation : uriString;
|
||||
String mimeType = FileHelper.getMimeType(uriString, this.cordova);
|
||||
|
||||
// If you ask for video or the selected file doesn't have JPEG or PNG mime type
|
||||
// there will be no attempt to resize any returned data
|
||||
if (this.mediaType == VIDEO || !(JPEG_MIME_TYPE.equalsIgnoreCase(mimeType) || PNG_MIME_TYPE.equalsIgnoreCase(mimeType))) {
|
||||
this.callbackContext.success(fileLocation);
|
||||
}
|
||||
else {
|
||||
if (finalLocation == null) {
|
||||
this.failPicture("Error retrieving result.");
|
||||
} else {
|
||||
|
||||
// This is a special case to just return the path as no scaling,
|
||||
// rotating, nor compressing needs to be done
|
||||
if (this.targetHeight == -1 && this.targetWidth == -1 &&
|
||||
(destType == FILE_URI || destType == NATIVE_URI) && !this.correctOrientation &&
|
||||
mimeType != null && mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType)))
|
||||
{
|
||||
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 you ask for video or the selected file doesn't have JPEG or PNG mime type
|
||||
// there will be no attempt to resize any returned data
|
||||
if (this.mediaType == VIDEO || !(JPEG_MIME_TYPE.equalsIgnoreCase(mimeType) || PNG_MIME_TYPE.equalsIgnoreCase(mimeType))) {
|
||||
this.callbackContext.success(finalLocation);
|
||||
}
|
||||
else {
|
||||
|
||||
// If sending base64 image back
|
||||
if (destType == DATA_URL) {
|
||||
this.processPicture(bitmap, this.encodingType);
|
||||
}
|
||||
|
||||
// If sending filename back
|
||||
else if (destType == FILE_URI || destType == NATIVE_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(fileLocation);
|
||||
// This is a special case to just return the path as no scaling,
|
||||
// rotating, nor compressing needs to be done
|
||||
if (this.targetHeight == -1 && this.targetWidth == -1 &&
|
||||
destType == FILE_URI && !this.correctOrientation &&
|
||||
mimeType != null && mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType)))
|
||||
{
|
||||
this.callbackContext.success(finalLocation);
|
||||
} 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
|
||||
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 {
|
||||
if (this.allowEdit) {
|
||||
Uri tmpFile = FileProvider.getUriForFile(cordova.getActivity(),
|
||||
applicationId + ".provider",
|
||||
applicationId + ".cordova.plugin.camera.provider",
|
||||
createCaptureFile(this.encodingType));
|
||||
performCrop(tmpFile, destType, intent);
|
||||
} else {
|
||||
@@ -888,34 +921,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
private void writeUncompressedImage(Uri src, Uri dest) throws FileNotFoundException,
|
||||
IOException {
|
||||
|
||||
FileInputStream fis = new FileInputStream(FileHelper.stripFileProtocol(src.toString()));
|
||||
InputStream fis = FileHelper.getInputStreamFromUriString(src.toString(), cordova);
|
||||
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
|
||||
*
|
||||
@@ -1246,9 +1256,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
*/
|
||||
public void processPicture(Bitmap bitmap, int encodingType) {
|
||||
ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream();
|
||||
CompressFormat compressFormat = encodingType == JPEG ?
|
||||
CompressFormat.JPEG :
|
||||
CompressFormat.PNG;
|
||||
CompressFormat compressFormat = getCompressFormatForEncodingType(encodingType);
|
||||
|
||||
try {
|
||||
if (bitmap.compress(compressFormat, mQuality, jpeg_data)) {
|
||||
@@ -1336,11 +1344,15 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
state.putBoolean("saveToPhotoAlbum", this.saveToPhotoAlbum);
|
||||
|
||||
if (this.croppedUri != null) {
|
||||
state.putString(CROPPED_URI_KEY, this.croppedUri.toString());
|
||||
state.putString(CROPPED_URI_KEY, this.croppedFilePath);
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -1365,28 +1377,13 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
||||
|
||||
if (state.containsKey(IMAGE_URI_KEY)) {
|
||||
//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 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")
|
||||
public static String getRealPath(Uri uri, CordovaInterface cordova) {
|
||||
String realPath = null;
|
||||
|
||||
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;
|
||||
return FileHelper.getRealPathFromURI(cordova.getActivity(), uri);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,11 +66,9 @@ public class FileHelper {
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public static String getRealPathFromURI_API11_And_Above(final Context context, final Uri uri) {
|
||||
|
||||
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
|
||||
public static String getRealPathFromURI(final Context context, final Uri uri) {
|
||||
// DocumentProvider
|
||||
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
|
||||
if (DocumentsContract.isDocumentUri(context, uri)) {
|
||||
|
||||
// ExternalStorageProvider
|
||||
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">
|
||||
<external-path name="external_files" path="."/>
|
||||
<cache-path name="cache_files" path="." />
|
||||
</paths>
|
||||
@@ -112,7 +112,7 @@ function capture (success, errorCallback, opts) {
|
||||
};
|
||||
|
||||
if (navigator.getUserMedia) {
|
||||
navigator.getUserMedia({video: true, audio: false}, successCallback, errorCallback);
|
||||
navigator.getUserMedia({ video: true, audio: false }, successCallback, errorCallback);
|
||||
} else {
|
||||
alert('Browser does not support camera :(');
|
||||
}
|
||||
|
||||
@@ -24,8 +24,7 @@
|
||||
|
||||
enum CDVDestinationType {
|
||||
DestinationTypeDataUrl = 0,
|
||||
DestinationTypeFileUri,
|
||||
DestinationTypeNativeUri
|
||||
DestinationTypeFileUri
|
||||
};
|
||||
typedef NSUInteger CDVDestinationType;
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ static NSString* toBase64(NSData* data) {
|
||||
[weakSelf sendNoPermissionResult:command.callbackId];
|
||||
}]];
|
||||
[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.viewController presentViewController:alertController animated:YES completion:nil];
|
||||
@@ -383,6 +383,7 @@ static NSString* toBase64(NSData* data) {
|
||||
}
|
||||
[[self locationManager] startUpdatingLocation];
|
||||
}
|
||||
data = nil;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -396,15 +397,10 @@ static NSString* toBase64(NSData* data) {
|
||||
- (NSString*)tempFilePath:(NSString*)extension
|
||||
{
|
||||
NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
|
||||
NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by Apple (vs [NSFileManager defaultManager]) to be threadsafe
|
||||
NSString* filePath;
|
||||
|
||||
// unique file name
|
||||
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
|
||||
NSNumber *timeStampObj = [NSNumber numberWithDouble: timeStamp];
|
||||
do {
|
||||
filePath = [NSString stringWithFormat:@"%@/%@%ld.%@", docsPath, CDV_PHOTO_PREFIX, [timeStampObj longValue], extension];
|
||||
} while ([fileMgr fileExistsAtPath:filePath]);
|
||||
NSString* filePath = [NSString stringWithFormat:@"%@/%@%ld.%@", docsPath, CDV_PHOTO_PREFIX, [timeStampObj longValue], extension];
|
||||
|
||||
return filePath;
|
||||
}
|
||||
@@ -444,33 +440,16 @@ static NSString* toBase64(NSData* data) {
|
||||
UIImage* image = nil;
|
||||
|
||||
switch (options.destinationType) {
|
||||
case DestinationTypeNativeUri:
|
||||
case DestinationTypeDataUrl:
|
||||
{
|
||||
NSURL* url = [info objectForKey:UIImagePickerControllerReferenceURL];
|
||||
saveToPhotoAlbum = NO;
|
||||
// If, for example, we use sourceType = Camera, URL might be nil because image is stored in memory.
|
||||
// In this case we must save image to device before obtaining an URI.
|
||||
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];
|
||||
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;
|
||||
case DestinationTypeFileUri:
|
||||
default: // DestinationTypeFileUri
|
||||
{
|
||||
image = [self retrieveImage:info options:options];
|
||||
NSData* data = [self processImage:image info:info options:options];
|
||||
@@ -489,22 +468,10 @@ static NSString* toBase64(NSData* data) {
|
||||
}
|
||||
}
|
||||
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) {
|
||||
ALAssetsLibrary* library = [ALAssetsLibrary new];
|
||||
[library writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)(image.imageOrientation) completionBlock:nil];
|
||||
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
|
||||
}
|
||||
|
||||
completion(result);
|
||||
@@ -580,10 +547,8 @@ static NSString* toBase64(NSData* data) {
|
||||
|
||||
dispatch_block_t invoke = ^ (void) {
|
||||
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"];
|
||||
} else if (picker.sourceType != UIImagePickerControllerSourceTypeCamera && ! IsAtLeastiOSVersion(@"11.0") && [ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusAuthorized) {
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to assets"];
|
||||
} else {
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No Image Selected"];
|
||||
}
|
||||
@@ -686,19 +651,26 @@ static NSString* toBase64(NSData* data) {
|
||||
CDVPluginResult* result = nil;
|
||||
|
||||
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);
|
||||
|
||||
CGImageDestinationRef destinationImage = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)self.data, sourceType, 1, NULL);
|
||||
CGImageDestinationAddImageFromSource(destinationImage, sourceImage, 0, (__bridge CFDictionaryRef)self.metadata);
|
||||
CGImageDestinationFinalize(destinationImage);
|
||||
|
||||
dataCopy = nil;
|
||||
CFRelease(sourceImage);
|
||||
CFRelease(destinationImage);
|
||||
}
|
||||
|
||||
switch (options.destinationType) {
|
||||
case DestinationTypeFileUri:
|
||||
case DestinationTypeDataUrl:
|
||||
{
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:toBase64(self.data)];
|
||||
}
|
||||
break;
|
||||
default: // DestinationTypeFileUri
|
||||
{
|
||||
NSError* err = nil;
|
||||
NSString* extension = self.pickerController.pictureOptions.encodingType == EncodingTypePNG ? @"png":@"jpg";
|
||||
@@ -713,14 +685,6 @@ static NSString* toBase64(NSData* data) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DestinationTypeDataUrl:
|
||||
{
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:toBase64(self.data)];
|
||||
}
|
||||
break;
|
||||
case DestinationTypeNativeUri:
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
if (result) {
|
||||
@@ -733,8 +697,7 @@ static NSString* toBase64(NSData* data) {
|
||||
self.metadata = nil;
|
||||
|
||||
if (options.saveToPhotoAlbum) {
|
||||
ALAssetsLibrary *library = [ALAssetsLibrary new];
|
||||
[library writeImageDataToSavedPhotosAlbum:self.data metadata:self.metadata completionBlock:nil];
|
||||
UIImageWriteToSavedPhotosAlbum([[UIImage alloc] initWithData:self.data], nil, nil, nil);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@
|
||||
|
||||
enum CDVDestinationType {
|
||||
DestinationTypeDataUrl = 0,
|
||||
DestinationTypeFileUri,
|
||||
DestinationTypeNativeUri
|
||||
DestinationTypeFileUri
|
||||
};
|
||||
typedef NSUInteger CDVDestinationType;
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ static NSMutableArray *cleanUpFiles;
|
||||
|
||||
/*!
|
||||
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 {
|
||||
NSString *protocol = (pictureOptions.destinationType == DestinationTypeFileUri) ? @"file://" : @"";
|
||||
|
||||
@@ -190,17 +190,13 @@ function takePictureFromFileWP (successCallback, errorCallback, args) {
|
||||
webUIApp.removeEventListener('activated', filePickerActivationHandler);
|
||||
return;
|
||||
}
|
||||
if (destinationType === Camera.DestinationType.FILE_URI || destinationType === Camera.DestinationType.NATIVE_URI) {
|
||||
if (destinationType === Camera.DestinationType.FILE_URI) {
|
||||
if (targetHeight > 0 && targetWidth > 0) {
|
||||
resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType);
|
||||
} else {
|
||||
var storageFolder = getAppData().localFolder;
|
||||
file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).done(function (storageFile) {
|
||||
if (destinationType === Camera.DestinationType.NATIVE_URI) {
|
||||
successCallback('ms-appdata:///local/' + storageFile.name);
|
||||
} else {
|
||||
successCallback(URL.createObjectURL(storageFile));
|
||||
}
|
||||
successCallback(URL.createObjectURL(storageFile));
|
||||
}, function () {
|
||||
errorCallback("Can't access localStorage folder.");
|
||||
});
|
||||
@@ -259,17 +255,13 @@ function takePictureFromFileWindows (successCallback, errorCallback, args) {
|
||||
errorCallback("User didn't choose a file.");
|
||||
return;
|
||||
}
|
||||
if (destinationType === Camera.DestinationType.FILE_URI || destinationType === Camera.DestinationType.NATIVE_URI) {
|
||||
if (destinationType === Camera.DestinationType.FILE_URI) {
|
||||
if (targetHeight > 0 && targetWidth > 0) {
|
||||
resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType);
|
||||
} else {
|
||||
var storageFolder = getAppData().localFolder;
|
||||
file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).done(function (storageFile) {
|
||||
if (destinationType === Camera.DestinationType.NATIVE_URI) {
|
||||
successCallback('ms-appdata:///local/' + storageFile.name);
|
||||
} else {
|
||||
successCallback(URL.createObjectURL(storageFile));
|
||||
}
|
||||
successCallback(URL.createObjectURL(storageFile));
|
||||
}, function () {
|
||||
errorCallback("Can't access localStorage folder.");
|
||||
});
|
||||
@@ -374,7 +366,6 @@ function takePictureFromCameraWP (successCallback, errorCallback, args) {
|
||||
|
||||
return capture.initializeAsync(captureSettings);
|
||||
}).then(function () {
|
||||
|
||||
// create focus control if available
|
||||
var VideoDeviceController = capture.videoDeviceController;
|
||||
var FocusControl = VideoDeviceController.focusControl;
|
||||
@@ -477,7 +468,6 @@ function takePictureFromCameraWP (successCallback, errorCallback, args) {
|
||||
}
|
||||
|
||||
function captureAction () {
|
||||
|
||||
var encodingProperties;
|
||||
var fileName;
|
||||
var tempFolder = getAppData().temporaryFolder;
|
||||
@@ -715,7 +705,7 @@ function takePictureFromCameraWindows (successCallback, errorCallback, args) {
|
||||
|
||||
if (targetWidth === -1 && targetHeight === -1) {
|
||||
maxRes = UIMaxRes.highestAvailable;
|
||||
// Temp fix for CB-10539
|
||||
// Temp fix for CB-10539
|
||||
/* else if (totalPixels <= 320 * 240) {
|
||||
maxRes = UIMaxRes.verySmallQvga;
|
||||
} */
|
||||
@@ -781,7 +771,7 @@ function takePictureFromCameraWindows (successCallback, errorCallback, args) {
|
||||
function savePhoto (picture, options, successCallback, errorCallback) {
|
||||
// success callback for capture operation
|
||||
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) {
|
||||
resizeImage(successCallback, errorCallback, picture, options.targetWidth, options.targetHeight, options.encodingType);
|
||||
} else {
|
||||
@@ -812,7 +802,6 @@ function savePhoto (picture, options, successCallback, errorCallback) {
|
||||
|
||||
if (!options.saveToPhotoAlbum) {
|
||||
success(picture);
|
||||
|
||||
} else {
|
||||
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
|
||||
var saveFile = function (file) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cordova-plugin-camera-tests",
|
||||
"version": "4.2.0",
|
||||
"version": "5.0.2",
|
||||
"description": "",
|
||||
"cordova": {
|
||||
"id": "cordova-plugin-camera-tests",
|
||||
|
||||
@@ -22,12 +22,10 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:rim="http://www.blackberry.com/ns/widgets"
|
||||
id="cordova-plugin-camera-tests"
|
||||
version="4.2.0">
|
||||
version="5.0.2">
|
||||
<name>Cordova Camera Plugin Tests</name>
|
||||
<license>Apache 2.0</license>
|
||||
|
||||
<dependency id="cordova-plugin-file-transfer" />
|
||||
|
||||
<js-module src="tests.js" name="tests">
|
||||
</js-module>
|
||||
</plugin>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* globals Camera, resolveLocalFileSystemURL, FileEntry, CameraPopoverOptions, FileTransfer, FileUploadOptions, LocalFileSystem, MSApp */
|
||||
/* globals Camera, resolveLocalFileSystemURL, FileEntry, CameraPopoverOptions, LocalFileSystem, MSApp */
|
||||
/* eslint-env jasmine */
|
||||
|
||||
exports.defineAutoTests = function () {
|
||||
@@ -42,10 +42,8 @@ exports.defineAutoTests = function () {
|
||||
it('camera.spec.2 should contain three DestinationType constants', function () {
|
||||
expect(Camera.DestinationType.DATA_URL).toBe(0);
|
||||
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.FILE_URI).toBe(1);
|
||||
expect(navigator.camera.DestinationType.NATIVE_URI).toBe(2);
|
||||
});
|
||||
|
||||
it('camera.spec.3 should contain two EncodingType constants', function () {
|
||||
@@ -140,7 +138,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
||||
function getPictureWin (data) {
|
||||
setPicture(data);
|
||||
// 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) {
|
||||
fileEntry = e;
|
||||
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) {
|
||||
return function () {
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
function removeImage () {
|
||||
@@ -378,7 +356,7 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
||||
|
||||
var options = '';
|
||||
if (typeof values === 'boolean') {
|
||||
values = { 'true': 1, 'false': 0 };
|
||||
values = { true: 1, false: 0 };
|
||||
}
|
||||
for (var k in values) {
|
||||
var isSelected = '';
|
||||
@@ -409,9 +387,9 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
||||
createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault) +
|
||||
createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault) +
|
||||
createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault) +
|
||||
createOptionsEl('quality', { '0': 0, '50': 50, '80': 80, '100': 100 }, camQualityDefault) +
|
||||
createOptionsEl('targetWidth', { '50': 50, '200': 200, '800': 800, '2048': 2048 }) +
|
||||
createOptionsEl('targetHeight', { '50': 50, '200': 200, '800': 800, '2048': 2048 }) +
|
||||
createOptionsEl('quality', { 0: 0, 50: 50, 80: 80, 100: 100 }, camQualityDefault) +
|
||||
createOptionsEl('targetWidth', { 50: 50, 200: 200, 800: 800, 2048: 2048 }) +
|
||||
createOptionsEl('targetHeight', { 50: 50, 200: 200, 800: 800, 2048: 2048 }) +
|
||||
createOptionsEl('allowEdit', true, camAllowEditDefault) +
|
||||
createOptionsEl('correctOrientation', true, camCorrectOrientationDefault) +
|
||||
createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault) +
|
||||
@@ -498,10 +476,6 @@ exports.defineManualTests = function (contentEl, createActionButton) {
|
||||
writeImage();
|
||||
}, 'write');
|
||||
|
||||
createActionButton('Upload Image', function () {
|
||||
uploadImage();
|
||||
}, 'upload');
|
||||
|
||||
createActionButton('Draw Using Canvas', function () {
|
||||
displayImageUsingCanvas();
|
||||
}, '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.
|
||||
* DATA_URL : 0, Return image as base64-encoded string
|
||||
* 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;
|
||||
/**
|
||||
@@ -149,7 +147,6 @@ declare var Camera: {
|
||||
DestinationType: {
|
||||
DATA_URL: number;
|
||||
FILE_URI: number;
|
||||
NATIVE_URI: number
|
||||
}
|
||||
Direction: {
|
||||
BACK: number;
|
||||
|
||||
@@ -26,20 +26,14 @@ module.exports = {
|
||||
/**
|
||||
* @description
|
||||
* 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}
|
||||
*/
|
||||
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,
|
||||
/** Return file uri (content://media/external/images/media/2 for Android) */
|
||||
FILE_URI: 1,
|
||||
/** Return native uri (eg. asset-library://... for iOS) */
|
||||
NATIVE_URI: 2
|
||||
FILE_URI: 1
|
||||
},
|
||||
/**
|
||||
* @enum {number}
|
||||
@@ -64,9 +58,6 @@ module.exports = {
|
||||
/**
|
||||
* @description
|
||||
* 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}
|
||||
*/
|
||||
|
||||
@@ -58,7 +58,7 @@ var CameraPopoverHandle = function () {
|
||||
* @param {module:CameraPopoverOptions} popoverOptions
|
||||
*/
|
||||
this.setPosition = function (popoverOptions) {
|
||||
var args = [ popoverOptions ];
|
||||
var args = [popoverOptions];
|
||||
exec(null, null, 'Camera', 'repositionPopover', args);
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user