Compare commits

...

65 Commits
4.1.0 ... 6.0.0

Author SHA1 Message Date
Erisu
869f02da1a Updated version and RELEASENOTES.md for release 6.0.0 (camera-v6.0.0) 2021-08-19 17:14:44 +09:00
Dave Alden
e9db20e381 fix(android): return exception message (where it exists) (#687)
Co-authored-by: エリス <erisu@users.noreply.github.com>
Co-authored-by: jcesarmobile <jcesarmobile@gmail.com>
2021-08-11 16:56:42 +09:00
Francis
c7971d9f63 fix(android): file path correction if Uri authority is FileProvider (#585)
Co-authored-by: Tim Brust <ratchet.player@gmx.de>
Co-authored-by: Francis Monier <contactpro@francismonier.com>
Co-authored-by: Norman Breau <norman@normanbreau.com>
2021-08-11 16:34:20 +09:00
Niklas Merz
3112e5fb15 chore: add release notify action (#654)
Co-authored-by: Erisu <ellis.bryan@gmail.com>
2021-08-11 16:04:14 +09:00
Jesse MacFadyen
c56a255fe8 ci(gh-action): added workflow to run tests (#745)
Co-authored-by: Erisu <ellis.bryan@gmail.com>
2021-08-11 16:03:34 +09:00
エリス
0227cdcf14 feat(android)!: support AndroidX (#751)
* feat: migrate FileProvider to androidx
* feat: add androidx.core:core with variable override ANDROIDX_CORE_VERSION
2021-08-09 23:09:29 +09:00
Pieter Van Poyer
75bf807261 Bugfix issue 711 heic format (#731)
* Android - issue/711 - support .heic format
2021-08-09 15:36:58 +02:00
エリス
abfbbd35d5 fix(android): supports sdk-30 package visibility (#684) 2021-08-09 20:57:12 +09:00
エリス
59cf76d1da feat: bump cordova-android requirements for 10.x (#750) 2021-08-09 20:56:15 +09:00
エリス
4ee90a84f3 feat: bump plugin version for next major (#749)
Co-authored-by: Niklas Merz <nmerz@gedys-intraware.de>
2021-08-09 20:52:50 +09:00
Niklas Merz
5587bec320 Bump 5.0.4-dev 2021-08-09 10:53:00 +02:00
Erisu
d523142cf2 Updated version and RELEASENOTES.md for release 5.0.3 (camera-v5.0.3) 2021-08-04 13:16:27 +09:00
エリス
0f6435ec73 chore: rebuilt package-lock.json (#754) 2021-08-04 13:06:29 +09:00
エリス
e81e02b21f fix: incorrect version in package-lock (#748) 2021-07-28 14:31:19 +09:00
エリス
1e20a9bd07 chore: set the 5.x versions locked to cordova-android <10.0.0 (#747) 2021-07-28 14:30:17 +09:00
Niklas Merz
d356030070 chore(asf): Update GitHub repo metadata (#729) 2021-06-28 11:16:24 +02:00
PVPoyer
7bc311fba9 Incremented plugin version. (cordova-plugin-camera20210511) 2021-05-11 22:45:53 +02:00
PVPoyer
e419a74546 Updated version and RELEASENOTES.md for release 5.0.2 (cordova-plugin-camera20210511) 2021-05-11 22:12:25 +02:00
Pieter Van Poyer
9a47f5c791 Merge pull request #728 from PieterVanPoyer/tasks/v5.0.2-audit-fix
chore(npm): fix npm audit issues automatically
2021-05-11 21:51:53 +02:00
PVPoyer
66d3f03270 plugin release preparation - audit fix 2021-05-11 21:39:28 +02:00
Pieter Van Poyer
731c10f5b2 Merge branch 'apache:master' into master 2021-05-11 21:32:47 +02:00
Pieter Van Poyer
f704689200 Bugfix issue 665 (#700)
* GH-665 - store the imageFilePath when the app is paused (onSaveInstance) and restore it back.

* Update src/android/CameraLauncher.java whitespace layout

Co-authored-by: Tim Brust <github@timbrust.de>

Co-authored-by: Tim Brust <github@timbrust.de>
2021-02-02 14:43:26 -04:00
Pieter Van Poyer
2bad1fd81c Merge pull request #1 from apache/master
make even
2021-01-08 17:14:07 +01:00
エリス
b43c78b419 ci: add node-14.x to workflow (#691) 2020-11-28 17:12:32 +09:00
Erisu
db2ffedecc Increment package version to 5.0.2-dev 2020-11-09 18:15:06 +09:00
Erisu
0d13b71d33 Updated version and RELEASENOTES.md for release 5.0.1 (camera-20201104) 2020-11-04 10:24:25 +09:00
エリス
8975171d7a chore(android): add missing apache license header (#686) 2020-11-04 10:12:19 +09:00
jcesarmobile
2d1ee66a2b fix(ios): correctly append exif on iOS 14 (#685) 2020-10-28 18:47:10 +01:00
Pieter Van Poyer
ebe0517a24 Bugfix issue 341 save to photo gallery - Fixes #341, fixes #577 (#669)
* GH-341 - GH-577 Fixed the Save Photo To Album starting from camera - Android

- saveToPhotoAlbum feature fixed by taken into count content - uri. (writeUncompressedImage method) ( see: https://github.com/apache/cordova-plugin-camera/issues/611#issuecomment-700273405 )
- make saveToPhotoAlbum future proof by using the MediaStore to insert the taken image
- made a method to calculate the compressFormat based on the encodingType (JPEG or PNG)
- layout of the performCrop method is adjusted
- removed unused rotate variable inside processResultFromGallery method

* Add extra VO class to the plugin.xml

* added package declaration to new VO

* GH-341 - GH-577 https://github.com/apache/cordova-plugin-camera/pull/669#discussion_r504632953 listen to review
2020-10-16 23:48:22 -03:00
Norman Breau
43d6591d9e Revert "fix(android): Declare CAMERA permission" (#677)
This reverts commit 140e8861e3.
2020-10-14 21:51:20 -03:00
jcesarmobile
64d8c5108a chore: Fix JIRA links in RELEASENOTES.md (#672) 2020-10-07 15:48:47 +02:00
Norman Breau
11769962bd Merge pull request #670 from breautek/fix/camera-perms
fix(android): Declare CAMERA permission
2020-10-01 07:56:42 -03:00
Norman Breau
140e8861e3 fix(android): Declare CAMERA permission 2020-09-30 22:07:19 -03:00
jcesarmobile
5ae56cf8f0 chore: Update RELEASENOTES (#664) 2020-09-24 17:00:05 +02:00
Erisu
e2e04ba3d8 Increment package version to 5.0.1-dev 2020-09-18 12:06:07 +09:00
Erisu
4584f15d9f Updated version and RELEASENOTES.md for release 5.0.0 (camera-20200914) 2020-09-14 12:19:36 +09:00
エリス
0111e93448 ci(travis): update osx xcode image (#648)
* ci(travis): update osx xcode image
* ci: use travis's latest supported osx_image xcode11.6
2020-09-03 19:35:43 +09:00
jcesarmobile
0333d001c7 breaking: remove NATIVE_URI DestinationType (#637) 2020-08-07 14:38:05 +02:00
エリス
45496213b3 breaking: bump project requirements (#628) 2020-07-28 20:25:48 +09:00
エリス
3f42591363 chore: remove deprecated file transfer plugin (#634) 2020-07-23 20:16:36 +09:00
jcesarmobile
e2ecd7fe91 fix(android): return error if file url is null (#632) 2020-07-23 12:11:55 +02:00
Loïc Le Malliaud
eb7fc333ee fix(android): use provider prefix to avoid conflicts other plugin providers (#510)
Co-authored-by: jcesarmobile <jcesarmobile@gmail.com>
2020-07-16 13:08:40 +02:00
jcesarmobile
fd155d9705 breaking(android): stop using CordovaUri helper class (#617) 2020-07-14 16:26:09 +02:00
エリス
2bf5b9347e chore: add package-lock.json (#630) 2020-07-14 19:26:24 +09:00
エリス
efb633969e chore(package): use short notation (#631) 2020-07-14 19:15:57 +09:00
エリス
973bbbbac7 feat: migrate to @cordova/eslint-config@3.x (#629) 2020-07-14 19:15:29 +09:00
エリス
358522c0b5 ci: fix additional tests (#626) 2020-07-14 17:55:23 +09:00
エリス
8766956abb breaking: bump version 5.0.0-dev (#627) 2020-07-14 17:55:04 +09:00
jcesarmobile
d89c25cd82 fix(ios): tempFilePath called twice if using CameraUsesGeolocation (#612) 2020-06-25 18:23:01 +02:00
Jesse MacFadyen
ba4f77468f chore(release): 4.2.0-dev 2020-05-07 01:34:03 -07:00
Jesse MacFadyen
adf15799d9 Updated version and RELEASENOTES.md for release (Camera-4.2.0) 2020-05-07 00:45:53 -07:00
Jesse MacFadyen
e9aba07926 Merge pull request #588 from purplecabbage/AndroidCacheLocal
[Android] Cache images in device storage, devices have enough space now.
2020-04-30 10:46:21 -07:00
Jesse MacFadyen
df14414203 Cache images in device storage, devices have enough space now. 2020-04-28 13:57:00 -07:00
Norman Breau
2a750f0fa1 Merge pull request #508 from rtpHarry/patch-1
docs(readme): app renamed to Google Photos
2020-04-24 23:09:49 -03:00
Erisu
06ac9b3dc9 chore(asf): update git notification settings 2020-04-22 13:39:50 +09:00
jcesarmobile
bfa38fed2c fix(ios): return copy of video when picking from gallery on iOS 13 (#580) 2020-04-15 11:41:21 +02:00
Niklas Merz
7611960ef2 Update CONTRIBUTING.md 2020-04-13 14:27:10 +02:00
exxbrain
f4067e22d9 Fix UI API called on a background thread (#550, #530, #447) (#551)
Co-authored-by: Denis Zakharov <d.zakharov@bssys.com>
2020-04-09 13:54:26 +00:00
Tim Brust
f33ade83e4 ci: updates Node.js versions (#576) 2020-03-28 12:11:08 +00:00
Tim Brust
6f25420ce7 chore(npm): adds ignore list (#575) 2020-03-28 12:10:44 +00:00
jcesarmobile
6feaa95559 docs(README): remove confusing comment (#513) 2019-10-20 01:05:19 +02:00
jcesarmobile
c887c229f0 docs(README): remove orphan windows phone 7 note (#512) 2019-10-19 17:07:21 +02:00
Matthew Harris
6900fbaefa docs(readme): app renamed to Google Photos 2019-09-25 22:04:31 +07:00
klodha
a9436b1a18 ImagePicker returning same image (#306)
ImagePicker returning same image

Co-authored-by: Jan Piotrowski <piotrowski+github@gmail.com>
Co-authored-by: Tim Brust <github@timbrust.de>
2019-09-16 11:40:54 +02:00
Jan Piotrowski
db4b4b947d chore(release): 4.1.1-dev 2019-06-27 21:04:04 +02:00
31 changed files with 2520 additions and 613 deletions

View File

@@ -12,12 +12,17 @@ image:
- Visual Studio 2017
environment:
nodejs_version: "6"
matrix:
- PLATFORM: windows-10-store
- nodejs_version: "10"
- nodejs_version: "12"
- nodejs_version: "14"
platform:
- x86
- x64
install:
- ps: Install-Product node $env:nodejs_version
- node --version
- npm install -g github:apache/cordova-paramedic
- npm install -g cordova
@@ -25,4 +30,4 @@ install:
build: off
test_script:
- cordova-paramedic --config pr\%PLATFORM% --plugin . --justBuild
- cordova-paramedic --config pr\windows-10-store --plugin . --justBuild

46
.asf.yaml Normal file
View File

@@ -0,0 +1,46 @@
# 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.
github:
description: Apache Cordova Plugin camera
homepage: https://cordova.apache.org/
labels:
- cordova
- mobile
- javascript
- nodejs
- hacktoberfest
- java
- objective-c
- cordova-plugin
features:
wiki: false
issues: true
projects: true
enabled_merge_buttons:
squash: true
merge: false
rebase: false
notifications:
commits: commits@cordova.apache.org
issues: issues@cordova.apache.org
pullrequests_status: issues@cordova.apache.org
pullrequests_comment: issues@cordova.apache.org

View File

@@ -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'

57
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
# 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.
name: Node CI
on: [push, pull_request]
jobs:
test:
name: NodeJS ${{ matrix.node-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version: [10.x, 12.x, 14.x, 16.x]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Environment Information
run: |
node --version
npm --version
gradle --version
- name: npm install and test
run: |
npm i
npm t
env:
CI: true

13
.github/workflows/release-notify.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
name: Close issue asking for release
on:
issues:
types: [opened]
jobs:
action-test:
runs-on: ubuntu-latest
steps:
- uses: niklasmerz/release-notify@master
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

3
.npmignore Normal file
View File

@@ -0,0 +1,3 @@
.*
appveyor.yml
tests

View File

@@ -1,4 +1,4 @@
# This Travis configuration file is built after a Cordova Paramedic
# This Travis configuration file is built after a Cordova Paramedic
# specific template with minimal modifications and adaptations:
# https://github.com/apache/cordova-paramedic/blob/master/.travis.yml
@@ -12,18 +12,18 @@ addons:
env:
global:
- SAUCE_USERNAME=snay
- TRAVIS_NODE_VERSION=8
- ANDROID_API_LEVEL=28
- ANDROID_BUILD_TOOLS_VERSION=28.0.3
- TRAVIS_NODE_VERSION=12
- ANDROID_API_LEVEL=29
- ANDROID_BUILD_TOOLS_VERSION=29.0.2
language: node_js
node_js: 8
node_js: 14
# yaml anchor/alias: https://medium.com/@tommyvn/travis-yml-dry-with-anchors-8b6a3ac1b027
_ios: &_ios
os: osx
osx_image: xcode10.2
osx_image: xcode11.6
_android: &_android
language: android
@@ -35,15 +35,16 @@ _android: &_android
- build-tools-$ANDROID_BUILD_TOOLS_VERSION
- android-$ANDROID_API_LEVEL
licenses:
- 'android-sdk-preview-license-.+'
- 'android-sdk-license-.+'
- 'google-gdk-license-.+'
- "android-sdk-preview-license-.+"
- "android-sdk-license-.+"
- "google-gdk-license-.+"
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
@@ -81,13 +82,13 @@ matrix:
before_install:
# manually install Node for `language: android`
- if [[ "$PLATFORM" =~ android ]]; then nvm install $TRAVIS_NODE_VERSION; fi
- if [[ "$PLATFORM" =~ android ]]; then nvm install $TRAVIS_NODE_VERSION; fi
- node --version
- if [[ "$PLATFORM" =~ android ]]; then gradle --version; fi
- if [[ "$PLATFORM" =~ ios ]]; then npm install -g ios-deploy; fi
- npm install -g cordova
# install paramedic if not running on paramedic repo
- if ! [[ "$TRAVIS_REPO_SLUG" =~ cordova-paramedic ]]; then npm install -g github:apache/cordova-paramedic; fi
- if ! [[ "$TRAVIS_REPO_SLUG" =~ cordova-paramedic ]]; then npm install -g github:apache/cordova-paramedic; fi
install:
- npm install
@@ -106,11 +107,12 @@ before_script:
PARAMEDIC_COMMAND="cordova-paramedic"
fi
- PARAMEDIC_BUILDNAME=travis-$TRAVIS_REPO_SLUG-$TRAVIS_JOB_NUMBER
script:
- $TEST_COMMAND
- if [[ "$ADDITIONAL_TESTS_DIR" != "" ]];
- |
if [[ "$ADDITIONAL_TESTS_DIR" != "" ]];
then cd $ADDITIONAL_TESTS_DIR && npm install && npm test;
else
$PARAMEDIC_COMMAND --config ./pr/$PLATFORM --plugin $PARAMEDIC_PLUGIN_TO_TEST --buildName $PARAMEDIC_BUILDNAME;
else
$PARAMEDIC_COMMAND --config ./pr/$PLATFORM --plugin $PARAMEDIC_PLUGIN_TO_TEST --buildName $PARAMEDIC_BUILDNAME;
fi

View File

@@ -25,13 +25,13 @@ Anyone can contribute to Cordova. And we need your contributions.
There are multiple ways to contribute: report bugs, improve the docs, and
contribute code.
For instructions on this, start with the
For instructions on this, start with the
[contribution overview](http://cordova.apache.org/contribute/).
The details are explained there, but the important items are:
- Sign and submit an Apache ICLA (Contributor License Agreement).
- Have a Jira issue open that corresponds to your contribution.
- Check for Github issues that corresponds to your contribution and link or create them if necessary.
- Run the tests so your patch doesn't break existing functionality.
We look forward to your contributions!

View File

@@ -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
@@ -482,11 +474,6 @@ displays:
// do your thing here!
}, 0);
#### Windows Phone 7 Quirks
Invoking the native camera application while the device is connected
via Zune does not work, and triggers an error callback.
#### Windows quirks
On Windows Phone 8.1 using `SAVEDPHOTOALBUM` or `PHOTOLIBRARY` as a source type causes application to suspend until file picker returns the selected image and
@@ -503,7 +490,7 @@ More information about Windows Phone 8.1 picker APIs is here: [How to continue y
- Any `cameraDirection` value results in a back-facing photo. (= You can only use the back camera)
- **`allowEdit` is unpredictable on Android and it should not be used!** The Android implementation of this plugin tries to find and use an application on the user's device to do image cropping. The plugin has no control over what application the user selects to perform the image cropping and it is very possible that the user could choose an incompatible option and cause the plugin to fail. This sometimes works because most devices come with an application that handles cropping in a way that is compatible with this plugin (Google Plus Photos), but it is unwise to rely on that being the case. If image editing is essential to your application, consider seeking a third party library or plugin that provides its own image editing utility for a more robust solution.
- **`allowEdit` is unpredictable on Android and it should not be used!** The Android implementation of this plugin tries to find and use an application on the user's device to do image cropping. The plugin has no control over what application the user selects to perform the image cropping and it is very possible that the user could choose an incompatible option and cause the plugin to fail. This sometimes works because most devices come with an application that handles cropping in a way that is compatible with this plugin (Google Photos), but it is unwise to rely on that being the case. If image editing is essential to your application, consider seeking a third party library or plugin that provides its own image editing utility for a more robust solution.
- `Camera.PictureSourceType.PHOTOLIBRARY` and `Camera.PictureSourceType.SAVEDPHOTOALBUM` both display the same photo album.
@@ -513,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
@@ -545,7 +529,7 @@ function setOptions(srcType) {
encodingType: Camera.EncodingType.JPEG,
mediaType: Camera.MediaType.PICTURE,
allowEdit: true,
correctOrientation: true //Corrects Android orientation quirks
correctOrientation: true
}
return options;
}

View File

@@ -20,6 +20,73 @@
-->
# Release Notes
### 6.0.0 (Aug 19, 2021)
**Feature:**
* [GH-751](https://github.com/apache/cordova-plugin-camera/pull/751) feat(android)!: support **AndroidX**
* [GH-750](https://github.com/apache/cordova-plugin-camera/pull/750) feat(android): bump `cordova-android` requirements for `10.x`
* [GH-731](https://github.com/apache/cordova-plugin-camera/pull/731) feat(android): encode `heic` format to `EncodingType` for webview display [#711](https://github.com/apache/cordova-plugin-camera/issues/711)
* [GH-684](https://github.com/apache/cordova-plugin-camera/pull/684) feat(android): `sdk-30` package visibility support
**Fix:**
* [GH-687](https://github.com/apache/cordova-plugin-camera/pull/687) fix(android): return exception message (where it exists)
* [GH-585](https://github.com/apache/cordova-plugin-camera/pull/585) fix(android): file path correction if `Uri` authority is `FileProvider`
**Chore & CI:**
* [GH-749](https://github.com/apache/cordova-plugin-camera/pull/749) chore: bump plugin version for next major
* [GH-654](https://github.com/apache/cordova-plugin-camera/pull/654) chore: add release notify action
* [GH-745](https://github.com/apache/cordova-plugin-camera/pull/745) ci(gh-action): added workflow to run tests
### 5.0.3 (Aug 04, 2021)
* [GH-754](https://github.com/apache/cordova-plugin-camera/pull/754) chore: rebuilt `package-lock.json`
* [GH-748](https://github.com/apache/cordova-plugin-camera/pull/748) fix: incorrect version in `package-lock`
* [GH-747](https://github.com/apache/cordova-plugin-camera/pull/747) chore: set the 5.x versions locked to `cordova-android` `<10.0.0`
* [GH-729](https://github.com/apache/cordova-plugin-camera/pull/729) chore(asf): Update GitHub repo metadata
### 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
* [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
* [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)
- docs: remove outdated test docs translations ([`06dc38f`](https://github.com/apache/cordova-plugin-camera/commit/06dc38f))
@@ -35,23 +102,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)

1837
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-camera",
"version": "4.1.0",
"version": "6.0.0",
"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,26 @@
"cordova": ">=7.1.0"
},
"5.0.0": {
"cordova-android": ">=9.0.0",
"cordova-ios": ">=5.1.0",
"cordova": ">=9.0.0"
},
"5.0.4-dev": {
"cordova-android": "<10.0.0",
"cordova-ios": ">=5.1.0",
"cordova": ">=9.0.0"
},
"6.0.0": {
"cordova-android": ">=10.0.0",
"cordova-ios": ">=5.1.0",
"cordova": ">=9.0.0"
},
"7.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"
}
}

View File

@@ -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.1.0">
version="6.0.0">
<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=">=10.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
@@ -68,20 +69,37 @@
</provider>
</config-file>
<config-file target="AndroidManifest.xml" parent="/*">
<queries>
<intent>
<action android:name="android.media.action.IMAGE_CAPTURE" />
</intent>
<intent>
<action android:name="android.intent.action.GET_CONTENT" />
</intent>
<intent>
<action android:name="android.intent.action.PICK" />
</intent>
<intent>
<action android:name="com.android.camera.action.CROP" />
<data android:scheme="content" android:mimeType="image/*"/>
</intent>
</queries>
</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" />
<preference name="ANDROIDX_CORE_VERSION" default="1.6.+"/>
<framework src="androidx.core:core:$ANDROIDX_CORE_VERSION" />
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
<clobbers target="CameraPopoverHandle" />
</js-module>
<preference name="ANDROID_SUPPORT_V4_VERSION" default="27.+"/>
<framework src="com.android.support:support-v4:$ANDROID_SUPPORT_V4_VERSION"/>
</platform>
<!-- ios -->
@@ -151,12 +169,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>

View File

@@ -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,10 +35,11 @@ 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;
import android.support.v4.content.FileProvider;
import androidx.core.content.FileProvider;
import android.util.Base64;
import org.apache.cordova.BuildHelper;
@@ -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
@@ -87,11 +87,13 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
private static final String PNG_EXTENSION = "." + PNG_TYPE;
private static final String PNG_MIME_TYPE = "image/png";
private static final String JPEG_MIME_TYPE = "image/jpeg";
private static final String HEIC_MIME_TYPE = "image/heic";
private static final String GET_PICTURE = "Get Picture";
private static final String GET_VIDEO = "Get Video";
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 +111,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 +130,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;
@@ -194,7 +198,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
if(!PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
PermissionHelper.requestPermission(this, SAVE_TO_ALBUM_SEC, Manifest.permission.READ_EXTERNAL_STORAGE);
} else {
this.getImage(this.srcType, destType, encodingType);
this.getImage(this.srcType, destType);
}
}
}
@@ -220,17 +224,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
//--------------------------------------------------------------------------
private String getTempDirectoryPath() {
File cache = null;
// SD Card Mounted
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
cache = cordova.getActivity().getExternalCacheDir();
}
// Use internal storage
else {
cache = cordova.getActivity().getCacheDir();
}
File cache = cordova.getActivity().getCacheDir();
// Create the cache directory if it doesn't exist
cache.mkdirs();
return cache.getAbsolutePath();
@@ -280,9 +274,9 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
if (takePicturePermission && saveAlbumPermission) {
takePicture(returnType, encodingType);
} else if (saveAlbumPermission && !takePicturePermission) {
} else if (saveAlbumPermission) {
PermissionHelper.requestPermission(this, TAKE_PIC_SEC, Manifest.permission.CAMERA);
} else if (!saveAlbumPermission && takePicturePermission) {
} else if (takePicturePermission) {
PermissionHelper.requestPermissions(this, TAKE_PIC_SEC,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE});
} else {
@@ -300,10 +294,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);
@@ -362,14 +357,14 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
*
* @param srcType The album to get image from.
* @param returnType Set the type of image to return.
* @param encodingType
*/
// TODO: Images selected from SDCARD don't display correctly, but from CAMERA ALBUM do!
// TODO: Images from kitkat filechooser not going into crop function
public void getImage(int srcType, int returnType, int encodingType) {
public void getImage(int srcType, int returnType) {
Intent intent = new Intent();
String title = GET_PICTURE;
croppedUri = null;
croppedFilePath = null;
if (this.mediaType == PICTURE) {
intent.setType("image/*");
if (this.allowEdit) {
@@ -385,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);
@@ -411,57 +407,53 @@ 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);
}
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
// indicate output X and Y
if (targetWidth > 0) {
cropIntent.putExtra("outputX", targetWidth);
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.
@@ -476,9 +468,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) {
try {
@@ -499,16 +490,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
@@ -536,7 +529,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) {
@@ -549,10 +542,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);
}
@@ -572,9 +565,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();
@@ -598,56 +589,69 @@ 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, getMimetypeForEncodingType());
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);
String imageFileName = "IMG_" + timeStamp + getExtensionForEncodingType();
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);
}
/**
* Converts output image format int value to string value of mime type.
* @param outputFormat int Output format of camera API.
* Must be value of either JPEG or PNG constant
* @return String String value of mime type or empty string if mime type is not supported
*/
private String getMimetypeForFormat(int outputFormat) {
if (outputFormat == PNG) return PNG_MIME_TYPE;
if (outputFormat == JPEG) return JPEG_MIME_TYPE;
private String getMimetypeForEncodingType() {
if (encodingType == PNG) return PNG_MIME_TYPE;
if (encodingType == JPEG) return JPEG_MIME_TYPE;
return "";
}
private String outputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException {
private String outputModifiedBitmap(Bitmap bitmap, Uri uri, String mimeTypeOfOriginalFile) throws IOException {
// Some content: URIs do not map to file paths (e.g. picasa).
String realPath = FileHelper.getRealPath(uri, this.cordova);
String fileName = calculateModifiedBitmapOutputFileName(mimeTypeOfOriginalFile, realPath);
// Get filename from uri
String fileName = realPath != null ?
realPath.substring(realPath.lastIndexOf('/') + 1) :
"modified." + (this.encodingType == JPEG ? JPEG_TYPE : PNG_TYPE);
String timeStamp = new SimpleDateFormat(TIME_FORMAT).format(new Date());
//String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
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();
@@ -667,6 +671,23 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
return modifiedPath;
}
private String calculateModifiedBitmapOutputFileName(String mimeTypeOfOriginalFile, String realPath) {
if (realPath == null) {
return "modified" + getExtensionForEncodingType();
}
String fileName = realPath.substring(realPath.lastIndexOf('/') + 1);
if (getMimetypeForEncodingType().equals(mimeTypeOfOriginalFile)) {
return fileName;
}
// if the picture is not a jpeg or png, (a .heic for example) when processed to a bitmap
// the file extension is changed to the output format, f.e. an input file my_photo.heic could become my_photo.jpg
return fileName.substring(fileName.lastIndexOf(".") + 1) + getExtensionForEncodingType();
}
private String getExtensionForEncodingType() {
return this.encodingType == JPEG ? JPEG_EXTENSION : PNG_EXTENSION;
}
/**
* Applies all needed transformation to the image received from the gallery.
@@ -684,74 +705,90 @@ 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 mimeType = FileHelper.getMimeType(uriString, this.cordova);
String finalLocation = fileLocation != null ? fileLocation : uriString;
String mimeTypeOfGalleryFile = 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 {
// 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);
if (finalLocation == null) {
this.failPicture("Error retrieving result.");
} else {
// If you ask for video or the selected file cannot be processed
// there will be no attempt to resize any returned data.
if (this.mediaType == VIDEO || !isImageMimeTypeProcessable(mimeTypeOfGalleryFile)) {
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 || 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 &&
getMimetypeForEncodingType().equalsIgnoreCase(mimeTypeOfGalleryFile))
{
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) ||
!mimeTypeOfGalleryFile.equalsIgnoreCase(getMimetypeForEncodingType()))
{
try {
String modifiedPath = this.outputModifiedBitmap(bitmap, uri, mimeTypeOfGalleryFile);
// 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: "+e.getLocalizedMessage());
}
} else {
this.callbackContext.success(finalLocation);
}
}
if (bitmap != null) {
bitmap.recycle();
bitmap = null;
}
System.gc();
}
if (bitmap != null) {
bitmap.recycle();
bitmap = null;
}
System.gc();
}
}
}
/**
* JPEG, PNG and HEIC mime types (images) can be scaled, decreased in quantity, corrected by orientation.
* But f.e. an image/gif cannot be scaled, but is can be selected through the PHOTOLIBRARY.
*
* @param mimeType The mimeType to check
* @return if the mimeType is a processable image mime type
*/
private boolean isImageMimeTypeProcessable(String mimeType) {
return JPEG_MIME_TYPE.equalsIgnoreCase(mimeType) || PNG_MIME_TYPE.equalsIgnoreCase(mimeType)
|| HEIC_MIME_TYPE.equalsIgnoreCase(mimeType);
}
/**
@@ -799,7 +836,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 {
@@ -807,7 +844,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
}
} catch (IOException e) {
e.printStackTrace();
this.failPicture("Error capturing image.");
this.failPicture("Error capturing image: "+e.getLocalizedMessage());
}
}
@@ -898,34 +935,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
*
@@ -974,7 +988,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
if (fileStream != null) {
// Generate a temporary file
String timeStamp = new SimpleDateFormat(TIME_FORMAT).format(new Date());
String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? JPEG_EXTENSION : PNG_EXTENSION);
String fileName = "IMG_" + timeStamp + (getExtensionForEncodingType());
localFile = new File(getTempDirectoryPath() + fileName);
galleryUri = Uri.fromFile(localFile);
writeUncompressedImage(fileStream, galleryUri);
@@ -998,15 +1012,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
rotate = 0;
}
}
}
catch (Exception e)
{
} catch (Exception e) {
LOG.e(LOG_TAG,"Exception while getting input stream: "+ e.toString());
return null;
}
try {
// figure out the original width and height of the image
BitmapFactory.Options options = new BitmapFactory.Options();
@@ -1052,7 +1062,6 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
// determine the correct aspect ratio
int[] widthHeight = calculateAspectRatio(rotatedWidth, rotatedHeight);
// Load in the smallest bitmap possible that is closest to the size we want
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(rotatedWidth, rotatedHeight, widthHeight[0], widthHeight[1]);
@@ -1092,8 +1101,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
}
}
return scaledBitmap;
}
finally {
} finally {
// delete the temporary copy
if (localFile != null) {
localFile.delete();
@@ -1256,9 +1264,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)) {
@@ -1271,7 +1277,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
code = null;
}
} catch (Exception e) {
this.failPicture("Error compressing image.");
this.failPicture("Error compressing image: "+e.getLocalizedMessage());
}
jpeg_data = null;
}
@@ -1307,9 +1313,8 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
this.conn.disconnect();
}
public void onRequestPermissionResult(int requestCode, String[] permissions,
int[] grantResults) throws JSONException {
int[] grantResults) {
for (int r : grantResults) {
if (r == PackageManager.PERMISSION_DENIED) {
this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR));
@@ -1321,7 +1326,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
takePicture(this.destType, this.encodingType);
break;
case SAVE_TO_ALBUM_SEC:
this.getImage(this.srcType, this.destType, this.encodingType);
this.getImage(this.srcType, this.destType);
break;
}
}
@@ -1346,11 +1351,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;
@@ -1375,28 +1384,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;
}
}

View File

@@ -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;
}
}

View File

@@ -19,7 +19,6 @@ package org.apache.cordova.camera;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.content.CursorLoader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
@@ -29,8 +28,8 @@ import android.provider.MediaStore;
import android.webkit.MimeTypeMap;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.LOG;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -44,29 +43,20 @@ public class FileHelper {
* Returns the real path of the given URI string.
* If the given URI string represents a content:// URI, the real path is retrieved from the media store.
*
* @param uriString the URI string of the audio/image/video
* @param uri the URI of the audio/image/video
* @param cordova the current application context
* @return the full path to the file
*/
@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);
}
/**
* Returns the real path of the given URI.
* If the given URI is a content:// URI, the real path is retrieved from the media store.
*
* @param uri the URI of the audio/image/video
* @param uriString the URI string from which to obtain the input stream
* @param cordova the current application context
* @return the full path to the file
*/
@@ -75,11 +65,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)) {
@@ -143,6 +131,9 @@ public class FileHelper {
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
if (isFileProviderUri(context, uri))
return getFileProviderPath(context, uri);
return getDataColumn(context, uri, null, null);
}
// File
@@ -153,22 +144,6 @@ public class FileHelper {
return null;
}
public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
String result = null;
try {
Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
result = cursor.getString(column_index);
} catch (Exception e) {
result = null;
}
return result;
}
/**
* Returns an input stream based on given URI string.
*
@@ -188,6 +163,7 @@ public class FileHelper {
if (question > -1) {
uriString = uriString.substring(0, question);
}
if (uriString.startsWith("file:///android_asset/")) {
Uri uri = Uri.parse(uriString);
String relativePath = uri.getPath().substring(15);
@@ -217,6 +193,7 @@ public class FileHelper {
* @return a path without the "file://" prefix
*/
public static String stripFileProtocol(String uriString) {
if (uriString.startsWith("file://")) {
uriString = uriString.substring(7);
}
@@ -236,7 +213,7 @@ public class FileHelper {
}
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
/**
* Returns the mime type of the data specified by the given URI string.
*
@@ -244,7 +221,7 @@ public class FileHelper {
* @return the mime type of the specified data
*/
public static String getMimeType(String uriString, CordovaInterface cordova) {
String mimeType = null;
String mimeType;
Uri uri = Uri.parse(uriString);
if (uriString.startsWith("content://")) {
@@ -327,4 +304,28 @@ public class FileHelper {
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
/**
* @param context The Application context
* @param uri The Uri is checked by functions
* @return Whether the Uri authority is FileProvider
*/
public static boolean isFileProviderUri(final Context context, final Uri uri) {
final String packageName = context.getPackageName();
final String authority = new StringBuilder(packageName).append(".provider").toString();
return authority.equals(uri.getAuthority());
}
/**
* @param context The Application context
* @param uri The Uri is checked by functions
* @return File path or null if file is missing
*/
public static String getFileProviderPath(final Context context, final Uri uri)
{
final File appDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
final File file = new File(appDir, uri.getLastPathSegment());
return file.exists() ? file.toString(): null;
}
}

View File

@@ -18,4 +18,4 @@
*/
package org.apache.cordova.camera;
public class FileProvider extends android.support.v4.content.FileProvider {}
public class FileProvider extends androidx.core.content.FileProvider {}

View 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;
}
}

View File

@@ -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>

View File

@@ -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 :(');
}

View File

@@ -24,8 +24,7 @@
enum CDVDestinationType {
DestinationTypeDataUrl = 0,
DestinationTypeFileUri,
DestinationTypeNativeUri
DestinationTypeFileUri
};
typedef NSUInteger CDVDestinationType;

View File

@@ -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];
@@ -185,16 +185,16 @@ static NSString* toBase64(NSData* data) {
- (void)showCameraPicker:(NSString*)callbackId withOptions:(CDVPictureOptions *) pictureOptions
{
CDVCameraPicker* cameraPicker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
self.pickerController = cameraPicker;
cameraPicker.delegate = self;
cameraPicker.callbackId = callbackId;
// we need to capture this state for memory warnings that dealloc this object
cameraPicker.webView = self.webView;
// Perform UI operations on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
CDVCameraPicker* cameraPicker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
self.pickerController = cameraPicker;
cameraPicker.delegate = self;
cameraPicker.callbackId = callbackId;
// we need to capture this state for memory warnings that dealloc this object
cameraPicker.webView = self.webView;
// If a popover is already open, close it; we only want one at a time.
if (([[self pickerController] pickerPopoverController] != nil) && [[[self pickerController] pickerPopoverController] isPopoverVisible]) {
[[[self pickerController] pickerPopoverController] dismissPopoverAnimated:YES];
@@ -374,7 +374,7 @@ static NSString* toBase64(NSData* data) {
self.metadata = [[NSMutableDictionary alloc] init];
NSMutableDictionary* EXIFDictionary = [[controllerMetadata objectForKey:(NSString*)kCGImagePropertyExifDictionary]mutableCopy];
if (EXIFDictionary) {
if (EXIFDictionary) {
[self.metadata setObject:EXIFDictionary forKey:(NSString*)kCGImagePropertyExifDictionary];
}
@@ -383,6 +383,7 @@ static NSString* toBase64(NSData* data) {
}
[[self locationManager] startUpdatingLocation];
}
data = nil;
}
}
break;
@@ -396,14 +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;
// generate unique file name
int i = 1;
do {
filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX, i++, extension];
} while ([fileMgr fileExistsAtPath:filePath]);
// unique file name
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
NSNumber *timeStampObj = [NSNumber numberWithDouble: timeStamp];
NSString* filePath = [NSString stringWithFormat:@"%@/%@%ld.%@", docsPath, CDV_PHOTO_PREFIX, [timeStampObj longValue], extension];
return filePath;
}
@@ -443,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];
@@ -488,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);
@@ -512,9 +480,22 @@ static NSString* toBase64(NSData* data) {
- (CDVPluginResult*)resultForVideo:(NSDictionary*)info
{
NSString* moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] absoluteString];
// On iOS 13 the movie path becomes inaccessible, create and return a copy
if (IsAtLeastiOSVersion(@"13.0")) {
moviePath = [self createTmpVideo:[[info objectForKey:UIImagePickerControllerMediaURL] path]];
}
return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:moviePath];
}
- (NSString *) createTmpVideo:(NSString *) moviePath {
NSString* moviePathExtension = [moviePath pathExtension];
NSString* copyMoviePath = [self tempFilePath:moviePathExtension];
NSFileManager* fileMgr = [[NSFileManager alloc] init];
NSError *error;
[fileMgr copyItemAtPath:moviePath toPath:copyMoviePath error:&error];
return [[NSURL fileURLWithPath:copyMoviePath] absoluteString];
}
- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{
__weak CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
@@ -566,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"];
}
@@ -586,15 +565,15 @@ static NSString* toBase64(NSData* data) {
- (CLLocationManager*)locationManager
{
if (locationManager != nil) {
return locationManager;
}
if (locationManager != nil) {
return locationManager;
}
locationManager = [[CLLocationManager alloc] init];
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[locationManager setDelegate:self];
locationManager = [[CLLocationManager alloc] init];
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[locationManager setDelegate:self];
return locationManager;
return locationManager;
}
- (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation
@@ -672,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";
@@ -699,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) {
@@ -719,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);
}
}

View File

@@ -24,8 +24,7 @@
enum CDVDestinationType {
DestinationTypeDataUrl = 0,
DestinationTypeFileUri,
DestinationTypeNativeUri
DestinationTypeFileUri
};
typedef NSUInteger CDVDestinationType;

View File

@@ -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://" : @"";

View 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) {

View File

@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-camera-tests",
"version": "4.1.0",
"version": "6.0.0",
"description": "",
"cordova": {
"id": "cordova-plugin-camera-tests",

View File

@@ -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.1.0">
version="6.0.0">
<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>

View File

@@ -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
View File

@@ -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;

View File

@@ -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}
*/

View File

@@ -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);
};
};