├── .asf.yaml
├── .eslintrc.yml
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE.md
├── ISSUE_TEMPLATE
│ ├── BUG_REPORT.md
│ ├── FEATURE_REQUEST.md
│ └── SUPPORT_QUESTION.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── android.yml
│ ├── chrome.yml
│ ├── ios.yml
│ ├── lint.yml
│ └── release-notify.yml
├── .gitignore
├── .npmignore
├── .npmrc
├── CONTRIBUTING.md
├── LICENSE
├── NOTICE
├── README.md
├── RELEASENOTES.md
├── package-lock.json
├── package.json
├── plugin.xml
├── src
├── android
│ ├── CameraLauncher.java
│ ├── ExifHelper.java
│ ├── FileHelper.java
│ ├── FileProvider.java
│ ├── GalleryPathVO.java
│ └── xml
│ │ └── camera_provider_paths.xml
├── browser
│ └── CameraProxy.js
└── ios
│ ├── CDVCamera.h
│ ├── CDVCamera.m
│ ├── CDVExif.h
│ ├── CDVJpegHeaderWriter.h
│ ├── CDVJpegHeaderWriter.m
│ ├── UIImage+CropScaleOrientation.h
│ └── UIImage+CropScaleOrientation.m
├── tests
├── ios
│ ├── .gitignore
│ ├── CDVCameraTest.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── CDVCameraTest.xccheckout
│ │ │ └── xcschemes
│ │ │ └── CordovaLib.xcscheme
│ ├── CDVCameraTest
│ │ ├── CDVCameraLibTests
│ │ │ ├── CameraTest.m
│ │ │ └── Info.plist
│ │ └── CDVCameraTest.xcodeproj
│ │ │ ├── project.pbxproj
│ │ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── CDVCameraTest.xccheckout
│ │ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ ├── CDVCameraLib.xcscheme
│ │ │ └── CDVCameraLibTests.xcscheme
│ ├── README.md
│ └── package.json
├── package-lock.json
├── package.json
├── plugin.xml
└── tests.js
├── types
└── index.d.ts
└── www
├── Camera.js
├── CameraConstants.js
├── CameraPopoverHandle.js
├── CameraPopoverOptions.js
└── ios
└── CameraPopoverHandle.js
/.asf.yaml:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | github:
19 | description: Apache Cordova Plugin camera
20 | homepage: https://cordova.apache.org/
21 |
22 | labels:
23 | - cordova
24 | - mobile
25 | - javascript
26 | - nodejs
27 | - hacktoberfest
28 | - java
29 | - objective-c
30 | - cordova-plugin
31 |
32 | features:
33 | wiki: false
34 | issues: true
35 | projects: true
36 |
37 | enabled_merge_buttons:
38 | squash: true
39 | merge: false
40 | rebase: false
41 |
42 | notifications:
43 | commits: commits@cordova.apache.org
44 | issues: issues@cordova.apache.org
45 | pullrequests_status: issues@cordova.apache.org
46 | pullrequests_comment: issues@cordova.apache.org
47 |
--------------------------------------------------------------------------------
/.eslintrc.yml:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | root: true
19 | extends: '@cordova/eslint-config/browser'
20 |
21 | overrides:
22 | - files: [tests/**/*.js]
23 | extends: '@cordova/eslint-config/node-tests'
24 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text eol=lf
2 |
3 | # source code
4 | *.php text
5 | *.css text
6 | *.sass text
7 | *.scss text
8 | *.less text
9 | *.styl text
10 | *.js text
11 | *.coffee text
12 | *.json text
13 | *.htm text
14 | *.html text
15 | *.xml text
16 | *.svg text
17 | *.txt text
18 | *.ini text
19 | *.inc text
20 | *.pl text
21 | *.rb text
22 | *.py text
23 | *.scm text
24 | *.sql text
25 | *.sh text
26 | *.bat text
27 |
28 | # templates
29 | *.ejs text
30 | *.hbt text
31 | *.jade text
32 | *.haml text
33 | *.hbs text
34 | *.dot text
35 | *.tmpl text
36 | *.phtml text
37 |
38 | # server config
39 | .htaccess text
40 |
41 | # git config
42 | .gitattributes text
43 | .gitignore text
44 | .gitconfig text
45 |
46 | # code analysis config
47 | .jshintrc text
48 | .jscsrc text
49 | .jshintignore text
50 | .csslintrc text
51 |
52 | # misc config
53 | *.yaml text
54 | *.yml text
55 | .editorconfig text
56 |
57 | # build config
58 | *.npmignore text
59 | *.bowerrc text
60 |
61 | # Heroku
62 | Procfile text
63 | .slugignore text
64 |
65 | # Documentation
66 | *.md text
67 | LICENSE text
68 | AUTHORS text
69 |
70 |
71 | #
72 | ## These files are binary and should be left untouched
73 | #
74 |
75 | # (binary is a macro for -text -diff)
76 | *.png binary
77 | *.jpg binary
78 | *.jpeg binary
79 | *.gif binary
80 | *.ico binary
81 | *.mov binary
82 | *.mp4 binary
83 | *.mp3 binary
84 | *.flv binary
85 | *.fla binary
86 | *.swf binary
87 | *.gz binary
88 | *.zip binary
89 | *.7z binary
90 | *.ttf binary
91 | *.eot binary
92 | *.woff binary
93 | *.pyc binary
94 | *.pdf binary
95 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
5 |
6 | ### Issue Type
7 |
8 |
9 | - [ ] Bug Report
10 | - [ ] Feature Request
11 | - [ ] Support Question
12 |
13 | ## Description
14 |
15 | ## Information
16 |
17 |
18 | ### Command or Code
19 |
20 |
21 | ### Environment, Platform, Device
22 |
23 |
24 |
25 |
26 | ### Version information
27 |
34 |
35 |
36 |
37 | ## Checklist
38 |
39 |
40 | - [ ] I searched for already existing GitHub issues about this
41 | - [ ] I updated all Cordova tooling to their most recent version
42 | - [ ] I included all the necessary information above
43 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/BUG_REPORT.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🐛 Bug Report
3 | about: If something isn't working as expected.
4 |
5 | ---
6 |
7 | # Bug Report
8 |
9 | ## Problem
10 |
11 | ### What is expected to happen?
12 |
13 |
14 |
15 | ### What does actually happen?
16 |
17 |
18 |
19 | ## Information
20 |
21 |
22 |
23 |
24 | ### Command or Code
25 |
26 |
27 |
28 |
29 | ### Environment, Platform, Device
30 |
31 |
32 |
33 |
34 | ### Version information
35 |
42 |
43 |
44 |
45 | ## Checklist
46 |
47 |
48 | - [ ] I searched for existing GitHub issues
49 | - [ ] I updated all Cordova tooling to most recent version
50 | - [ ] I included all the necessary information above
51 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🚀 Feature Request
3 | about: A suggestion for a new functionality
4 |
5 | ---
6 |
7 | # Feature Request
8 |
9 | ## Motivation Behind Feature
10 |
11 |
12 |
13 |
14 | ## Feature Description
15 |
20 |
21 |
22 |
23 | ## Alternatives or Workarounds
24 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/SUPPORT_QUESTION.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 💬 Support Question
3 | about: If you have a question, please check out our Slack or StackOverflow!
4 |
5 | ---
6 |
7 |
8 |
9 | Apache Cordova uses GitHub Issues as a feature request and bug tracker _only_.
10 | For usage and support questions, please check out the resources below. Thanks!
11 |
12 | ---
13 |
14 | You can get answers to your usage and support questions about **Apache Cordova** on:
15 |
16 | * GitHub Discussions: https://github.com/apache/cordova/discussions
17 | * Slack Community Chat: https://cordova.slack.com (you can sign-up at https://s.apache.org/cordova-slack)
18 | * StackOverflow: https://stackoverflow.com/questions/tagged/cordova using the tag `cordova`
19 |
20 | ---
21 |
22 | If you are using a tool that uses Cordova internally, like e.g. Ionic, check their support channels:
23 |
24 | * **Ionic Framework**
25 | * [Ionic Community Forum](https://forum.ionicframework.com/)
26 | * [Ionic Discord](https://ionic.link/discord)
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
8 |
9 | ### Platforms affected
10 |
11 |
12 |
13 | ### Motivation and Context
14 |
15 |
16 |
17 |
18 |
19 | ### Description
20 |
21 |
22 |
23 |
24 | ### Testing
25 |
26 |
27 |
28 |
29 | ### Checklist
30 |
31 | - [ ] I've run the tests to see all new and existing tests pass
32 | - [ ] I added automated test coverage as appropriate for this change
33 | - [ ] Commit is prefixed with `(platform)` if this change only applies to one platform (e.g. `(android)`)
34 | - [ ] If this Pull Request resolves an issue, I linked to the issue in the text above (and used the correct [keyword to close issues using keywords](https://help.github.com/articles/closing-issues-using-keywords/))
35 | - [ ] I've updated the documentation if necessary
36 |
--------------------------------------------------------------------------------
/.github/workflows/android.yml:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | name: Android Testsuite
19 |
20 | on:
21 | push:
22 | paths-ignore:
23 | - '**.md'
24 | - 'LICENSE'
25 | - '.eslint*'
26 |
27 | pull_request:
28 | paths-ignore:
29 | - '**.md'
30 | - 'LICENSE'
31 | - '.eslint*'
32 |
33 | jobs:
34 | test:
35 | name: Android ${{ matrix.versions.android }} Test
36 | runs-on: ubuntu-latest
37 | continue-on-error: true
38 |
39 | # hoist configurations to top that are expected to be updated
40 | env:
41 | # Storing a copy of the repo
42 | repo: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
43 |
44 | node-version: 20
45 |
46 | # These are the default Java configurations used by most tests.
47 | # To customize these options, add "java-distro" or "java-version" to the strategy matrix with its overriding value.
48 | default_java-distro: temurin
49 | default_java-version: 17
50 |
51 | # These are the default Android System Image configurations used by most tests.
52 | # To customize these options, add "system-image-arch" or "system-image-target" to the strategy matrix with its overriding value.
53 | default_system-image-arch: x86_64
54 | default_system-image-target: google_apis # Most system images have a google_api option. Set this as default.
55 |
56 | # configurations for each testing strategy (test matrix)
57 | strategy:
58 | matrix:
59 | versions:
60 | - android: 7
61 | android-api: 24
62 |
63 | - android: 7.1
64 | android-api: 25
65 |
66 | - android: 8
67 | android-api: 26
68 |
69 | - android: 8.1
70 | android-api: 27
71 | system-image-arch: x86
72 |
73 | - android: 9
74 | android-api: 28
75 |
76 | - android: 10
77 | android-api: 29
78 |
79 | - android: 11
80 | android-api: 30
81 |
82 | - android: 12
83 | android-api: 31
84 |
85 | - android: 12L
86 | android-api: 32
87 |
88 | - android: 13
89 | android-api: 33
90 |
91 | - android: 14
92 | android-api: 34
93 |
94 | timeout-minutes: 60
95 |
96 | steps:
97 | - uses: actions/checkout@v4
98 | - uses: actions/setup-node@v4
99 | with:
100 | node-version: ${{ env.node-version }}
101 | - uses: actions/setup-java@v4
102 | env:
103 | java-version: ${{ matrix.versions.java-version == '' && env.default_java-version || matrix.versions.java-version }}
104 | java-distro: ${{ matrix.versions.java-distro == '' && env.default_java-distro || matrix.versions.java-distro }}
105 | with:
106 | distribution: ${{ env.java-distro }}
107 | java-version: ${{ env.java-version }}
108 |
109 | - name: Enable KVM group perms
110 | run: |
111 | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
112 | sudo udevadm control --reload-rules
113 | sudo udevadm trigger --name-match=kvm
114 |
115 | - name: Run Environment Information
116 | run: |
117 | node --version
118 | npm --version
119 | java -version
120 |
121 | - name: Run npm install
122 | run: |
123 | export PATH="/usr/local/lib/android/sdk/platform-tools":$PATH
124 | export JAVA_HOME=$JAVA_HOME_11_X64
125 | npm i -g cordova@latest
126 | npm ci
127 |
128 | - name: Run paramedic install
129 | if: ${{ endswith(env.repo, '/cordova-paramedic') != true }}
130 | run: npm i -g github:apache/cordova-paramedic
131 |
132 | - uses: reactivecircus/android-emulator-runner@v2
133 | env:
134 | system-image-arch: ${{ matrix.versions.system-image-arch == '' && env.default_system-image-arch || matrix.versions.system-image-arch }}
135 | system-image-target: ${{ matrix.versions.system-image-target == '' && env.default_system-image-target || matrix.versions.system-image-target }}
136 | with:
137 | api-level: ${{ matrix.versions.android-api }}
138 | target: ${{ env.system-image-target }}
139 | arch: ${{ env.system-image-arch }}
140 | force-avd-creation: false
141 | disable-animations: false
142 | emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim
143 | script: echo "Pregenerate the AVD before running Paramedic"
144 |
145 | - name: Run paramedic tests
146 | uses: reactivecircus/android-emulator-runner@v2
147 | env:
148 | system-image-arch: ${{ matrix.versions.system-image-arch == '' && env.default_system-image-arch || matrix.versions.system-image-arch }}
149 | system-image-target: ${{ matrix.versions.system-image-target == '' && env.default_system-image-target || matrix.versions.system-image-target }}
150 | test_config: 'android-${{ matrix.versions.android }}.config.json'
151 | # Generally, this should automatically work for cordova-paramedic & plugins. If the path is unique, this can be manually changed.
152 | test_plugin_path: ${{ endswith(env.repo, '/cordova-paramedic') && './spec/testable-plugin/' || './' }}
153 | paramedic: ${{ endswith(env.repo, '/cordova-paramedic') && 'node main.js' || 'cordova-paramedic' }}
154 | with:
155 | api-level: ${{ matrix.versions.android-api }}
156 | target: ${{ env.system-image-target }}
157 | arch: ${{ env.system-image-arch }}
158 | force-avd-creation: false
159 | disable-animations: false
160 | emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim
161 | script: ${{ env.paramedic }} --config ./pr/local/${{ env.test_config }} --plugin ${{ env.test_plugin_path }}
162 |
--------------------------------------------------------------------------------
/.github/workflows/chrome.yml:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | name: Chrome Testsuite
19 |
20 | on:
21 | push:
22 | paths-ignore:
23 | - '**.md'
24 | - 'LICENSE'
25 | - '.eslint*'
26 | pull_request:
27 | paths-ignore:
28 | - '**.md'
29 | - 'LICENSE'
30 | - '.eslint*'
31 |
32 | jobs:
33 | test:
34 | name: Chrome Latest Test
35 | runs-on: ubuntu-latest
36 |
37 | # hoist configurations to top that are expected to be updated
38 | env:
39 | # Storing a copy of the repo
40 | repo: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
41 |
42 | node-version: 20
43 |
44 | steps:
45 | - uses: actions/checkout@v4
46 | - uses: actions/setup-node@v4
47 | with:
48 | node-version: ${{ env.node-version }}
49 |
50 | - name: Run install xvfb
51 | run: sudo apt-get install xvfb
52 |
53 | - name: Run Environment Information
54 | run: |
55 | node --version
56 | npm --version
57 |
58 | - name: Run npm install
59 | run: |
60 | npm i -g cordova@latest
61 | npm ci
62 |
63 | - name: Run paramedic install
64 | if: ${{ endswith(env.repo, '/cordova-paramedic') != true }}
65 | run: npm i -g github:apache/cordova-paramedic
66 |
67 | - name: Run paramedic tests
68 | env:
69 | test_config: 'browser.config.json'
70 | # Generally, this should automatically work for cordova-paramedic & plugins. If the path is unique, this can be manually changed.
71 | test_plugin_path: ${{ endswith(env.repo, '/cordova-paramedic') && './spec/testable-plugin/' || './' }}
72 | paramedic: ${{ endswith(env.repo, '/cordova-paramedic') && 'node main.js' || 'cordova-paramedic' }}
73 | run: xvfb-run --auto-servernum ${{ env.paramedic }} --config ./pr/local/${{ env.test_config }} --plugin ${{ env.test_plugin_path }}
74 |
--------------------------------------------------------------------------------
/.github/workflows/ios.yml:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | name: iOS Testsuite
19 |
20 | on:
21 | push:
22 | paths-ignore:
23 | - '**.md'
24 | - 'LICENSE'
25 | - '.eslint*'
26 | pull_request:
27 | paths-ignore:
28 | - '**.md'
29 | - 'LICENSE'
30 | - '.eslint*'
31 |
32 | jobs:
33 | test:
34 | name: iOS ${{ matrix.versions.ios-version }} Test
35 | runs-on: ${{ matrix.versions.os-version }}
36 | continue-on-error: true
37 |
38 | # hoist configurations to top that are expected to be updated
39 | env:
40 | # Storing a copy of the repo
41 | repo: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
42 |
43 | node-version: 20
44 |
45 | # > Starting April 26, 2021, all iOS and iPadOS apps submitted to the App Store must be built with Xcode 12 and the iOS 14 SDK.
46 | # Because of Apple's requirement, listed above, We will only be using the latest Xcode release for testing.
47 | # To customize these options, add "xcode-version" to the strategy matrix with its overriding value.
48 | default_xcode-version: latest-stable
49 |
50 | strategy:
51 | matrix:
52 | versions:
53 | - os-version: macos-12
54 | ios-version: 15.x
55 | xcode-version: 13.x
56 |
57 | - os-version: macos-14
58 | ios-version: 16.x
59 | xcode-version: 14.x
60 |
61 | - os-version: macos-14
62 | ios-version: 17.x
63 | xcode-version: 15.x
64 |
65 | steps:
66 | - uses: actions/checkout@v4
67 | - uses: actions/setup-node@v4
68 | with:
69 | node-version: ${{ env.node-version }}
70 | - uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd
71 | env:
72 | xcode-version: ${{ matrix.versions.xcode-version == '' && env.default_xcode-version || matrix.versions.xcode-version }}
73 | with:
74 | xcode-version: ${{ env.xcode-version }}
75 |
76 | - name: Run Environment Information
77 | run: |
78 | node --version
79 | npm --version
80 | xcodebuild -version
81 |
82 | - name: Run npm install
83 | run: |
84 | npm i -g cordova@latest ios-deploy@latest
85 | npm ci
86 |
87 | - name: Run paramedic install
88 | if: ${{ endswith(env.repo, '/cordova-paramedic') != true }}
89 | run: npm i -g github:apache/cordova-paramedic
90 |
91 | - name: Run paramedic tests
92 | env:
93 | test_config: 'ios-${{ matrix.versions.ios-version }}.config.json'
94 | # Generally, this should automatically work for cordova-paramedic & plugins. If the path is unique, this can be manually changed.
95 | test_plugin_path: ${{ endswith(env.repo, '/cordova-paramedic') && './spec/testable-plugin/' || './' }}
96 | paramedic: ${{ endswith(env.repo, '/cordova-paramedic') && 'node main.js' || 'cordova-paramedic' }}
97 | run: ${{ env.paramedic }} --config ./pr/local/${{ env.test_config }} --plugin ${{ env.test_plugin_path }}
98 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | name: Lint Test
19 |
20 | on:
21 | push:
22 | paths:
23 | - '**.js'
24 | - '.eslint*'
25 | - '.github/workflow/lint.yml'
26 | pull_request:
27 | paths:
28 | - '**.js'
29 | - '.eslint*'
30 | - '.github/workflow/lint.yml'
31 |
32 | jobs:
33 | test:
34 | name: Lint Test
35 | runs-on: ubuntu-latest
36 | env:
37 | node-version: 20
38 |
39 | steps:
40 | - uses: actions/checkout@v4
41 | - uses: actions/setup-node@v4
42 | with:
43 | node-version: ${{ env.node-version }}
44 |
45 | - name: Run Environment Information
46 | run: |
47 | node --version
48 | npm --version
49 |
50 | - name: Run npm install
51 | run: |
52 | npm ci
53 |
54 | - name: Run lint test
55 | run: |
56 | npm run lint
57 |
--------------------------------------------------------------------------------
/.github/workflows/release-notify.yml:
--------------------------------------------------------------------------------
1 | name: Close issue asking for release
2 |
3 | on:
4 | issues:
5 | types: [opened]
6 |
7 | jobs:
8 | action-test:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: niklasmerz/release-notify@master
12 | with:
13 | repo-token: ${{ secrets.GITHUB_TOKEN }}
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #If ignorance is bliss, then somebody knock the smile off my face
2 |
3 | *.csproj.user
4 | *.suo
5 | *.cache
6 | Thumbs.db
7 | *.DS_Store
8 |
9 | *.bak
10 | *.cache
11 | *.log
12 | *.swp
13 | *.user
14 |
15 | /node_modules/**
16 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .*
2 | tests
3 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://registry.npmjs.org
2 |
3 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 |
21 |
22 | # Contributing to Apache Cordova
23 |
24 | Anyone can contribute to Cordova. And we need your contributions.
25 |
26 | There are multiple ways to contribute: report bugs, improve the docs, and
27 | contribute code.
28 |
29 | For instructions on this, start with the
30 | [contribution overview](http://cordova.apache.org/contribute/).
31 |
32 | The details are explained there, but the important items are:
33 | - Check for Github issues that corresponds to your contribution and link or create them if necessary.
34 | - Run the tests so your patch doesn't break existing functionality.
35 |
36 | We look forward to your contributions!
37 |
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Apache Cordova
2 | Copyright 2012 The Apache Software Foundation
3 |
4 | This product includes software developed at
5 | The Apache Software Foundation (http://www.apache.org/).
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cordova-plugin-camera",
3 | "version": "8.0.1-dev",
4 | "description": "Cordova Camera Plugin",
5 | "types": "./types/index.d.ts",
6 | "cordova": {
7 | "id": "cordova-plugin-camera",
8 | "platforms": [
9 | "android",
10 | "ios",
11 | "browser"
12 | ]
13 | },
14 | "repository": "github:apache/cordova-plugin-camera",
15 | "bugs": "https://github.com/apache/cordova-plugin-camera/issues",
16 | "keywords": [
17 | "cordova",
18 | "camera",
19 | "ecosystem:cordova",
20 | "cordova-android",
21 | "cordova-ios",
22 | "cordova-browser"
23 | ],
24 | "scripts": {
25 | "test": "npm run lint",
26 | "lint": "eslint ."
27 | },
28 | "author": "Apache Software Foundation",
29 | "license": "Apache-2.0",
30 | "engines": {
31 | "cordovaDependencies": {
32 | "3.0.0": {
33 | "cordova-android": ">=6.3.0"
34 | },
35 | "4.1.0": {
36 | "cordova-android": ">=6.3.0",
37 | "cordova": ">=7.1.0"
38 | },
39 | "5.0.0": {
40 | "cordova-android": ">=9.0.0",
41 | "cordova-ios": ">=5.1.0",
42 | "cordova": ">=9.0.0"
43 | },
44 | "5.0.4-dev": {
45 | "cordova-android": "<10.0.0",
46 | "cordova-ios": ">=5.1.0",
47 | "cordova": ">=9.0.0"
48 | },
49 | "6.0.0": {
50 | "cordova-android": ">=10.0.0",
51 | "cordova-ios": ">=5.1.0",
52 | "cordova": ">=9.0.0"
53 | },
54 | "7.0.0": {
55 | "cordova-android": ">=12.0.0",
56 | "cordova-ios": ">=5.1.0",
57 | "cordova": ">=9.0.0"
58 | },
59 | "8.0.0": {
60 | "cordova-android": ">=12.0.0",
61 | "cordova-ios": ">=5.1.0",
62 | "cordova": ">=9.0.0"
63 | },
64 | "9.0.0": {
65 | "cordova": ">100"
66 | }
67 | }
68 | },
69 | "devDependencies": {
70 | "@cordova/eslint-config": "^5.1.0"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
25 | Camera
26 | Cordova Camera Plugin
27 | Apache 2.0
28 | cordova,camera
29 | https://github.com/apache/cordova-plugin-camera
30 | https://github.com/apache/cordova-plugin-camera/issues
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
63 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/src/android/ExifHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 | package org.apache.cordova.camera;
20 |
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 |
24 | import android.media.ExifInterface;
25 |
26 | public class ExifHelper {
27 | private String aperture = null;
28 | private String datetime = null;
29 | private String exposureTime = null;
30 | private String flash = null;
31 | private String focalLength = null;
32 | private String gpsAltitude = null;
33 | private String gpsAltitudeRef = null;
34 | private String gpsDateStamp = null;
35 | private String gpsLatitude = null;
36 | private String gpsLatitudeRef = null;
37 | private String gpsLongitude = null;
38 | private String gpsLongitudeRef = null;
39 | private String gpsProcessingMethod = null;
40 | private String gpsTimestamp = null;
41 | private String iso = null;
42 | private String make = null;
43 | private String model = null;
44 | private String orientation = null;
45 | private String whiteBalance = null;
46 |
47 | private ExifInterface inFile = null;
48 | private ExifInterface outFile = null;
49 |
50 | /**
51 | * The file before it is compressed
52 | *
53 | * @param filePath
54 | * @throws IOException
55 | */
56 | public void createInFile(String filePath) throws IOException {
57 | this.inFile = new ExifInterface(filePath);
58 | }
59 |
60 | /**
61 | * The file before it is compressed
62 | *
63 | * @param input
64 | * @throws IOException
65 | */
66 | public void createInFile(InputStream input) throws IOException {
67 | this.inFile = new ExifInterface(input);
68 | }
69 |
70 | /**
71 | * The file after it has been compressed
72 | *
73 | * @param filePath
74 | * @throws IOException
75 | */
76 | public void createOutFile(String filePath) throws IOException {
77 | this.outFile = new ExifInterface(filePath);
78 | }
79 |
80 | /**
81 | * Reads all the EXIF data from the input file.
82 | */
83 | public void readExifData() {
84 | this.aperture = inFile.getAttribute(ExifInterface.TAG_APERTURE);
85 | this.datetime = inFile.getAttribute(ExifInterface.TAG_DATETIME);
86 | this.exposureTime = inFile.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
87 | this.flash = inFile.getAttribute(ExifInterface.TAG_FLASH);
88 | this.focalLength = inFile.getAttribute(ExifInterface.TAG_FOCAL_LENGTH);
89 | this.gpsAltitude = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE);
90 | this.gpsAltitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF);
91 | this.gpsDateStamp = inFile.getAttribute(ExifInterface.TAG_GPS_DATESTAMP);
92 | this.gpsLatitude = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
93 | this.gpsLatitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
94 | this.gpsLongitude = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
95 | this.gpsLongitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
96 | this.gpsProcessingMethod = inFile.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD);
97 | this.gpsTimestamp = inFile.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
98 | this.iso = inFile.getAttribute(ExifInterface.TAG_ISO);
99 | this.make = inFile.getAttribute(ExifInterface.TAG_MAKE);
100 | this.model = inFile.getAttribute(ExifInterface.TAG_MODEL);
101 | this.orientation = inFile.getAttribute(ExifInterface.TAG_ORIENTATION);
102 | this.whiteBalance = inFile.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
103 | }
104 |
105 | /**
106 | * Writes the previously stored EXIF data to the output file.
107 | *
108 | * @throws IOException
109 | */
110 | public void writeExifData() throws IOException {
111 | // Don't try to write to a null file
112 | if (this.outFile == null) {
113 | return;
114 | }
115 |
116 | if (this.aperture != null) {
117 | this.outFile.setAttribute(ExifInterface.TAG_APERTURE, this.aperture);
118 | }
119 | if (this.datetime != null) {
120 | this.outFile.setAttribute(ExifInterface.TAG_DATETIME, this.datetime);
121 | }
122 | if (this.exposureTime != null) {
123 | this.outFile.setAttribute(ExifInterface.TAG_EXPOSURE_TIME, this.exposureTime);
124 | }
125 | if (this.flash != null) {
126 | this.outFile.setAttribute(ExifInterface.TAG_FLASH, this.flash);
127 | }
128 | if (this.focalLength != null) {
129 | this.outFile.setAttribute(ExifInterface.TAG_FOCAL_LENGTH, this.focalLength);
130 | }
131 | if (this.gpsAltitude != null) {
132 | this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE, this.gpsAltitude);
133 | }
134 | if (this.gpsAltitudeRef != null) {
135 | this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF, this.gpsAltitudeRef);
136 | }
137 | if (this.gpsDateStamp != null) {
138 | this.outFile.setAttribute(ExifInterface.TAG_GPS_DATESTAMP, this.gpsDateStamp);
139 | }
140 | if (this.gpsLatitude != null) {
141 | this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE, this.gpsLatitude);
142 | }
143 | if (this.gpsLatitudeRef != null) {
144 | this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, this.gpsLatitudeRef);
145 | }
146 | if (this.gpsLongitude != null) {
147 | this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, this.gpsLongitude);
148 | }
149 | if (this.gpsLongitudeRef != null) {
150 | this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, this.gpsLongitudeRef);
151 | }
152 | if (this.gpsProcessingMethod != null) {
153 | this.outFile.setAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD, this.gpsProcessingMethod);
154 | }
155 | if (this.gpsTimestamp != null) {
156 | this.outFile.setAttribute(ExifInterface.TAG_GPS_TIMESTAMP, this.gpsTimestamp);
157 | }
158 | if (this.iso != null) {
159 | this.outFile.setAttribute(ExifInterface.TAG_ISO, this.iso);
160 | }
161 | if (this.make != null) {
162 | this.outFile.setAttribute(ExifInterface.TAG_MAKE, this.make);
163 | }
164 | if (this.model != null) {
165 | this.outFile.setAttribute(ExifInterface.TAG_MODEL, this.model);
166 | }
167 | if (this.orientation != null) {
168 | this.outFile.setAttribute(ExifInterface.TAG_ORIENTATION, this.orientation);
169 | }
170 | if (this.whiteBalance != null) {
171 | this.outFile.setAttribute(ExifInterface.TAG_WHITE_BALANCE, this.whiteBalance);
172 | }
173 |
174 | this.outFile.saveAttributes();
175 | }
176 |
177 | public int getOrientation() {
178 | int o = Integer.parseInt(this.orientation);
179 |
180 | if (o == ExifInterface.ORIENTATION_NORMAL) {
181 | return 0;
182 | } else if (o == ExifInterface.ORIENTATION_ROTATE_90) {
183 | return 90;
184 | } else if (o == ExifInterface.ORIENTATION_ROTATE_180) {
185 | return 180;
186 | } else if (o == ExifInterface.ORIENTATION_ROTATE_270) {
187 | return 270;
188 | } else {
189 | return 0;
190 | }
191 | }
192 |
193 | public void resetOrientation() {
194 | this.orientation = "" + ExifInterface.ORIENTATION_NORMAL;
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/src/android/FileHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 | http://www.apache.org/licenses/LICENSE-2.0
10 | Unless required by applicable law or agreed to in writing,
11 | software distributed under the License is distributed on an
12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13 | KIND, either express or implied. See the License for the
14 | specific language governing permissions and limitations
15 | under the License.
16 | */
17 | package org.apache.cordova.camera;
18 |
19 | import android.annotation.SuppressLint;
20 | import android.content.ContentUris;
21 | import android.content.Context;
22 | import android.database.Cursor;
23 | import android.net.Uri;
24 | import android.os.Build;
25 | import android.os.Environment;
26 | import android.provider.DocumentsContract;
27 | import android.provider.MediaStore;
28 | import android.webkit.MimeTypeMap;
29 |
30 | import org.apache.cordova.CordovaInterface;
31 |
32 | import java.io.File;
33 | import java.io.FileInputStream;
34 | import java.io.IOException;
35 | import java.io.InputStream;
36 | import java.util.Locale;
37 |
38 | public class FileHelper {
39 | private static final String LOG_TAG = "FileUtils";
40 | private static final String _DATA = "_data";
41 |
42 | /**
43 | * Returns the real path of the given URI string.
44 | * If the given URI string represents a content:// URI, the real path is retrieved from the media store.
45 | *
46 | * @param uri the URI of the audio/image/video
47 | * @param cordova the current application context
48 | * @return the full path to the file
49 | */
50 | @SuppressWarnings("deprecation")
51 | public static String getRealPath(Uri uri, CordovaInterface cordova) {
52 | return FileHelper.getRealPathFromURI(cordova.getActivity(), uri);
53 | }
54 |
55 | /**
56 | * Returns the real path of the given URI.
57 | * If the given URI is a content:// URI, the real path is retrieved from the media store.
58 | *
59 | * @param uriString the URI string from which to obtain the input stream
60 | * @param cordova the current application context
61 | * @return the full path to the file
62 | */
63 | public static String getRealPath(String uriString, CordovaInterface cordova) {
64 | return FileHelper.getRealPath(Uri.parse(uriString), cordova);
65 | }
66 |
67 | @SuppressLint("NewApi")
68 | public static String getRealPathFromURI(final Context context, final Uri uri) {
69 | // DocumentProvider
70 | if (DocumentsContract.isDocumentUri(context, uri)) {
71 |
72 | // ExternalStorageProvider
73 | if (isExternalStorageDocument(uri)) {
74 | final String docId = DocumentsContract.getDocumentId(uri);
75 | final String[] split = docId.split(":");
76 | final String type = split[0];
77 |
78 | if ("primary".equalsIgnoreCase(type)) {
79 | return Environment.getExternalStorageDirectory() + "/" + split[1];
80 | }
81 |
82 | // TODO handle non-primary volumes
83 | }
84 | // DownloadsProvider
85 | else if (isDownloadsDocument(uri)) {
86 |
87 | final String id = DocumentsContract.getDocumentId(uri);
88 | if (id != null && id.length() > 0) {
89 | if (id.startsWith("raw:")) {
90 | return id.replaceFirst("raw:", "");
91 | }
92 | try {
93 | final Uri contentUri = ContentUris.withAppendedId(
94 | Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
95 |
96 | return getDataColumn(context, contentUri, null, null);
97 | } catch (NumberFormatException e) {
98 | return null;
99 | }
100 | } else {
101 | return null;
102 | }
103 | }
104 | // MediaProvider
105 | else if (isMediaDocument(uri)) {
106 | final String docId = DocumentsContract.getDocumentId(uri);
107 | final String[] split = docId.split(":");
108 | final String type = split[0];
109 |
110 | Uri contentUri = null;
111 | if ("image".equals(type)) {
112 | contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
113 | } else if ("video".equals(type)) {
114 | contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
115 | } else if ("audio".equals(type)) {
116 | contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
117 | }
118 |
119 | final String selection = "_id=?";
120 | final String[] selectionArgs = new String[] {
121 | split[1]
122 | };
123 |
124 | return getDataColumn(context, contentUri, selection, selectionArgs);
125 | }
126 | }
127 | // MediaStore (and general)
128 | else if ("content".equalsIgnoreCase(uri.getScheme())) {
129 |
130 | // Return the remote address
131 | if (isGooglePhotosUri(uri))
132 | return uri.getLastPathSegment();
133 |
134 | if (isFileProviderUri(context, uri))
135 | return getFileProviderPath(context, uri);
136 |
137 | return getDataColumn(context, uri, null, null);
138 | }
139 | // File
140 | else if ("file".equalsIgnoreCase(uri.getScheme())) {
141 | return uri.getPath();
142 | }
143 |
144 | return null;
145 | }
146 |
147 | /**
148 | * Returns an input stream based on given URI string.
149 | *
150 | * @param uriString the URI string from which to obtain the input stream
151 | * @param cordova the current application context
152 | * @return an input stream into the data at the given URI or null if given an invalid URI string
153 | * @throws IOException
154 | */
155 | public static InputStream getInputStreamFromUriString(String uriString, CordovaInterface cordova)
156 | throws IOException {
157 | InputStream returnValue = null;
158 | if (uriString.startsWith("content")) {
159 | Uri uri = Uri.parse(uriString);
160 | returnValue = cordova.getActivity().getContentResolver().openInputStream(uri);
161 | } else if (uriString.startsWith("file://")) {
162 | int question = uriString.indexOf("?");
163 | if (question > -1) {
164 | uriString = uriString.substring(0, question);
165 | }
166 |
167 | if (uriString.startsWith("file:///android_asset/")) {
168 | Uri uri = Uri.parse(uriString);
169 | String relativePath = uri.getPath().substring(15);
170 | returnValue = cordova.getActivity().getAssets().open(relativePath);
171 | } else {
172 | // might still be content so try that first
173 | try {
174 | returnValue = cordova.getActivity().getContentResolver().openInputStream(Uri.parse(uriString));
175 | } catch (Exception e) {
176 | returnValue = null;
177 | }
178 | if (returnValue == null) {
179 | returnValue = new FileInputStream(getRealPath(uriString, cordova));
180 | }
181 | }
182 | } else {
183 | returnValue = new FileInputStream(uriString);
184 | }
185 | return returnValue;
186 | }
187 |
188 | /**
189 | * Removes the "file://" prefix from the given URI string, if applicable.
190 | * If the given URI string doesn't have a "file://" prefix, it is returned unchanged.
191 | *
192 | * @param uriString the URI string to operate on
193 | * @return a path without the "file://" prefix
194 | */
195 | public static String stripFileProtocol(String uriString) {
196 |
197 | if (uriString.startsWith("file://")) {
198 | uriString = uriString.substring(7);
199 | }
200 | return uriString;
201 | }
202 |
203 | public static String getMimeTypeForExtension(String path) {
204 | String extension = path;
205 | int lastDot = extension.lastIndexOf('.');
206 | if (lastDot != -1) {
207 | extension = extension.substring(lastDot + 1);
208 | }
209 | // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
210 | extension = extension.toLowerCase(Locale.getDefault());
211 | if (extension.equals("3ga")) {
212 | return "audio/3gpp";
213 | }
214 | return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
215 | }
216 |
217 | /**
218 | * Returns the mime type of the data specified by the given URI string.
219 | *
220 | * @param uriString the URI string of the data
221 | * @return the mime type of the specified data
222 | */
223 | public static String getMimeType(String uriString, CordovaInterface cordova) {
224 | String mimeType;
225 |
226 | Uri uri = Uri.parse(uriString);
227 | if (uriString.startsWith("content://")) {
228 | mimeType = cordova.getActivity().getContentResolver().getType(uri);
229 | } else {
230 | mimeType = getMimeTypeForExtension(uri.getPath());
231 | }
232 |
233 | return mimeType;
234 | }
235 |
236 | /**
237 | * Get the value of the data column for this Uri. This is useful for
238 | * MediaStore Uris, and other file-based ContentProviders.
239 | *
240 | * @param context The context.
241 | * @param uri The Uri to query.
242 | * @param selection (Optional) Filter used in the query.
243 | * @param selectionArgs (Optional) Selection arguments used in the query.
244 | * @return The value of the _data column, which is typically a file path.
245 | * @author paulburke
246 | */
247 | public static String getDataColumn(Context context, Uri uri, String selection,
248 | String[] selectionArgs) {
249 |
250 | Cursor cursor = null;
251 | final String column = "_data";
252 | final String[] projection = {
253 | column
254 | };
255 |
256 | try {
257 | cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
258 | null);
259 | if (cursor != null && cursor.moveToFirst()) {
260 |
261 | final int column_index = cursor.getColumnIndexOrThrow(column);
262 | return cursor.getString(column_index);
263 | }
264 | } catch (Exception e) {
265 | return null;
266 | } finally {
267 | if (cursor != null)
268 | cursor.close();
269 | }
270 | return null;
271 | }
272 |
273 | /**
274 | * @param uri The Uri to check.
275 | * @return Whether the Uri authority is ExternalStorageProvider.
276 | * @author paulburke
277 | */
278 | public static boolean isExternalStorageDocument(Uri uri) {
279 | return "com.android.externalstorage.documents".equals(uri.getAuthority());
280 | }
281 |
282 | /**
283 | * @param uri The Uri to check.
284 | * @return Whether the Uri authority is DownloadsProvider.
285 | * @author paulburke
286 | */
287 | public static boolean isDownloadsDocument(Uri uri) {
288 | return "com.android.providers.downloads.documents".equals(uri.getAuthority());
289 | }
290 |
291 | /**
292 | * @param uri The Uri to check.
293 | * @return Whether the Uri authority is MediaProvider.
294 | * @author paulburke
295 | */
296 | public static boolean isMediaDocument(Uri uri) {
297 | return "com.android.providers.media.documents".equals(uri.getAuthority());
298 | }
299 |
300 | /**
301 | * @param uri The Uri to check.
302 | * @return Whether the Uri authority is Google Photos.
303 | */
304 | public static boolean isGooglePhotosUri(Uri uri) {
305 | return "com.google.android.apps.photos.content".equals(uri.getAuthority());
306 | }
307 |
308 | /**
309 | * @param context The Application context
310 | * @param uri The Uri is checked by functions
311 | * @return Whether the Uri authority is FileProvider
312 | */
313 | public static boolean isFileProviderUri(final Context context, final Uri uri) {
314 | final String packageName = context.getPackageName();
315 | final String authority = new StringBuilder(packageName).append(".provider").toString();
316 | return authority.equals(uri.getAuthority());
317 | }
318 |
319 | /**
320 | * @param context The Application context
321 | * @param uri The Uri is checked by functions
322 | * @return File path or null if file is missing
323 | */
324 | public static String getFileProviderPath(final Context context, final Uri uri)
325 | {
326 | final File appDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
327 | final File file = new File(appDir, uri.getLastPathSegment());
328 | return file.exists() ? file.toString(): null;
329 | }
330 |
331 | }
332 |
--------------------------------------------------------------------------------
/src/android/FileProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 | package org.apache.cordova.camera;
20 |
21 | public class FileProvider extends androidx.core.content.FileProvider {}
22 |
--------------------------------------------------------------------------------
/src/android/GalleryPathVO.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 | package org.apache.cordova.camera;
20 |
21 | public class GalleryPathVO {
22 | private final String galleryPath;
23 | private String picturesDirectory;
24 | private String galleryFileName;
25 |
26 | public GalleryPathVO(String picturesDirectory, String galleryFileName) {
27 | this.picturesDirectory = picturesDirectory;
28 | this.galleryFileName = galleryFileName;
29 | this.galleryPath = this.picturesDirectory + "/" + this.galleryFileName;
30 | }
31 |
32 | public String getGalleryPath() {
33 | return galleryPath;
34 | }
35 |
36 | public String getPicturesDirectory() {
37 | return picturesDirectory;
38 | }
39 |
40 | public String getGalleryFileName() {
41 | return galleryFileName;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/android/xml/camera_provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/browser/CameraProxy.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | const HIGHEST_POSSIBLE_Z_INDEX = 2147483647;
23 |
24 | function takePicture (success, error, opts) {
25 | if (opts && opts[2] === 1) {
26 | capture(success, error, opts);
27 | } else {
28 | const input = document.createElement('input');
29 | input.style.position = 'relative';
30 | input.style.zIndex = HIGHEST_POSSIBLE_Z_INDEX;
31 | input.className = 'cordova-camera-select';
32 | input.type = 'file';
33 | input.name = 'files[]';
34 |
35 | input.onchange = function (inputEvent) {
36 | const reader = new FileReader(); /* eslint no-undef : 0 */
37 | reader.onload = function (readerEvent) {
38 | input.parentNode.removeChild(input);
39 |
40 | const imageData = readerEvent.target.result;
41 |
42 | return success(imageData);
43 | };
44 |
45 | reader.readAsDataURL(inputEvent.target.files[0]);
46 | };
47 |
48 | document.body.appendChild(input);
49 | }
50 | }
51 |
52 | function capture (success, errorCallback, opts) {
53 | let localMediaStream;
54 | let targetWidth = opts[3];
55 | let targetHeight = opts[4];
56 |
57 | targetWidth = targetWidth === -1 ? 320 : targetWidth;
58 | targetHeight = targetHeight === -1 ? 240 : targetHeight;
59 |
60 | const video = document.createElement('video');
61 | const button = document.createElement('button');
62 | const parent = document.createElement('div');
63 | parent.style.position = 'relative';
64 | parent.style.zIndex = HIGHEST_POSSIBLE_Z_INDEX;
65 | parent.className = 'cordova-camera-capture';
66 | parent.appendChild(video);
67 | parent.appendChild(button);
68 |
69 | video.width = targetWidth;
70 | video.height = targetHeight;
71 | button.innerHTML = 'Capture!';
72 |
73 | button.onclick = function () {
74 | // create a canvas and capture a frame from video stream
75 | const canvas = document.createElement('canvas');
76 | canvas.width = targetWidth;
77 | canvas.height = targetHeight;
78 | canvas.getContext('2d').drawImage(video, 0, 0, targetWidth, targetHeight);
79 |
80 | // convert image stored in canvas to base64 encoded image
81 | const imageData = canvas.toDataURL('image/png');
82 |
83 | // stop video stream, remove video and button.
84 | // Note that MediaStream.stop() is deprecated as of Chrome 47.
85 | if (localMediaStream.stop) {
86 | localMediaStream.stop();
87 | } else {
88 | localMediaStream.getTracks().forEach(function (track) {
89 | track.stop();
90 | });
91 | }
92 | parent.parentNode.removeChild(parent);
93 |
94 | return success(imageData);
95 | };
96 |
97 | navigator.getUserMedia = navigator.getUserMedia ||
98 | navigator.webkitGetUserMedia ||
99 | navigator.mozGetUserMedia ||
100 | navigator.msGetUserMedia;
101 |
102 | const successCallback = function (stream) {
103 | localMediaStream = stream;
104 | if ('srcObject' in video) {
105 | video.srcObject = localMediaStream;
106 | } else {
107 | video.src = window.URL.createObjectURL(localMediaStream);
108 | }
109 | video.play();
110 | document.body.appendChild(parent);
111 | };
112 |
113 | if (navigator.mediaDevices.getUserMedia) {
114 | navigator.mediaDevices.getUserMedia({ video: true, audio: false })
115 | .then(successCallback)
116 | .catch(errorCallback);
117 | } else if (navigator.getUserMedia) {
118 | navigator.getUserMedia({ video: true, audio: false }, successCallback, errorCallback);
119 | } else {
120 | alert('Browser does not support camera :(');
121 | }
122 | }
123 |
124 | module.exports = {
125 | takePicture,
126 | cleanup: function () {}
127 | };
128 |
129 | require('cordova/exec/proxy').add('Camera', module.exports);
130 |
--------------------------------------------------------------------------------
/src/ios/CDVCamera.h:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | #import
21 | #import
22 | #import
23 | #import
24 |
25 | enum CDVDestinationType {
26 | DestinationTypeDataUrl = 0,
27 | DestinationTypeFileUri
28 | };
29 | typedef NSUInteger CDVDestinationType;
30 |
31 | enum CDVEncodingType {
32 | EncodingTypeJPEG = 0,
33 | EncodingTypePNG
34 | };
35 | typedef NSUInteger CDVEncodingType;
36 |
37 | enum CDVMediaType {
38 | MediaTypePicture = 0,
39 | MediaTypeVideo,
40 | MediaTypeAll
41 | };
42 | typedef NSUInteger CDVMediaType;
43 |
44 | @interface CDVPictureOptions : NSObject
45 |
46 | @property (strong) NSNumber* quality;
47 | @property (assign) CDVDestinationType destinationType;
48 | @property (assign) UIImagePickerControllerSourceType sourceType;
49 | @property (assign) CGSize targetSize;
50 | @property (assign) CDVEncodingType encodingType;
51 | @property (assign) CDVMediaType mediaType;
52 | @property (assign) BOOL allowsEditing;
53 | @property (assign) BOOL correctOrientation;
54 | @property (assign) BOOL saveToPhotoAlbum;
55 | @property (strong) NSDictionary* popoverOptions;
56 | @property (assign) UIImagePickerControllerCameraDevice cameraDirection;
57 |
58 | @property (assign) BOOL popoverSupported;
59 | @property (assign) BOOL usesGeolocation;
60 | @property (assign) BOOL cropToSize;
61 |
62 | + (instancetype) createFromTakePictureArguments:(CDVInvokedUrlCommand*)command;
63 |
64 | @end
65 |
66 | @interface CDVCameraPicker : UIImagePickerController
67 |
68 | @property (strong) CDVPictureOptions* pictureOptions;
69 |
70 | @property (copy) NSString* callbackId;
71 | @property (copy) NSString* postUrl;
72 | @property (strong) UIPopoverController* pickerPopoverController;
73 | @property (assign) BOOL cropToSize;
74 | @property (strong) UIView* webView;
75 |
76 | + (instancetype) createFromPictureOptions:(CDVPictureOptions*)options;
77 |
78 | @end
79 |
80 | // ======================================================================= //
81 |
82 | @interface CDVCamera : CDVPlugin
86 | {}
87 |
88 | @property (strong) CDVCameraPicker* pickerController;
89 | @property (strong) NSMutableDictionary *metadata;
90 | @property (strong, nonatomic) CLLocationManager *locationManager;
91 | @property (strong) NSData* data;
92 |
93 | /*
94 | * getPicture
95 | *
96 | * arguments:
97 | * 1: this is the javascript function that will be called with the results, the first parameter passed to the
98 | * javascript function is the picture as a Base64 encoded string
99 | * 2: this is the javascript function to be called if there was an error
100 | * options:
101 | * quality: integer between 1 and 100
102 | */
103 | - (void)takePicture:(CDVInvokedUrlCommand*)command;
104 | - (void)cleanup:(CDVInvokedUrlCommand*)command;
105 | - (void)repositionPopover:(CDVInvokedUrlCommand*)command;
106 |
107 | - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info;
108 | - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo;
109 | - (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker;
110 | - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
111 |
112 | - (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation;
113 | - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;
114 |
115 | @end
116 |
--------------------------------------------------------------------------------
/src/ios/CDVExif.h:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | #ifndef CordovaLib_ExifData_h
21 | #define CordovaLib_ExifData_h
22 |
23 | // exif data types
24 | typedef enum exifDataTypes {
25 | EDT_UBYTE = 1, // 8 bit unsigned integer
26 | EDT_ASCII_STRING, // 8 bits containing 7 bit ASCII code, null terminated
27 | EDT_USHORT, // 16 bit unsigned integer
28 | EDT_ULONG, // 32 bit unsigned integer
29 | EDT_URATIONAL, // 2 longs, first is numerator and second is denominator
30 | EDT_SBYTE,
31 | EDT_UNDEFINED, // 8 bits
32 | EDT_SSHORT,
33 | EDT_SLONG, // 32bit signed integer (2's complement)
34 | EDT_SRATIONAL, // 2 SLONGS, first long is numerator, second is denominator
35 | EDT_SINGLEFLOAT,
36 | EDT_DOUBLEFLOAT
37 | } ExifDataTypes;
38 |
39 | // maps integer code for exif data types to width in bytes
40 | static const int DataTypeToWidth[] = {1,1,2,4,8,1,1,2,4,8,4,8};
41 |
42 | static const int RECURSE_HORIZON = 8;
43 | #endif
44 |
--------------------------------------------------------------------------------
/src/ios/CDVJpegHeaderWriter.h:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | #import
21 |
22 | @interface CDVJpegHeaderWriter : NSObject {
23 | NSDictionary * SubIFDTagFormatDict;
24 | NSDictionary * IFD0TagFormatDict;
25 | }
26 |
27 | - (NSData*) spliceExifBlockIntoJpeg: (NSData*) jpegdata
28 | withExifBlock: (NSString*) exifstr;
29 | - (NSString*) createExifAPP1 : (NSDictionary*) datadict;
30 | - (NSString*) formattedHexStringFromDecimalNumber: (NSNumber*) numb
31 | withPlaces: (NSNumber*) width;
32 | - (NSString*) formatNumberWithLeadingZeroes: (NSNumber*) numb
33 | withPlaces: (NSNumber*) places;
34 | - (NSString*) decimalToUnsignedRational: (NSNumber*) numb
35 | withResultNumerator: (NSNumber**) numerator
36 | withResultDenominator: (NSNumber**) denominator;
37 | - (void) continuedFraction: (double) val
38 | withFractionList: (NSMutableArray*) fractionlist
39 | withHorizon: (int) horizon;
40 | //- (void) expandContinuedFraction: (NSArray*) fractionlist;
41 | - (void) splitDouble: (double) val
42 | withIntComponent: (int*) rightside
43 | withFloatRemainder: (double*) leftside;
44 | - (NSString*) formatRationalWithNumerator: (NSNumber*) numerator
45 | withDenominator: (NSNumber*) denominator
46 | asSigned: (Boolean) signedFlag;
47 | - (NSString*) hexStringFromData : (NSData*) data;
48 | - (NSNumber*) numericFromHexString : (NSString *) hexstring;
49 |
50 | /*
51 | - (void) readExifMetaData : (NSData*) imgdata;
52 | - (void) spliceImageData : (NSData*) imgdata withExifData: (NSDictionary*) exifdata;
53 | - (void) locateExifMetaData : (NSData*) imgdata;
54 | - (NSString*) createExifAPP1 : (NSDictionary*) datadict;
55 | - (void) createExifDataString : (NSDictionary*) datadict;
56 | - (NSString*) createDataElement : (NSString*) element
57 | withElementData: (NSString*) data
58 | withExternalDataBlock: (NSDictionary*) memblock;
59 | - (NSString*) hexStringFromData : (NSData*) data;
60 | - (NSNumber*) numericFromHexString : (NSString *) hexstring;
61 | */
62 | @end
63 |
--------------------------------------------------------------------------------
/src/ios/UIImage+CropScaleOrientation.h:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | #import
21 |
22 | @interface UIImage (CropScaleOrientation)
23 |
24 | - (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize;
25 | - (UIImage*)imageCorrectedForCaptureOrientation;
26 | - (UIImage*)imageCorrectedForCaptureOrientation:(UIImageOrientation)imageOrientation;
27 | - (UIImage*)imageByScalingNotCroppingForSize:(CGSize)targetSize;
28 |
29 | @end
--------------------------------------------------------------------------------
/src/ios/UIImage+CropScaleOrientation.m:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | #import "UIImage+CropScaleOrientation.h"
21 |
22 | @implementation UIImage (CropScaleOrientation)
23 |
24 | - (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize
25 | {
26 | UIImage* sourceImage = self;
27 | UIImage* newImage = nil;
28 | CGSize imageSize = sourceImage.size;
29 | CGFloat width = imageSize.width;
30 | CGFloat height = imageSize.height;
31 | CGFloat targetWidth = targetSize.width;
32 | CGFloat targetHeight = targetSize.height;
33 | CGFloat scaleFactor = 0.0;
34 | CGFloat scaledWidth = targetWidth;
35 | CGFloat scaledHeight = targetHeight;
36 | CGPoint thumbnailPoint = CGPointMake(0.0, 0.0);
37 |
38 | if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
39 | CGFloat widthFactor = targetWidth / width;
40 | CGFloat heightFactor = targetHeight / height;
41 |
42 | if (widthFactor > heightFactor) {
43 | scaleFactor = widthFactor; // scale to fit height
44 | } else {
45 | scaleFactor = heightFactor; // scale to fit width
46 | }
47 | scaledWidth = width * scaleFactor;
48 | scaledHeight = height * scaleFactor;
49 |
50 | // center the image
51 | if (widthFactor > heightFactor) {
52 | thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
53 | } else if (widthFactor < heightFactor) {
54 | thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
55 | }
56 | }
57 |
58 | UIGraphicsBeginImageContext(targetSize); // this will crop
59 |
60 | CGRect thumbnailRect = CGRectZero;
61 | thumbnailRect.origin = thumbnailPoint;
62 | thumbnailRect.size.width = scaledWidth;
63 | thumbnailRect.size.height = scaledHeight;
64 |
65 | [sourceImage drawInRect:thumbnailRect];
66 |
67 | newImage = UIGraphicsGetImageFromCurrentImageContext();
68 | if (newImage == nil) {
69 | NSLog(@"could not scale image");
70 | }
71 |
72 | // pop the context to get back to the default
73 | UIGraphicsEndImageContext();
74 | return newImage;
75 | }
76 |
77 | - (UIImage*)imageCorrectedForCaptureOrientation:(UIImageOrientation)imageOrientation
78 | {
79 | float rotation_radians = 0;
80 | bool perpendicular = false;
81 |
82 | switch (imageOrientation) {
83 | case UIImageOrientationUp :
84 | rotation_radians = 0.0;
85 | break;
86 |
87 | case UIImageOrientationDown:
88 | rotation_radians = M_PI; // don't be scared of radians, if you're reading this, you're good at math
89 | break;
90 |
91 | case UIImageOrientationRight:
92 | rotation_radians = M_PI_2;
93 | perpendicular = true;
94 | break;
95 |
96 | case UIImageOrientationLeft:
97 | rotation_radians = -M_PI_2;
98 | perpendicular = true;
99 | break;
100 |
101 | default:
102 | break;
103 | }
104 |
105 | UIGraphicsBeginImageContext(CGSizeMake(self.size.width, self.size.height));
106 | CGContextRef context = UIGraphicsGetCurrentContext();
107 |
108 | // Rotate around the center point
109 | CGContextTranslateCTM(context, self.size.width / 2, self.size.height / 2);
110 | CGContextRotateCTM(context, rotation_radians);
111 |
112 | CGContextScaleCTM(context, 1.0, -1.0);
113 | float width = perpendicular ? self.size.height : self.size.width;
114 | float height = perpendicular ? self.size.width : self.size.height;
115 | CGContextDrawImage(context, CGRectMake(-width / 2, -height / 2, width, height), [self CGImage]);
116 |
117 | // Move the origin back since the rotation might've change it (if its 90 degrees)
118 | if (perpendicular) {
119 | CGContextTranslateCTM(context, -self.size.height / 2, -self.size.width / 2);
120 | }
121 |
122 | UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
123 | UIGraphicsEndImageContext();
124 | return newImage;
125 | }
126 |
127 | - (UIImage*)imageCorrectedForCaptureOrientation
128 | {
129 | return [self imageCorrectedForCaptureOrientation:[self imageOrientation]];
130 | }
131 |
132 | - (UIImage*)imageByScalingNotCroppingForSize:(CGSize)targetSize
133 | {
134 | UIImage* sourceImage = self;
135 | UIImage* newImage = nil;
136 | CGSize imageSize = sourceImage.size;
137 | CGFloat width = imageSize.width;
138 | CGFloat height = imageSize.height;
139 | CGFloat targetWidth = targetSize.width;
140 | CGFloat targetHeight = targetSize.height;
141 | CGFloat scaleFactor = 0.0;
142 | CGSize scaledSize = targetSize;
143 |
144 | if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
145 | CGFloat widthFactor = targetWidth / width;
146 | CGFloat heightFactor = targetHeight / height;
147 |
148 | // opposite comparison to imageByScalingAndCroppingForSize in order to contain the image within the given bounds
149 | if (widthFactor > heightFactor) {
150 | scaleFactor = heightFactor; // scale to fit height
151 | } else {
152 | scaleFactor = widthFactor; // scale to fit width
153 | }
154 | scaledSize = CGSizeMake(MIN(width * scaleFactor, targetWidth), MIN(height * scaleFactor, targetHeight));
155 | }
156 |
157 | // If the pixels are floats, it causes a white line in iOS8 and probably other versions too
158 | scaledSize.width = (int)scaledSize.width;
159 | scaledSize.height = (int)scaledSize.height;
160 |
161 | UIGraphicsBeginImageContext(scaledSize); // this will resize
162 |
163 | [sourceImage drawInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height)];
164 |
165 | newImage = UIGraphicsGetImageFromCurrentImageContext();
166 | if (newImage == nil) {
167 | NSLog(@"could not scale image");
168 | }
169 |
170 | // pop the context to get back to the default
171 | UIGraphicsEndImageContext();
172 | return newImage;
173 | }
174 |
175 | @end
176 |
--------------------------------------------------------------------------------
/tests/ios/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/tests/ios/CDVCameraTest.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/tests/ios/CDVCameraTest.xcworkspace/xcshareddata/CDVCameraTest.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 6BE9AD73-1B9F-4362-98D7-DC631BEC6185
9 | IDESourceControlProjectName
10 | CDVCameraTest
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 729B5706E7BAF4E9EE7AEE3C003A08107411AB7C
14 | github.com:shazron/cordova-plugin-camera.git
15 |
16 | IDESourceControlProjectPath
17 | tests/ios/CDVCameraTest.xcworkspace
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | 729B5706E7BAF4E9EE7AEE3C003A08107411AB7C
21 | ../../..
22 |
23 | IDESourceControlProjectURL
24 | github.com:shazron/cordova-plugin-camera.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | 729B5706E7BAF4E9EE7AEE3C003A08107411AB7C
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | 729B5706E7BAF4E9EE7AEE3C003A08107411AB7C
36 | IDESourceControlWCCName
37 | cordova-plugin-camera
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/tests/ios/CDVCameraTest.xcworkspace/xcshareddata/xcschemes/CordovaLib.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
60 |
61 |
67 |
68 |
69 |
70 |
72 |
73 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/tests/ios/CDVCameraTest/CDVCameraLibTests/CameraTest.m:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | #import
21 | #import
22 | #import "CDVCamera.h"
23 | #import "UIImage+CropScaleOrientation.h"
24 | #import
25 |
26 |
27 | @interface CameraTest : XCTestCase
28 |
29 | @property (nonatomic, strong) CDVCamera* plugin;
30 |
31 | @end
32 |
33 | @interface CDVCamera ()
34 |
35 | // expose private interface
36 | - (NSData*)processImage:(UIImage*)image info:(NSDictionary*)info options:(CDVPictureOptions*)options;
37 | - (UIImage*)retrieveImage:(NSDictionary*)info options:(CDVPictureOptions*)options;
38 | - (CDVPluginResult*)resultForImage:(CDVPictureOptions*)options info:(NSDictionary*)info;
39 | - (CDVPluginResult*)resultForVideo:(NSDictionary*)info;
40 |
41 | @end
42 |
43 | @implementation CameraTest
44 |
45 | - (void)setUp {
46 | [super setUp];
47 | // Put setup code here. This method is called before the invocation of each test method in the class.
48 |
49 | self.plugin = [[CDVCamera alloc] init];
50 | }
51 |
52 | - (void)tearDown {
53 | // Put teardown code here. This method is called after the invocation of each test method in the class.
54 | [super tearDown];
55 | }
56 |
57 | - (void) testPictureOptionsCreate
58 | {
59 | NSArray* args;
60 | CDVPictureOptions* options;
61 | NSDictionary* popoverOptions;
62 |
63 | // No arguments, check whether the defaults are set
64 | args = @[];
65 | CDVInvokedUrlCommand* command = [[CDVInvokedUrlCommand alloc] initWithArguments:args callbackId:@"dummy" className:@"myclassname" methodName:@"mymethodname"];
66 |
67 | options = [CDVPictureOptions createFromTakePictureArguments:command];
68 |
69 | XCTAssertEqual([options.quality intValue], 50);
70 | XCTAssertEqual(options.destinationType, (int)DestinationTypeFileUri);
71 | XCTAssertEqual(options.sourceType, (int)UIImagePickerControllerSourceTypeCamera);
72 | XCTAssertEqual(options.targetSize.width, 0);
73 | XCTAssertEqual(options.targetSize.height, 0);
74 | XCTAssertEqual(options.encodingType, (int)EncodingTypeJPEG);
75 | XCTAssertEqual(options.mediaType, (int)MediaTypePicture);
76 | XCTAssertEqual(options.allowsEditing, NO);
77 | XCTAssertEqual(options.correctOrientation, NO);
78 | XCTAssertEqual(options.saveToPhotoAlbum, NO);
79 | XCTAssertEqualObjects(options.popoverOptions, nil);
80 | XCTAssertEqual(options.cameraDirection, (int)UIImagePickerControllerCameraDeviceRear);
81 | XCTAssertEqual(options.popoverSupported, NO);
82 | XCTAssertEqual(options.usesGeolocation, NO);
83 |
84 | // Set each argument, check whether they are set. different from defaults
85 | popoverOptions = @{ @"x" : @1, @"y" : @2, @"width" : @3, @"height" : @4, @"popoverWidth": @200, @"popoverHeight": @300 };
86 |
87 | args = @[
88 | @(49),
89 | @(DestinationTypeDataUrl),
90 | @(UIImagePickerControllerSourceTypePhotoLibrary),
91 | @(120),
92 | @(240),
93 | @(EncodingTypePNG),
94 | @(MediaTypeVideo),
95 | @YES,
96 | @YES,
97 | @YES,
98 | popoverOptions,
99 | @(UIImagePickerControllerCameraDeviceFront),
100 | ];
101 |
102 | command = [[CDVInvokedUrlCommand alloc] initWithArguments:args callbackId:@"dummy" className:@"myclassname" methodName:@"mymethodname"];
103 | options = [CDVPictureOptions createFromTakePictureArguments:command];
104 |
105 | XCTAssertEqual([options.quality intValue], 49);
106 | XCTAssertEqual(options.destinationType, (int)DestinationTypeDataUrl);
107 | XCTAssertEqual(options.sourceType, (int)UIImagePickerControllerSourceTypePhotoLibrary);
108 | XCTAssertEqual(options.targetSize.width, 120);
109 | XCTAssertEqual(options.targetSize.height, 240);
110 | XCTAssertEqual(options.encodingType, (int)EncodingTypePNG);
111 | XCTAssertEqual(options.mediaType, (int)MediaTypeVideo);
112 | XCTAssertEqual(options.allowsEditing, YES);
113 | XCTAssertEqual(options.correctOrientation, YES);
114 | XCTAssertEqual(options.saveToPhotoAlbum, YES);
115 | XCTAssertEqualObjects(options.popoverOptions, popoverOptions);
116 | XCTAssertEqual(options.cameraDirection, (int)UIImagePickerControllerCameraDeviceFront);
117 | XCTAssertEqual(options.popoverSupported, NO);
118 | XCTAssertEqual(options.usesGeolocation, NO);
119 | }
120 |
121 | - (void) testCameraPickerCreate
122 | {
123 | NSDictionary* popoverOptions;
124 | NSArray* args;
125 | CDVPictureOptions* pictureOptions;
126 | CDVCameraPicker* picker;
127 |
128 | // Souce is Camera, and image type
129 |
130 | popoverOptions = @{ @"x" : @1, @"y" : @2, @"width" : @3, @"height" : @4, @"popoverWidth": @200, @"popoverHeight": @300 };
131 | args = @[
132 | @(49),
133 | @(DestinationTypeDataUrl),
134 | @(UIImagePickerControllerSourceTypeCamera),
135 | @(120),
136 | @(240),
137 | @(EncodingTypePNG),
138 | @(MediaTypeAll),
139 | @YES,
140 | @YES,
141 | @YES,
142 | popoverOptions,
143 | @(UIImagePickerControllerCameraDeviceFront),
144 | ];
145 |
146 | CDVInvokedUrlCommand* command = [[CDVInvokedUrlCommand alloc] initWithArguments:args callbackId:@"dummy" className:@"myclassname" methodName:@"mymethodname"];
147 | pictureOptions = [CDVPictureOptions createFromTakePictureArguments:command];
148 |
149 | if ([UIImagePickerController isSourceTypeAvailable:pictureOptions.sourceType]) {
150 | picker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
151 |
152 | XCTAssertEqualObjects(picker.pictureOptions, pictureOptions);
153 |
154 | XCTAssertEqual(picker.sourceType, pictureOptions.sourceType);
155 | XCTAssertEqual(picker.allowsEditing, pictureOptions.allowsEditing);
156 | XCTAssertEqualObjects(picker.mediaTypes, @[(NSString*)kUTTypeImage]);
157 | XCTAssertEqual(picker.cameraDevice, pictureOptions.cameraDirection);
158 | }
159 |
160 | // Souce is not Camera, and all media types
161 |
162 | args = @[
163 | @(49),
164 | @(DestinationTypeDataUrl),
165 | @(UIImagePickerControllerSourceTypePhotoLibrary),
166 | @(120),
167 | @(240),
168 | @(EncodingTypePNG),
169 | @(MediaTypeAll),
170 | @YES,
171 | @YES,
172 | @YES,
173 | popoverOptions,
174 | @(UIImagePickerControllerCameraDeviceFront),
175 | ];
176 |
177 | command = [[CDVInvokedUrlCommand alloc] initWithArguments:args callbackId:@"dummy" className:@"myclassname" methodName:@"mymethodname"];
178 | pictureOptions = [CDVPictureOptions createFromTakePictureArguments:command];
179 |
180 | if ([UIImagePickerController isSourceTypeAvailable:pictureOptions.sourceType]) {
181 | picker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
182 |
183 | XCTAssertEqualObjects(picker.pictureOptions, pictureOptions);
184 |
185 | XCTAssertEqual(picker.sourceType, pictureOptions.sourceType);
186 | XCTAssertEqual(picker.allowsEditing, pictureOptions.allowsEditing);
187 | XCTAssertEqualObjects(picker.mediaTypes, [UIImagePickerController availableMediaTypesForSourceType:picker.sourceType]);
188 | }
189 |
190 | // Souce is not Camera, and either Image or Movie media type
191 |
192 | args = @[
193 | @(49),
194 | @(DestinationTypeDataUrl),
195 | @(UIImagePickerControllerSourceTypePhotoLibrary),
196 | @(120),
197 | @(240),
198 | @(EncodingTypePNG),
199 | @(MediaTypeVideo),
200 | @YES,
201 | @YES,
202 | @YES,
203 | popoverOptions,
204 | @(UIImagePickerControllerCameraDeviceFront),
205 | ];
206 |
207 | command = [[CDVInvokedUrlCommand alloc] initWithArguments:args callbackId:@"dummy" className:@"myclassname" methodName:@"mymethodname"];
208 | pictureOptions = [CDVPictureOptions createFromTakePictureArguments:command];
209 |
210 | if ([UIImagePickerController isSourceTypeAvailable:pictureOptions.sourceType]) {
211 | picker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
212 |
213 | XCTAssertEqualObjects(picker.pictureOptions, pictureOptions);
214 |
215 | XCTAssertEqual(picker.sourceType, pictureOptions.sourceType);
216 | XCTAssertEqual(picker.allowsEditing, pictureOptions.allowsEditing);
217 | XCTAssertEqualObjects(picker.mediaTypes, @[(NSString*)kUTTypeMovie]);
218 | }
219 | }
220 |
221 | - (UIImage*) createImage:(CGRect)rect orientation:(UIImageOrientation)imageOrientation {
222 | UIGraphicsBeginImageContext(rect.size);
223 | CGContextRef context = UIGraphicsGetCurrentContext();
224 |
225 | CGContextSetFillColorWithColor(context, [[UIColor greenColor] CGColor]);
226 | CGContextFillRect(context, rect);
227 |
228 | CGImageRef result = CGBitmapContextCreateImage(UIGraphicsGetCurrentContext());
229 | UIImage* image = [UIImage imageWithCGImage:result scale:1.0f orientation:imageOrientation];
230 |
231 | UIGraphicsEndImageContext();
232 |
233 | return image;
234 | }
235 |
236 | - (void) testImageScaleCropForSize {
237 |
238 | UIImage *sourceImagePortrait, *sourceImageLandscape, *targetImage;
239 | CGSize targetSize = CGSizeZero;
240 |
241 | sourceImagePortrait = [self createImage:CGRectMake(0, 0, 2448, 3264) orientation:UIImageOrientationUp];
242 | sourceImageLandscape = [self createImage:CGRectMake(0, 0, 3264, 2448) orientation:UIImageOrientationUp];
243 |
244 | // test 640x480
245 |
246 | targetSize = CGSizeMake(640, 480);
247 |
248 | targetImage = [sourceImagePortrait imageByScalingAndCroppingForSize:targetSize];
249 | XCTAssertEqual(targetImage.size.width, targetSize.width);
250 | XCTAssertEqual(targetImage.size.height, targetSize.height);
251 |
252 | targetImage = [sourceImageLandscape imageByScalingAndCroppingForSize:targetSize];
253 | XCTAssertEqual(targetImage.size.width, targetSize.width);
254 | XCTAssertEqual(targetImage.size.height, targetSize.height);
255 |
256 |
257 | // test 800x600
258 |
259 | targetSize = CGSizeMake(800, 600);
260 |
261 | targetImage = [sourceImagePortrait imageByScalingAndCroppingForSize:targetSize];
262 | XCTAssertEqual(targetImage.size.width, targetSize.width);
263 | XCTAssertEqual(targetImage.size.height, targetSize.height);
264 |
265 | targetImage = [sourceImageLandscape imageByScalingAndCroppingForSize:targetSize];
266 | XCTAssertEqual(targetImage.size.width, targetSize.width);
267 | XCTAssertEqual(targetImage.size.height, targetSize.height);
268 |
269 | // test 1024x768
270 |
271 | targetSize = CGSizeMake(1024, 768);
272 |
273 | targetImage = [sourceImagePortrait imageByScalingAndCroppingForSize:targetSize];
274 | XCTAssertEqual(targetImage.size.width, targetSize.width);
275 | XCTAssertEqual(targetImage.size.height, targetSize.height);
276 |
277 | targetImage = [sourceImageLandscape imageByScalingAndCroppingForSize:targetSize];
278 | XCTAssertEqual(targetImage.size.width, targetSize.width);
279 | XCTAssertEqual(targetImage.size.height, targetSize.height);
280 | }
281 |
282 | - (void) testImageScaleNoCropForSize {
283 | UIImage *sourceImagePortrait, *sourceImageLandscape, *targetImage;
284 | CGSize targetSize = CGSizeZero;
285 |
286 | sourceImagePortrait = [self createImage:CGRectMake(0, 0, 2448, 3264) orientation:UIImageOrientationUp];
287 | sourceImageLandscape = [self createImage:CGRectMake(0, 0, 3264, 2448) orientation:UIImageOrientationUp];
288 |
289 | // test 640x480
290 |
291 | targetSize = CGSizeMake(480, 640);
292 |
293 | targetImage = [sourceImagePortrait imageByScalingNotCroppingForSize:targetSize];
294 | XCTAssertEqual(targetImage.size.width, targetSize.width);
295 | XCTAssertEqual(targetImage.size.height, targetSize.height);
296 |
297 | targetSize = CGSizeMake(640, 480);
298 |
299 | targetImage = [sourceImageLandscape imageByScalingNotCroppingForSize:targetSize];
300 | XCTAssertEqual(targetImage.size.width, targetSize.width);
301 | XCTAssertEqual(targetImage.size.height, targetSize.height);
302 |
303 |
304 | // test 800x600
305 |
306 | targetSize = CGSizeMake(600, 800);
307 |
308 | targetImage = [sourceImagePortrait imageByScalingNotCroppingForSize:targetSize];
309 | XCTAssertEqual(targetImage.size.width, targetSize.width);
310 | XCTAssertEqual(targetImage.size.height, targetSize.height);
311 |
312 | targetSize = CGSizeMake(800, 600);
313 |
314 | targetImage = [sourceImageLandscape imageByScalingNotCroppingForSize:targetSize];
315 | XCTAssertEqual(targetImage.size.width, targetSize.width);
316 | XCTAssertEqual(targetImage.size.height, targetSize.height);
317 |
318 | // test 1024x768
319 |
320 | targetSize = CGSizeMake(768, 1024);
321 |
322 | targetImage = [sourceImagePortrait imageByScalingNotCroppingForSize:targetSize];
323 | XCTAssertEqual(targetImage.size.width, targetSize.width);
324 | XCTAssertEqual(targetImage.size.height, targetSize.height);
325 |
326 | targetSize = CGSizeMake(1024, 768);
327 |
328 | targetImage = [sourceImageLandscape imageByScalingNotCroppingForSize:targetSize];
329 | XCTAssertEqual(targetImage.size.width, targetSize.width);
330 | XCTAssertEqual(targetImage.size.height, targetSize.height);
331 | }
332 |
333 | - (void) testImageCorrectedForOrientation {
334 | UIImage *sourceImagePortrait, *sourceImageLandscape, *targetImage;
335 | CGSize targetSize = CGSizeZero;
336 |
337 | sourceImagePortrait = [self createImage:CGRectMake(0, 0, 2448, 3264) orientation:UIImageOrientationDown];
338 | sourceImageLandscape = [self createImage:CGRectMake(0, 0, 3264, 2448) orientation:UIImageOrientationDown];
339 |
340 | // PORTRAIT - image size should be unchanged
341 |
342 | targetSize = CGSizeMake(2448, 3264);
343 |
344 | targetImage = [sourceImagePortrait imageCorrectedForCaptureOrientation:UIImageOrientationUp];
345 | XCTAssertEqual(targetImage.size.width, targetSize.width);
346 | XCTAssertEqual(targetImage.size.height, targetSize.height);
347 | XCTAssertEqual(targetImage.imageOrientation, UIImageOrientationUp);
348 |
349 | targetImage = [sourceImagePortrait imageCorrectedForCaptureOrientation:UIImageOrientationDown];
350 | XCTAssertEqual(targetImage.size.width, targetSize.width);
351 | XCTAssertEqual(targetImage.size.height, targetSize.height);
352 | XCTAssertEqual(targetImage.imageOrientation, UIImageOrientationUp);
353 |
354 | targetImage = [sourceImagePortrait imageCorrectedForCaptureOrientation:UIImageOrientationRight];
355 | XCTAssertEqual(targetImage.size.width, targetSize.width);
356 | XCTAssertEqual(targetImage.size.height, targetSize.height);
357 | XCTAssertEqual(targetImage.imageOrientation, UIImageOrientationUp);
358 |
359 | targetImage = [sourceImagePortrait imageCorrectedForCaptureOrientation:UIImageOrientationLeft];
360 | XCTAssertEqual(targetImage.size.width, targetSize.width);
361 | XCTAssertEqual(targetImage.size.height, targetSize.height);
362 | XCTAssertEqual(targetImage.imageOrientation, UIImageOrientationUp);
363 |
364 | // LANDSCAPE - image size should be unchanged
365 |
366 | targetSize = CGSizeMake(3264, 2448);
367 |
368 | targetImage = [sourceImageLandscape imageCorrectedForCaptureOrientation:UIImageOrientationUp];
369 | XCTAssertEqual(targetImage.size.width, targetSize.width);
370 | XCTAssertEqual(targetImage.size.height, targetSize.height);
371 |
372 | targetImage = [sourceImageLandscape imageCorrectedForCaptureOrientation:UIImageOrientationDown];
373 | XCTAssertEqual(targetImage.size.width, targetSize.width);
374 | XCTAssertEqual(targetImage.size.height, targetSize.height);
375 |
376 | targetImage = [sourceImageLandscape imageCorrectedForCaptureOrientation:UIImageOrientationRight];
377 | XCTAssertEqual(targetImage.size.width, targetSize.width);
378 | XCTAssertEqual(targetImage.size.height, targetSize.height);
379 |
380 | targetImage = [sourceImageLandscape imageCorrectedForCaptureOrientation:UIImageOrientationLeft];
381 | XCTAssertEqual(targetImage.size.width, targetSize.width);
382 | XCTAssertEqual(targetImage.size.height, targetSize.height);
383 | }
384 |
385 |
386 | - (void) testRetrieveImage
387 | {
388 | CDVPictureOptions* pictureOptions = [[CDVPictureOptions alloc] init];
389 | NSDictionary *infoDict1, *infoDict2;
390 | UIImage* resultImage;
391 |
392 | UIImage* originalImage = [self createImage:CGRectMake(0, 0, 1024, 768) orientation:UIImageOrientationDown];
393 | UIImage* originalCorrectedForOrientation = [originalImage imageCorrectedForCaptureOrientation];
394 |
395 | UIImage* editedImage = [self createImage:CGRectMake(0, 0, 800, 600) orientation:UIImageOrientationDown];
396 | UIImage* scaledImageWithCrop = [originalImage imageByScalingAndCroppingForSize:CGSizeMake(640, 480)];
397 | UIImage* scaledImageNoCrop = [originalImage imageByScalingNotCroppingForSize:CGSizeMake(640, 480)];
398 |
399 | infoDict1 = @{
400 | UIImagePickerControllerOriginalImage : originalImage
401 | };
402 |
403 | infoDict2 = @{
404 | UIImagePickerControllerOriginalImage : originalImage,
405 | UIImagePickerControllerEditedImage : editedImage
406 | };
407 |
408 | // Original with no options
409 |
410 | pictureOptions.allowsEditing = YES;
411 | pictureOptions.targetSize = CGSizeZero;
412 | pictureOptions.cropToSize = NO;
413 | pictureOptions.correctOrientation = NO;
414 |
415 | resultImage = [self.plugin retrieveImage:infoDict1 options:pictureOptions];
416 | XCTAssertEqualObjects(resultImage, originalImage);
417 |
418 | // Original with no options
419 |
420 | pictureOptions.allowsEditing = YES;
421 | pictureOptions.targetSize = CGSizeZero;
422 | pictureOptions.cropToSize = NO;
423 | pictureOptions.correctOrientation = NO;
424 |
425 | resultImage = [self.plugin retrieveImage:infoDict2 options:pictureOptions];
426 | XCTAssertEqualObjects(resultImage, editedImage);
427 |
428 | // Original with corrected orientation
429 |
430 | pictureOptions.allowsEditing = YES;
431 | pictureOptions.targetSize = CGSizeZero;
432 | pictureOptions.cropToSize = NO;
433 | pictureOptions.correctOrientation = YES;
434 |
435 | resultImage = [self.plugin retrieveImage:infoDict1 options:pictureOptions];
436 | XCTAssertNotEqual(resultImage.imageOrientation, originalImage.imageOrientation);
437 | XCTAssertEqual(resultImage.imageOrientation, originalCorrectedForOrientation.imageOrientation);
438 | XCTAssertEqual(resultImage.size.width, originalCorrectedForOrientation.size.width);
439 | XCTAssertEqual(resultImage.size.height, originalCorrectedForOrientation.size.height);
440 |
441 | // Original with targetSize, no crop
442 |
443 | pictureOptions.allowsEditing = YES;
444 | pictureOptions.targetSize = CGSizeMake(640, 480);
445 | pictureOptions.cropToSize = NO;
446 | pictureOptions.correctOrientation = NO;
447 |
448 | resultImage = [self.plugin retrieveImage:infoDict1 options:pictureOptions];
449 | XCTAssertEqual(resultImage.size.width, scaledImageNoCrop.size.width);
450 | XCTAssertEqual(resultImage.size.height, scaledImageNoCrop.size.height);
451 |
452 | // Original with targetSize, plus crop
453 |
454 | pictureOptions.allowsEditing = YES;
455 | pictureOptions.targetSize = CGSizeMake(640, 480);
456 | pictureOptions.cropToSize = YES;
457 | pictureOptions.correctOrientation = NO;
458 |
459 | resultImage = [self.plugin retrieveImage:infoDict1 options:pictureOptions];
460 | XCTAssertEqual(resultImage.size.width, scaledImageWithCrop.size.width);
461 | XCTAssertEqual(resultImage.size.height, scaledImageWithCrop.size.height);
462 | }
463 |
464 | - (void) testProcessImage
465 | {
466 | CDVPictureOptions* pictureOptions = [[CDVPictureOptions alloc] init];
467 | NSData* resultData;
468 |
469 | UIImage* originalImage = [self createImage:CGRectMake(0, 0, 1024, 768) orientation:UIImageOrientationDown];
470 | NSData* originalImageDataPNG = UIImagePNGRepresentation(originalImage);
471 | NSData* originalImageDataJPEG = UIImageJPEGRepresentation(originalImage, 1.0);
472 |
473 | // Original, PNG
474 |
475 | pictureOptions.allowsEditing = YES;
476 | pictureOptions.targetSize = CGSizeZero;
477 | pictureOptions.cropToSize = NO;
478 | pictureOptions.correctOrientation = NO;
479 | pictureOptions.encodingType = EncodingTypePNG;
480 |
481 | resultData = [self.plugin processImage:originalImage info:@{} options:pictureOptions];
482 | XCTAssertEqualObjects([resultData base64EncodedStringWithOptions:0], [originalImageDataPNG base64EncodedStringWithOptions:0]);
483 |
484 | // Original, JPEG, full quality
485 |
486 | pictureOptions.allowsEditing = NO;
487 | pictureOptions.targetSize = CGSizeZero;
488 | pictureOptions.cropToSize = NO;
489 | pictureOptions.correctOrientation = NO;
490 | pictureOptions.encodingType = EncodingTypeJPEG;
491 |
492 | resultData = [self.plugin processImage:originalImage info:@{} options:pictureOptions];
493 | XCTAssertEqualObjects([resultData base64EncodedStringWithOptions:0], [originalImageDataJPEG base64EncodedStringWithOptions:0]);
494 |
495 | // Original, JPEG, with quality value
496 |
497 | pictureOptions.allowsEditing = YES;
498 | pictureOptions.targetSize = CGSizeZero;
499 | pictureOptions.cropToSize = NO;
500 | pictureOptions.correctOrientation = NO;
501 | pictureOptions.encodingType = EncodingTypeJPEG;
502 | pictureOptions.quality = @(57);
503 |
504 | NSData* originalImageDataJPEGWithQuality = UIImageJPEGRepresentation(originalImage, [pictureOptions.quality floatValue]/ 100.f);
505 | resultData = [self.plugin processImage:originalImage info:@{} options:pictureOptions];
506 | XCTAssertEqualObjects([resultData base64EncodedStringWithOptions:0], [originalImageDataJPEGWithQuality base64EncodedStringWithOptions:0]);
507 |
508 | // TODO: usesGeolocation is not tested
509 | }
510 |
511 | @end
512 |
--------------------------------------------------------------------------------
/tests/ios/CDVCameraTest/CDVCameraLibTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
23 |
24 |
25 | CFBundleDevelopmentRegion
26 | en
27 | CFBundleExecutable
28 | $(EXECUTABLE_NAME)
29 | CFBundleIdentifier
30 | org.apache.cordova.$(PRODUCT_NAME:rfc1034identifier)
31 | CFBundleInfoDictionaryVersion
32 | 6.0
33 | CFBundleName
34 | $(PRODUCT_NAME)
35 | CFBundlePackageType
36 | BNDL
37 | CFBundleShortVersionString
38 | 1.0
39 | CFBundleSignature
40 | ????
41 | CFBundleVersion
42 | 1
43 |
44 |
45 |
--------------------------------------------------------------------------------
/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 30486FEB1A40DC350065C233 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30486FEA1A40DC350065C233 /* UIKit.framework */; };
11 | 30486FED1A40DC3B0065C233 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30486FEC1A40DC3A0065C233 /* Foundation.framework */; };
12 | 30486FF91A40DCC70065C233 /* CDVCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = 30486FF31A40DCC70065C233 /* CDVCamera.m */; };
13 | 30486FFA1A40DCC70065C233 /* CDVJpegHeaderWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 30486FF61A40DCC70065C233 /* CDVJpegHeaderWriter.m */; };
14 | 30486FFB1A40DCC70065C233 /* UIImage+CropScaleOrientation.m in Sources */ = {isa = PBXBuildFile; fileRef = 30486FF81A40DCC70065C233 /* UIImage+CropScaleOrientation.m */; };
15 | 304870011A40DD620065C233 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30486FFE1A40DD180065C233 /* CoreGraphics.framework */; };
16 | 304870021A40DD860065C233 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30486FFE1A40DD180065C233 /* CoreGraphics.framework */; };
17 | 304870031A40DD8C0065C233 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30486FEA1A40DC350065C233 /* UIKit.framework */; };
18 | 304870051A40DD9A0065C233 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 304870041A40DD9A0065C233 /* MobileCoreServices.framework */; };
19 | 304870071A40DDAC0065C233 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 304870061A40DDAC0065C233 /* AssetsLibrary.framework */; };
20 | 304870091A40DDB90065C233 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 304870081A40DDB90065C233 /* CoreLocation.framework */; };
21 | 3048700B1A40DDF30065C233 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3048700A1A40DDF30065C233 /* ImageIO.framework */; };
22 | 308F59B11A4228730031A4D4 /* libCordova.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E9F519019DA0F8300DA31AC /* libCordova.a */; };
23 | 7E9F51B119DA114400DA31AC /* CameraTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E9F51B019DA114400DA31AC /* CameraTest.m */; };
24 | 7E9F51B919DA1B1600DA31AC /* libCDVCameraLib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E9F519519DA102000DA31AC /* libCDVCameraLib.a */; };
25 | /* End PBXBuildFile section */
26 |
27 | /* Begin PBXContainerItemProxy section */
28 | 30486FFC1A40DCE80065C233 /* PBXContainerItemProxy */ = {
29 | isa = PBXContainerItemProxy;
30 | containerPortal = 7E9F518B19DA0F8300DA31AC /* CordovaLib.xcodeproj */;
31 | proxyType = 1;
32 | remoteGlobalIDString = D2AAC07D0554694100DB518D;
33 | remoteInfo = CordovaLib;
34 | };
35 | 7E9F518F19DA0F8300DA31AC /* PBXContainerItemProxy */ = {
36 | isa = PBXContainerItemProxy;
37 | containerPortal = 7E9F518B19DA0F8300DA31AC /* CordovaLib.xcodeproj */;
38 | proxyType = 2;
39 | remoteGlobalIDString = 68A32D7114102E1C006B237C;
40 | remoteInfo = CordovaLib;
41 | };
42 | 7E9F51AC19DA10DE00DA31AC /* PBXContainerItemProxy */ = {
43 | isa = PBXContainerItemProxy;
44 | containerPortal = 7E9F517219DA09CE00DA31AC /* Project object */;
45 | proxyType = 1;
46 | remoteGlobalIDString = 7E9F519419DA102000DA31AC;
47 | remoteInfo = CDVCameraLib;
48 | };
49 | /* End PBXContainerItemProxy section */
50 |
51 | /* Begin PBXCopyFilesBuildPhase section */
52 | 7E9F519319DA102000DA31AC /* CopyFiles */ = {
53 | isa = PBXCopyFilesBuildPhase;
54 | buildActionMask = 2147483647;
55 | dstPath = "include/$(PRODUCT_NAME)";
56 | dstSubfolderSpec = 16;
57 | files = (
58 | );
59 | runOnlyForDeploymentPostprocessing = 0;
60 | };
61 | /* End PBXCopyFilesBuildPhase section */
62 |
63 | /* Begin PBXFileReference section */
64 | 30486FEA1A40DC350065C233 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
65 | 30486FEC1A40DC3A0065C233 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
66 | 30486FF21A40DCC70065C233 /* CDVCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVCamera.h; sourceTree = ""; };
67 | 30486FF31A40DCC70065C233 /* CDVCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVCamera.m; sourceTree = ""; };
68 | 30486FF41A40DCC70065C233 /* CDVExif.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVExif.h; sourceTree = ""; };
69 | 30486FF51A40DCC70065C233 /* CDVJpegHeaderWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVJpegHeaderWriter.h; sourceTree = ""; };
70 | 30486FF61A40DCC70065C233 /* CDVJpegHeaderWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVJpegHeaderWriter.m; sourceTree = ""; };
71 | 30486FF71A40DCC70065C233 /* UIImage+CropScaleOrientation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+CropScaleOrientation.h"; sourceTree = ""; };
72 | 30486FF81A40DCC70065C233 /* UIImage+CropScaleOrientation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+CropScaleOrientation.m"; sourceTree = ""; };
73 | 30486FFE1A40DD180065C233 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
74 | 304870041A40DD9A0065C233 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; };
75 | 304870061A40DDAC0065C233 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/AssetsLibrary.framework; sourceTree = DEVELOPER_DIR; };
76 | 304870081A40DDB90065C233 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/CoreLocation.framework; sourceTree = DEVELOPER_DIR; };
77 | 3048700A1A40DDF30065C233 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/ImageIO.framework; sourceTree = DEVELOPER_DIR; };
78 | 7E9F518B19DA0F8300DA31AC /* CordovaLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CordovaLib.xcodeproj; path = "../node_modules/cordova-ios/CordovaLib/CordovaLib.xcodeproj"; sourceTree = ""; };
79 | 7E9F519519DA102000DA31AC /* libCDVCameraLib.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCDVCameraLib.a; sourceTree = BUILT_PRODUCTS_DIR; };
80 | 7E9F519F19DA102000DA31AC /* CDVCameraLibTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CDVCameraLibTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
81 | 7E9F51A219DA102000DA31AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
82 | 7E9F51B019DA114400DA31AC /* CameraTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraTest.m; sourceTree = ""; };
83 | /* End PBXFileReference section */
84 |
85 | /* Begin PBXFrameworksBuildPhase section */
86 | 7E9F519219DA102000DA31AC /* Frameworks */ = {
87 | isa = PBXFrameworksBuildPhase;
88 | buildActionMask = 2147483647;
89 | files = (
90 | 308F59B11A4228730031A4D4 /* libCordova.a in Frameworks */,
91 | 304870011A40DD620065C233 /* CoreGraphics.framework in Frameworks */,
92 | 30486FED1A40DC3B0065C233 /* Foundation.framework in Frameworks */,
93 | 30486FEB1A40DC350065C233 /* UIKit.framework in Frameworks */,
94 | );
95 | runOnlyForDeploymentPostprocessing = 0;
96 | };
97 | 7E9F519C19DA102000DA31AC /* Frameworks */ = {
98 | isa = PBXFrameworksBuildPhase;
99 | buildActionMask = 2147483647;
100 | files = (
101 | 3048700B1A40DDF30065C233 /* ImageIO.framework in Frameworks */,
102 | 304870091A40DDB90065C233 /* CoreLocation.framework in Frameworks */,
103 | 304870071A40DDAC0065C233 /* AssetsLibrary.framework in Frameworks */,
104 | 304870051A40DD9A0065C233 /* MobileCoreServices.framework in Frameworks */,
105 | 304870031A40DD8C0065C233 /* UIKit.framework in Frameworks */,
106 | 304870021A40DD860065C233 /* CoreGraphics.framework in Frameworks */,
107 | 7E9F51B919DA1B1600DA31AC /* libCDVCameraLib.a in Frameworks */,
108 | );
109 | runOnlyForDeploymentPostprocessing = 0;
110 | };
111 | /* End PBXFrameworksBuildPhase section */
112 |
113 | /* Begin PBXGroup section */
114 | 30486FF11A40DCC70065C233 /* CDVCameraLib */ = {
115 | isa = PBXGroup;
116 | children = (
117 | 30486FF21A40DCC70065C233 /* CDVCamera.h */,
118 | 30486FF31A40DCC70065C233 /* CDVCamera.m */,
119 | 30486FF41A40DCC70065C233 /* CDVExif.h */,
120 | 30486FF51A40DCC70065C233 /* CDVJpegHeaderWriter.h */,
121 | 30486FF61A40DCC70065C233 /* CDVJpegHeaderWriter.m */,
122 | 30486FF71A40DCC70065C233 /* UIImage+CropScaleOrientation.h */,
123 | 30486FF81A40DCC70065C233 /* UIImage+CropScaleOrientation.m */,
124 | );
125 | name = CDVCameraLib;
126 | path = ../../../src/ios;
127 | sourceTree = "";
128 | };
129 | 308F59B01A4227A60031A4D4 /* Frameworks */ = {
130 | isa = PBXGroup;
131 | children = (
132 | 3048700A1A40DDF30065C233 /* ImageIO.framework */,
133 | 304870081A40DDB90065C233 /* CoreLocation.framework */,
134 | 304870061A40DDAC0065C233 /* AssetsLibrary.framework */,
135 | 304870041A40DD9A0065C233 /* MobileCoreServices.framework */,
136 | 30486FFE1A40DD180065C233 /* CoreGraphics.framework */,
137 | 30486FEC1A40DC3A0065C233 /* Foundation.framework */,
138 | 30486FEA1A40DC350065C233 /* UIKit.framework */,
139 | );
140 | name = Frameworks;
141 | sourceTree = "";
142 | };
143 | 7E9F517119DA09CE00DA31AC = {
144 | isa = PBXGroup;
145 | children = (
146 | 7E9F518B19DA0F8300DA31AC /* CordovaLib.xcodeproj */,
147 | 308F59B01A4227A60031A4D4 /* Frameworks */,
148 | 30486FF11A40DCC70065C233 /* CDVCameraLib */,
149 | 7E9F51A019DA102000DA31AC /* CDVCameraLibTests */,
150 | 7E9F517D19DA0A0A00DA31AC /* Products */,
151 | );
152 | sourceTree = "";
153 | };
154 | 7E9F517D19DA0A0A00DA31AC /* Products */ = {
155 | isa = PBXGroup;
156 | children = (
157 | 7E9F519519DA102000DA31AC /* libCDVCameraLib.a */,
158 | 7E9F519F19DA102000DA31AC /* CDVCameraLibTests.xctest */,
159 | );
160 | name = Products;
161 | sourceTree = "";
162 | };
163 | 7E9F518C19DA0F8300DA31AC /* Products */ = {
164 | isa = PBXGroup;
165 | children = (
166 | 7E9F519019DA0F8300DA31AC /* libCordova.a */,
167 | );
168 | name = Products;
169 | sourceTree = "";
170 | };
171 | 7E9F51A019DA102000DA31AC /* CDVCameraLibTests */ = {
172 | isa = PBXGroup;
173 | children = (
174 | 7E9F51A119DA102000DA31AC /* Supporting Files */,
175 | 7E9F51B019DA114400DA31AC /* CameraTest.m */,
176 | );
177 | path = CDVCameraLibTests;
178 | sourceTree = "";
179 | };
180 | 7E9F51A119DA102000DA31AC /* Supporting Files */ = {
181 | isa = PBXGroup;
182 | children = (
183 | 7E9F51A219DA102000DA31AC /* Info.plist */,
184 | );
185 | name = "Supporting Files";
186 | sourceTree = "";
187 | };
188 | /* End PBXGroup section */
189 |
190 | /* Begin PBXNativeTarget section */
191 | 7E9F519419DA102000DA31AC /* CDVCameraLib */ = {
192 | isa = PBXNativeTarget;
193 | buildConfigurationList = 7E9F51A319DA102000DA31AC /* Build configuration list for PBXNativeTarget "CDVCameraLib" */;
194 | buildPhases = (
195 | 7E9F519119DA102000DA31AC /* Sources */,
196 | 7E9F519219DA102000DA31AC /* Frameworks */,
197 | 7E9F519319DA102000DA31AC /* CopyFiles */,
198 | );
199 | buildRules = (
200 | );
201 | dependencies = (
202 | 30486FFD1A40DCE80065C233 /* PBXTargetDependency */,
203 | );
204 | name = CDVCameraLib;
205 | productName = CDVCameraLib;
206 | productReference = 7E9F519519DA102000DA31AC /* libCDVCameraLib.a */;
207 | productType = "com.apple.product-type.library.static";
208 | };
209 | 7E9F519E19DA102000DA31AC /* CDVCameraLibTests */ = {
210 | isa = PBXNativeTarget;
211 | buildConfigurationList = 7E9F51A619DA102000DA31AC /* Build configuration list for PBXNativeTarget "CDVCameraLibTests" */;
212 | buildPhases = (
213 | 7E9F519B19DA102000DA31AC /* Sources */,
214 | 7E9F519C19DA102000DA31AC /* Frameworks */,
215 | 7E9F519D19DA102000DA31AC /* Resources */,
216 | );
217 | buildRules = (
218 | );
219 | dependencies = (
220 | 7E9F51AD19DA10DE00DA31AC /* PBXTargetDependency */,
221 | );
222 | name = CDVCameraLibTests;
223 | productName = CDVCameraLibTests;
224 | productReference = 7E9F519F19DA102000DA31AC /* CDVCameraLibTests.xctest */;
225 | productType = "com.apple.product-type.bundle.unit-test";
226 | };
227 | /* End PBXNativeTarget section */
228 |
229 | /* Begin PBXProject section */
230 | 7E9F517219DA09CE00DA31AC /* Project object */ = {
231 | isa = PBXProject;
232 | attributes = {
233 | LastUpgradeCheck = 0610;
234 | TargetAttributes = {
235 | 7E9F519419DA102000DA31AC = {
236 | CreatedOnToolsVersion = 6.0;
237 | };
238 | 7E9F519E19DA102000DA31AC = {
239 | CreatedOnToolsVersion = 6.0;
240 | };
241 | };
242 | };
243 | buildConfigurationList = 7E9F517519DA09CE00DA31AC /* Build configuration list for PBXProject "CDVCameraTest" */;
244 | compatibilityVersion = "Xcode 3.2";
245 | developmentRegion = English;
246 | hasScannedForEncodings = 0;
247 | knownRegions = (
248 | en,
249 | );
250 | mainGroup = 7E9F517119DA09CE00DA31AC;
251 | productRefGroup = 7E9F517D19DA0A0A00DA31AC /* Products */;
252 | projectDirPath = "";
253 | projectReferences = (
254 | {
255 | ProductGroup = 7E9F518C19DA0F8300DA31AC /* Products */;
256 | ProjectRef = 7E9F518B19DA0F8300DA31AC /* CordovaLib.xcodeproj */;
257 | },
258 | );
259 | projectRoot = "";
260 | targets = (
261 | 7E9F519419DA102000DA31AC /* CDVCameraLib */,
262 | 7E9F519E19DA102000DA31AC /* CDVCameraLibTests */,
263 | );
264 | };
265 | /* End PBXProject section */
266 |
267 | /* Begin PBXReferenceProxy section */
268 | 7E9F519019DA0F8300DA31AC /* libCordova.a */ = {
269 | isa = PBXReferenceProxy;
270 | fileType = archive.ar;
271 | path = libCordova.a;
272 | remoteRef = 7E9F518F19DA0F8300DA31AC /* PBXContainerItemProxy */;
273 | sourceTree = BUILT_PRODUCTS_DIR;
274 | };
275 | /* End PBXReferenceProxy section */
276 |
277 | /* Begin PBXResourcesBuildPhase section */
278 | 7E9F519D19DA102000DA31AC /* Resources */ = {
279 | isa = PBXResourcesBuildPhase;
280 | buildActionMask = 2147483647;
281 | files = (
282 | );
283 | runOnlyForDeploymentPostprocessing = 0;
284 | };
285 | /* End PBXResourcesBuildPhase section */
286 |
287 | /* Begin PBXSourcesBuildPhase section */
288 | 7E9F519119DA102000DA31AC /* Sources */ = {
289 | isa = PBXSourcesBuildPhase;
290 | buildActionMask = 2147483647;
291 | files = (
292 | 30486FF91A40DCC70065C233 /* CDVCamera.m in Sources */,
293 | 30486FFB1A40DCC70065C233 /* UIImage+CropScaleOrientation.m in Sources */,
294 | 30486FFA1A40DCC70065C233 /* CDVJpegHeaderWriter.m in Sources */,
295 | );
296 | runOnlyForDeploymentPostprocessing = 0;
297 | };
298 | 7E9F519B19DA102000DA31AC /* Sources */ = {
299 | isa = PBXSourcesBuildPhase;
300 | buildActionMask = 2147483647;
301 | files = (
302 | 7E9F51B119DA114400DA31AC /* CameraTest.m in Sources */,
303 | );
304 | runOnlyForDeploymentPostprocessing = 0;
305 | };
306 | /* End PBXSourcesBuildPhase section */
307 |
308 | /* Begin PBXTargetDependency section */
309 | 30486FFD1A40DCE80065C233 /* PBXTargetDependency */ = {
310 | isa = PBXTargetDependency;
311 | name = CordovaLib;
312 | targetProxy = 30486FFC1A40DCE80065C233 /* PBXContainerItemProxy */;
313 | };
314 | 7E9F51AD19DA10DE00DA31AC /* PBXTargetDependency */ = {
315 | isa = PBXTargetDependency;
316 | target = 7E9F519419DA102000DA31AC /* CDVCameraLib */;
317 | targetProxy = 7E9F51AC19DA10DE00DA31AC /* PBXContainerItemProxy */;
318 | };
319 | /* End PBXTargetDependency section */
320 |
321 | /* Begin XCBuildConfiguration section */
322 | 7E9F517619DA09CE00DA31AC /* Debug */ = {
323 | isa = XCBuildConfiguration;
324 | buildSettings = {
325 | ONLY_ACTIVE_ARCH = YES;
326 | };
327 | name = Debug;
328 | };
329 | 7E9F517719DA09CE00DA31AC /* Release */ = {
330 | isa = XCBuildConfiguration;
331 | buildSettings = {
332 | };
333 | name = Release;
334 | };
335 | 7E9F51A419DA102000DA31AC /* Debug */ = {
336 | isa = XCBuildConfiguration;
337 | buildSettings = {
338 | ALWAYS_SEARCH_USER_PATHS = NO;
339 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
340 | CLANG_CXX_LIBRARY = "libc++";
341 | CLANG_ENABLE_MODULES = YES;
342 | CLANG_ENABLE_OBJC_ARC = YES;
343 | CLANG_WARN_BOOL_CONVERSION = YES;
344 | CLANG_WARN_CONSTANT_CONVERSION = YES;
345 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
346 | CLANG_WARN_EMPTY_BODY = YES;
347 | CLANG_WARN_ENUM_CONVERSION = YES;
348 | CLANG_WARN_INT_CONVERSION = YES;
349 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
350 | CLANG_WARN_UNREACHABLE_CODE = YES;
351 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
352 | COPY_PHASE_STRIP = NO;
353 | ENABLE_STRICT_OBJC_MSGSEND = YES;
354 | GCC_C_LANGUAGE_STANDARD = gnu99;
355 | GCC_DYNAMIC_NO_PIC = NO;
356 | GCC_OPTIMIZATION_LEVEL = 0;
357 | GCC_PREPROCESSOR_DEFINITIONS = (
358 | "DEBUG=1",
359 | "$(inherited)",
360 | );
361 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
362 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
363 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
364 | GCC_WARN_UNDECLARED_SELECTOR = YES;
365 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
366 | GCC_WARN_UNUSED_FUNCTION = YES;
367 | GCC_WARN_UNUSED_VARIABLE = YES;
368 | HEADER_SEARCH_PATHS = (
369 | "$(inherited)",
370 | "\"$(TARGET_BUILD_DIR)/usr/local/lib/include\"",
371 | "\"$(OBJROOT)/UninstalledProducts/include\"",
372 | "\"$(BUILT_PRODUCTS_DIR)\"",
373 | );
374 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
375 | MTL_ENABLE_DEBUG_INFO = YES;
376 | ONLY_ACTIVE_ARCH = YES;
377 | OTHER_LDFLAGS = "-ObjC";
378 | PRODUCT_NAME = "$(TARGET_NAME)";
379 | SDKROOT = iphoneos;
380 | SKIP_INSTALL = YES;
381 | };
382 | name = Debug;
383 | };
384 | 7E9F51A519DA102000DA31AC /* Release */ = {
385 | isa = XCBuildConfiguration;
386 | buildSettings = {
387 | ALWAYS_SEARCH_USER_PATHS = NO;
388 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
389 | CLANG_CXX_LIBRARY = "libc++";
390 | CLANG_ENABLE_MODULES = YES;
391 | CLANG_ENABLE_OBJC_ARC = YES;
392 | CLANG_WARN_BOOL_CONVERSION = YES;
393 | CLANG_WARN_CONSTANT_CONVERSION = YES;
394 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
395 | CLANG_WARN_EMPTY_BODY = YES;
396 | CLANG_WARN_ENUM_CONVERSION = YES;
397 | CLANG_WARN_INT_CONVERSION = YES;
398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
399 | CLANG_WARN_UNREACHABLE_CODE = YES;
400 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
401 | COPY_PHASE_STRIP = YES;
402 | ENABLE_NS_ASSERTIONS = NO;
403 | ENABLE_STRICT_OBJC_MSGSEND = YES;
404 | GCC_C_LANGUAGE_STANDARD = gnu99;
405 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
406 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
407 | GCC_WARN_UNDECLARED_SELECTOR = YES;
408 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
409 | GCC_WARN_UNUSED_FUNCTION = YES;
410 | GCC_WARN_UNUSED_VARIABLE = YES;
411 | HEADER_SEARCH_PATHS = (
412 | "$(inherited)",
413 | "\"$(TARGET_BUILD_DIR)/usr/local/lib/include\"",
414 | "\n\"$(OBJROOT)/UninstalledProducts/include\"\n\"$(BUILT_PRODUCTS_DIR)\"",
415 | );
416 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
417 | MTL_ENABLE_DEBUG_INFO = NO;
418 | OTHER_LDFLAGS = "-ObjC";
419 | PRODUCT_NAME = "$(TARGET_NAME)";
420 | SDKROOT = iphoneos;
421 | SKIP_INSTALL = YES;
422 | VALIDATE_PRODUCT = YES;
423 | };
424 | name = Release;
425 | };
426 | 7E9F51A719DA102000DA31AC /* Debug */ = {
427 | isa = XCBuildConfiguration;
428 | buildSettings = {
429 | ALWAYS_SEARCH_USER_PATHS = NO;
430 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
431 | CLANG_CXX_LIBRARY = "libc++";
432 | CLANG_ENABLE_MODULES = YES;
433 | CLANG_ENABLE_OBJC_ARC = YES;
434 | CLANG_WARN_BOOL_CONVERSION = YES;
435 | CLANG_WARN_CONSTANT_CONVERSION = YES;
436 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
437 | CLANG_WARN_EMPTY_BODY = YES;
438 | CLANG_WARN_ENUM_CONVERSION = YES;
439 | CLANG_WARN_INT_CONVERSION = YES;
440 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
441 | CLANG_WARN_UNREACHABLE_CODE = YES;
442 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
443 | COPY_PHASE_STRIP = NO;
444 | ENABLE_STRICT_OBJC_MSGSEND = YES;
445 | FRAMEWORK_SEARCH_PATHS = (
446 | "$(SDKROOT)/Developer/Library/Frameworks",
447 | "$(inherited)",
448 | );
449 | GCC_C_LANGUAGE_STANDARD = gnu99;
450 | GCC_DYNAMIC_NO_PIC = NO;
451 | GCC_OPTIMIZATION_LEVEL = 0;
452 | GCC_PREPROCESSOR_DEFINITIONS = (
453 | "DEBUG=1",
454 | "$(inherited)",
455 | );
456 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
457 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
458 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
459 | GCC_WARN_UNDECLARED_SELECTOR = YES;
460 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
461 | GCC_WARN_UNUSED_FUNCTION = YES;
462 | GCC_WARN_UNUSED_VARIABLE = YES;
463 | INFOPLIST_FILE = CDVCameraLibTests/Info.plist;
464 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
465 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
466 | MTL_ENABLE_DEBUG_INFO = YES;
467 | ONLY_ACTIVE_ARCH = YES;
468 | OTHER_LDFLAGS = (
469 | "$(inherited)",
470 | "-framework",
471 | XCTest,
472 | "-all_load",
473 | "-ObjC",
474 | );
475 | PRODUCT_NAME = "$(TARGET_NAME)";
476 | SDKROOT = iphoneos;
477 | };
478 | name = Debug;
479 | };
480 | 7E9F51A819DA102000DA31AC /* Release */ = {
481 | isa = XCBuildConfiguration;
482 | buildSettings = {
483 | ALWAYS_SEARCH_USER_PATHS = NO;
484 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
485 | CLANG_CXX_LIBRARY = "libc++";
486 | CLANG_ENABLE_MODULES = YES;
487 | CLANG_ENABLE_OBJC_ARC = YES;
488 | CLANG_WARN_BOOL_CONVERSION = YES;
489 | CLANG_WARN_CONSTANT_CONVERSION = YES;
490 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
491 | CLANG_WARN_EMPTY_BODY = YES;
492 | CLANG_WARN_ENUM_CONVERSION = YES;
493 | CLANG_WARN_INT_CONVERSION = YES;
494 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
495 | CLANG_WARN_UNREACHABLE_CODE = YES;
496 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
497 | COPY_PHASE_STRIP = YES;
498 | ENABLE_NS_ASSERTIONS = NO;
499 | ENABLE_STRICT_OBJC_MSGSEND = YES;
500 | FRAMEWORK_SEARCH_PATHS = (
501 | "$(SDKROOT)/Developer/Library/Frameworks",
502 | "$(inherited)",
503 | );
504 | GCC_C_LANGUAGE_STANDARD = gnu99;
505 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
506 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
507 | GCC_WARN_UNDECLARED_SELECTOR = YES;
508 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
509 | GCC_WARN_UNUSED_FUNCTION = YES;
510 | GCC_WARN_UNUSED_VARIABLE = YES;
511 | INFOPLIST_FILE = CDVCameraLibTests/Info.plist;
512 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
513 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
514 | MTL_ENABLE_DEBUG_INFO = NO;
515 | OTHER_LDFLAGS = (
516 | "$(inherited)",
517 | "-framework",
518 | XCTest,
519 | "-all_load",
520 | "-ObjC",
521 | );
522 | PRODUCT_NAME = "$(TARGET_NAME)";
523 | SDKROOT = iphoneos;
524 | VALIDATE_PRODUCT = YES;
525 | };
526 | name = Release;
527 | };
528 | /* End XCBuildConfiguration section */
529 |
530 | /* Begin XCConfigurationList section */
531 | 7E9F517519DA09CE00DA31AC /* Build configuration list for PBXProject "CDVCameraTest" */ = {
532 | isa = XCConfigurationList;
533 | buildConfigurations = (
534 | 7E9F517619DA09CE00DA31AC /* Debug */,
535 | 7E9F517719DA09CE00DA31AC /* Release */,
536 | );
537 | defaultConfigurationIsVisible = 0;
538 | defaultConfigurationName = Release;
539 | };
540 | 7E9F51A319DA102000DA31AC /* Build configuration list for PBXNativeTarget "CDVCameraLib" */ = {
541 | isa = XCConfigurationList;
542 | buildConfigurations = (
543 | 7E9F51A419DA102000DA31AC /* Debug */,
544 | 7E9F51A519DA102000DA31AC /* Release */,
545 | );
546 | defaultConfigurationIsVisible = 0;
547 | defaultConfigurationName = Release;
548 | };
549 | 7E9F51A619DA102000DA31AC /* Build configuration list for PBXNativeTarget "CDVCameraLibTests" */ = {
550 | isa = XCConfigurationList;
551 | buildConfigurations = (
552 | 7E9F51A719DA102000DA31AC /* Debug */,
553 | 7E9F51A819DA102000DA31AC /* Release */,
554 | );
555 | defaultConfigurationIsVisible = 0;
556 | defaultConfigurationName = Release;
557 | };
558 | /* End XCConfigurationList section */
559 | };
560 | rootObject = 7E9F517219DA09CE00DA31AC /* Project object */;
561 | }
562 |
--------------------------------------------------------------------------------
/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/project.xcworkspace/xcshareddata/CDVCameraTest.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 6BE9AD73-1B9F-4362-98D7-DC631BEC6185
9 | IDESourceControlProjectName
10 | CDVCameraTest
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | BEF5A5D0FF64801E558286389440357A9233D7DB
14 | https://git-wip-us.apache.org/repos/asf/cordova-plugin-camera.git
15 |
16 | IDESourceControlProjectPath
17 | tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | BEF5A5D0FF64801E558286389440357A9233D7DB
21 | ../../../../..
22 |
23 | IDESourceControlProjectURL
24 | https://git-wip-us.apache.org/repos/asf/cordova-plugin-camera.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | BEF5A5D0FF64801E558286389440357A9233D7DB
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | BEF5A5D0FF64801E558286389440357A9233D7DB
36 | IDESourceControlWCCName
37 | cordova-plugin-camera
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/xcshareddata/xcschemes/CDVCameraLib.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
60 |
61 |
67 |
68 |
69 |
70 |
72 |
73 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/xcshareddata/xcschemes/CDVCameraLibTests.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
61 |
62 |
68 |
69 |
70 |
71 |
72 |
73 |
79 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/tests/ios/README.md:
--------------------------------------------------------------------------------
1 |
19 |
20 | # iOS Tests for CDVCamera
21 |
22 | You need to install `node.js` to pull in `cordova-ios`.
23 |
24 | First install cordova-ios:
25 |
26 | npm install
27 |
28 | ... in the current folder.
29 |
30 |
31 | # Testing from Xcode
32 |
33 | 1. Launch the `CDVCameraTest.xcworkspace` file.
34 | 2. Choose "CDVCameraLibTests" from the scheme drop-down menu
35 | 3. Click and hold on the `Play` button, and choose the `Wrench` icon to run the tests
36 |
37 |
38 | # Testing from the command line
39 |
40 | npm test
41 |
--------------------------------------------------------------------------------
/tests/ios/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cordova-plugin-camera-test-ios",
3 | "version": "1.0.0",
4 | "description": "iOS Unit Tests for Camera Plugin",
5 | "author": "Apache Software Foundation",
6 | "license": "Apache Version 2.0",
7 | "dependencies": {
8 | "cordova-ios": "*"
9 | },
10 | "scripts": {
11 | "test": "xcodebuild -scheme CordovaLib && xcodebuild test -scheme CDVCameraLibTests -destination 'platform=iOS Simulator,name=iPhone 5s'"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/tests/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cordova-plugin-camera-tests",
3 | "version": "8.0.1-dev",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "cordova-plugin-camera-tests",
9 | "version": "8.0.1-dev",
10 | "license": "Apache-2.0"
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/tests/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cordova-plugin-camera-tests",
3 | "version": "8.0.1-dev",
4 | "description": "",
5 | "cordova": {
6 | "id": "cordova-plugin-camera-tests",
7 | "platforms": []
8 | },
9 | "keywords": [
10 | "ecosystem:cordova"
11 | ],
12 | "author": "",
13 | "license": "Apache-2.0"
14 | }
15 |
--------------------------------------------------------------------------------
/tests/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
26 | Cordova Camera Plugin Tests
27 | Apache 2.0
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/tests/tests.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | /* globals Camera, resolveLocalFileSystemURL, FileEntry, CameraPopoverOptions, LocalFileSystem */
23 | /* eslint-env jasmine */
24 |
25 | exports.defineAutoTests = function () {
26 | describe('Camera (navigator.camera)', function () {
27 | it('should exist', function () {
28 | expect(navigator.camera).toBeDefined();
29 | });
30 |
31 | it('should contain a getPicture function', function () {
32 | expect(navigator.camera.getPicture).toBeDefined();
33 | expect(typeof navigator.camera.getPicture === 'function').toBe(true);
34 | });
35 | });
36 |
37 | describe('Camera Constants (window.Camera + navigator.camera)', function () {
38 | it('camera.spec.1 window.Camera should exist', function () {
39 | expect(window.Camera).toBeDefined();
40 | });
41 |
42 | it('camera.spec.2 should contain three DestinationType constants', function () {
43 | expect(Camera.DestinationType.DATA_URL).toBe(0);
44 | expect(Camera.DestinationType.FILE_URI).toBe(1);
45 | expect(navigator.camera.DestinationType.DATA_URL).toBe(0);
46 | expect(navigator.camera.DestinationType.FILE_URI).toBe(1);
47 | });
48 |
49 | it('camera.spec.3 should contain two EncodingType constants', function () {
50 | expect(Camera.EncodingType.JPEG).toBe(0);
51 | expect(Camera.EncodingType.PNG).toBe(1);
52 | expect(navigator.camera.EncodingType.JPEG).toBe(0);
53 | expect(navigator.camera.EncodingType.PNG).toBe(1);
54 | });
55 |
56 | it('camera.spec.4 should contain three MediaType constants', function () {
57 | expect(Camera.MediaType.PICTURE).toBe(0);
58 | expect(Camera.MediaType.VIDEO).toBe(1);
59 | expect(Camera.MediaType.ALLMEDIA).toBe(2);
60 | expect(navigator.camera.MediaType.PICTURE).toBe(0);
61 | expect(navigator.camera.MediaType.VIDEO).toBe(1);
62 | expect(navigator.camera.MediaType.ALLMEDIA).toBe(2);
63 | });
64 |
65 | it('camera.spec.5 should contain three PictureSourceType constants', function () {
66 | expect(Camera.PictureSourceType.PHOTOLIBRARY).toBe(0);
67 | expect(Camera.PictureSourceType.CAMERA).toBe(1);
68 | expect(Camera.PictureSourceType.SAVEDPHOTOALBUM).toBe(2);
69 | expect(navigator.camera.PictureSourceType.PHOTOLIBRARY).toBe(0);
70 | expect(navigator.camera.PictureSourceType.CAMERA).toBe(1);
71 | expect(navigator.camera.PictureSourceType.SAVEDPHOTOALBUM).toBe(2);
72 | });
73 | });
74 | };
75 |
76 | /******************************************************************************/
77 | /******************************************************************************/
78 | /******************************************************************************/
79 |
80 | exports.defineManualTests = function (contentEl, createActionButton) {
81 | let pictureUrl = null;
82 | let fileObj = null;
83 | let fileEntry = null;
84 | const pageStartTime = +new Date();
85 |
86 | // default camera options
87 | const camQualityDefault = ['50', 50];
88 | const camDestinationTypeDefault = ['FILE_URI', 1];
89 | const camPictureSourceTypeDefault = ['CAMERA', 1];
90 | const camAllowEditDefault = ['allowEdit', false];
91 | const camEncodingTypeDefault = ['JPEG', 0];
92 | const camMediaTypeDefault = ['mediaType', 0];
93 | const camCorrectOrientationDefault = ['correctOrientation', false];
94 | const camSaveToPhotoAlbumDefault = ['saveToPhotoAlbum', true];
95 |
96 | function log (value) {
97 | console.log(value);
98 | document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
99 | }
100 |
101 | function clearStatus () {
102 | document.getElementById('camera_status').innerHTML = '';
103 | document.getElementById('camera_image').src = 'about:blank';
104 | const canvas = document.getElementById('canvas');
105 | canvas.width = canvas.height = 1;
106 | pictureUrl = null;
107 | fileObj = null;
108 | fileEntry = null;
109 | }
110 |
111 | function setPicture (url, callback) {
112 | try {
113 | window.atob(url);
114 | // if we got here it is a base64 string (DATA_URL)
115 | url = 'data:image/jpeg;base64,' + url;
116 | } catch (e) {
117 | // not DATA_URL
118 | }
119 | log('URL: "' + url.slice(0, 90) + '"');
120 |
121 | pictureUrl = url;
122 | const img = document.getElementById('camera_image');
123 | const startTime = new Date();
124 | img.src = url;
125 | img.onload = function () {
126 | log('Img size: ' + img.naturalWidth + 'x' + img.naturalHeight);
127 | log('Image tag load time: ' + (new Date() - startTime));
128 | if (callback) {
129 | callback();
130 | }
131 | };
132 | }
133 |
134 | function onGetPictureError (e) {
135 | log('Error getting picture: ' + (e.code || e));
136 | }
137 |
138 | function getPictureWin (data) {
139 | setPicture(data);
140 | // TODO: Fix resolveLocalFileSystemURI to work with native-uri.
141 | if (pictureUrl.indexOf('file:') === 0 || pictureUrl.indexOf('content:') === 0) {
142 | resolveLocalFileSystemURL(data, function (e) {
143 | fileEntry = e;
144 | logCallback('resolveLocalFileSystemURL()', true)(e.toURL());
145 | readFile();
146 | }, logCallback('resolveLocalFileSystemURL()', false));
147 | } else if (pictureUrl.indexOf('data:image/jpeg;base64') === 0) {
148 | // do nothing
149 | } else {
150 | const path = pictureUrl.replace(/^file:\/\/(localhost)?/, '').replace(/%20/g, ' ');
151 | fileEntry = new FileEntry('image_name.png', path);
152 | }
153 | }
154 |
155 | function getPicture () {
156 | clearStatus();
157 | const options = extractOptions();
158 | log('Getting picture with options: ' + JSON.stringify(options));
159 | const popoverHandle = navigator.camera.getPicture(getPictureWin, onGetPictureError, options);
160 |
161 | // Reposition the popover if the orientation changes.
162 | window.onorientationchange = function () {
163 | const newPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, 0, 300, 400);
164 | popoverHandle.setPosition(newPopoverOptions);
165 | };
166 | }
167 |
168 | function logCallback (apiName, success) {
169 | return function () {
170 | log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments)));
171 | };
172 | }
173 |
174 | /**
175 | * Select image from library
176 | * This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL.
177 | */
178 | function readFile () {
179 | function onFileReadAsDataURL (evt) {
180 | const img = document.getElementById('camera_image');
181 | img.style.visibility = 'visible';
182 | img.style.display = 'block';
183 | img.src = evt.target.result;
184 | log('FileReader.readAsDataURL success');
185 | }
186 |
187 | function onFileReceived (file) {
188 | log('Got file: ' + JSON.stringify(file));
189 | fileObj = file;
190 | /* eslint-disable no-undef */
191 | const reader = new FileReader();
192 | /* eslint-enable no-undef */
193 | reader.onload = function () {
194 | log('FileReader.readAsDataURL() - length = ' + reader.result.length);
195 | };
196 | reader.onerror = logCallback('FileReader.readAsDataURL', false);
197 | reader.onloadend = onFileReadAsDataURL;
198 | reader.readAsDataURL(file);
199 | }
200 |
201 | // Test out onFileReceived when the file object was set via a native elements.
202 | if (fileObj) {
203 | onFileReceived(fileObj);
204 | } else {
205 | fileEntry.file(onFileReceived, logCallback('FileEntry.file', false));
206 | }
207 | }
208 |
209 | function getFileInfo () {
210 | // Test FileEntry API here.
211 | fileEntry.getMetadata(logCallback('FileEntry.getMetadata', true), logCallback('FileEntry.getMetadata', false));
212 | fileEntry.setMetadata(logCallback('FileEntry.setMetadata', true), logCallback('FileEntry.setMetadata', false), { 'com.apple.MobileBackup': 1 });
213 | fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
214 | fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
215 | }
216 |
217 | /**
218 | * Copy image from library
219 | * This calls FileEntry.copyTo and FileEntry.moveTo.
220 | */
221 | function copyImage () {
222 | const onFileSystemReceived = function (fileSystem) {
223 | const destDirEntry = fileSystem.root;
224 | const origName = fileEntry.name;
225 |
226 | // Test FileEntry API here.
227 | fileEntry.copyTo(destDirEntry, 'copied_file.png', logCallback('FileEntry.copyTo', true), logCallback('FileEntry.copyTo', false));
228 | fileEntry.moveTo(destDirEntry, 'moved_file.png', logCallback('FileEntry.moveTo', true), logCallback('FileEntry.moveTo', false));
229 |
230 | // cleanup
231 | // rename moved file back to original name so other tests can reference image
232 | resolveLocalFileSystemURL(destDirEntry.nativeURL + 'moved_file.png', function (fileEntry) {
233 | fileEntry.moveTo(destDirEntry, origName, logCallback('FileEntry.moveTo', true), logCallback('FileEntry.moveTo', false));
234 | console.log('Cleanup: successfully renamed file back to original name');
235 | }, function () {
236 | console.log('Cleanup: failed to rename file back to original name');
237 | });
238 |
239 | // remove copied file
240 | resolveLocalFileSystemURL(destDirEntry.nativeURL + 'copied_file.png', function (fileEntry) {
241 | fileEntry.remove(logCallback('FileEntry.remove', true), logCallback('FileEntry.remove', false));
242 | console.log('Cleanup: successfully removed copied file');
243 | }, function () {
244 | console.log('Cleanup: failed to remove copied file');
245 | });
246 | };
247 |
248 | window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, onFileSystemReceived, null);
249 | }
250 |
251 | /**
252 | * Write image to library
253 | * This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate.
254 | */
255 | function writeImage () {
256 | const onFileWriterReceived = function (fileWriter) {
257 | fileWriter.onwrite = logCallback('FileWriter.write', true);
258 | fileWriter.onerror = logCallback('FileWriter.write', false);
259 | fileWriter.write('some text!');
260 | };
261 |
262 | const onFileTruncateWriterReceived = function (fileWriter) {
263 | fileWriter.onwrite = logCallback('FileWriter.truncate', true);
264 | fileWriter.onerror = logCallback('FileWriter.truncate', false);
265 | fileWriter.truncate(10);
266 | };
267 |
268 | fileEntry.createWriter(onFileWriterReceived, logCallback('FileEntry.createWriter', false));
269 | fileEntry.createWriter(onFileTruncateWriterReceived, null);
270 | }
271 |
272 | function displayImageUsingCanvas () {
273 | const canvas = document.getElementById('canvas');
274 | const img = document.getElementById('camera_image');
275 | let w = img.width;
276 | let h = img.height;
277 | h = 100 / w * h;
278 | w = 100;
279 | canvas.width = w;
280 | canvas.height = h;
281 | const context = canvas.getContext('2d');
282 | context.drawImage(img, 0, 0, w, h);
283 | }
284 |
285 | /**
286 | * Remove image from library
287 | * This calls FileEntry.remove.
288 | */
289 | function removeImage () {
290 | fileEntry.remove(logCallback('FileEntry.remove', true), logCallback('FileEntry.remove', false));
291 | }
292 |
293 | function testInputTag (inputEl) {
294 | clearStatus();
295 | // iOS 6 likes to dead-lock in the onchange context if you
296 | // do any alerts or try to remote-debug.
297 | window.setTimeout(function () {
298 | testNativeFile2(inputEl);
299 | }, 0);
300 | }
301 |
302 | function testNativeFile2 (inputEl) {
303 | /* eslint-disable no-undef */
304 | if (!inputEl.value) {
305 | alert('No file selected.');
306 | return;
307 | }
308 | fileObj = inputEl.files[0];
309 | if (!fileObj) {
310 | alert('Got value but no file.');
311 | return;
312 | }
313 | /* eslint-enable no-undef */
314 | const URLApi = window.URL || window.webkitURL;
315 | if (URLApi) {
316 | const blobURL = URLApi.createObjectURL(fileObj);
317 | if (blobURL) {
318 | setPicture(blobURL, function () {
319 | URLApi.revokeObjectURL(blobURL);
320 | });
321 | } else {
322 | log('URL.createObjectURL returned null');
323 | }
324 | } else {
325 | log('URL.createObjectURL() not supported.');
326 | }
327 | }
328 |
329 | function extractOptions () {
330 | const els = document.querySelectorAll('#image-options select');
331 | const ret = {};
332 | /* eslint-disable no-cond-assign */
333 | for (let i = 0, el; el = els[i]; ++i) {
334 | let value = el.value;
335 | if (value === '') continue;
336 | value = +value;
337 |
338 | if (el.isBool) {
339 | ret[el.getAttribute('name')] = !!value;
340 | } else {
341 | ret[el.getAttribute('name')] = value;
342 | }
343 | }
344 | /* eslint-enable no-cond-assign */
345 | return ret;
346 | }
347 |
348 | function createOptionsEl (name, values, selectionDefault) {
349 | const openDiv = '' + name + ': ';
350 | const select = '';
351 |
352 | let defaultOption = '';
353 | if (selectionDefault === undefined) {
354 | defaultOption = 'default ';
355 | }
356 |
357 | let options = '';
358 | if (typeof values === 'boolean') {
359 | values = { true: 1, false: 0 };
360 | }
361 | for (const k in values) {
362 | let isSelected = '';
363 | if (selectionDefault) {
364 | if (selectionDefault[0] === k) {
365 | isSelected = 'selected';
366 | }
367 | }
368 | options += '' + k + ' ';
369 | }
370 |
371 | const closeDiv = '
';
372 |
373 | return openDiv + select + defaultOption + options + closeDiv;
374 | }
375 |
376 | /******************************************************************************/
377 |
378 | const info_div = 'Camera ' +
379 | '' +
380 | '
Status:
' +
381 | 'img:
' +
382 | 'canvas:
' +
383 | '
';
384 | const options_div = 'Cordova Camera API Options ' +
385 | '' +
386 | createOptionsEl('sourceType', Camera.PictureSourceType, camPictureSourceTypeDefault) +
387 | createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault) +
388 | createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault) +
389 | createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault) +
390 | createOptionsEl('quality', { 0: 0, 50: 50, 80: 80, 100: 100 }, camQualityDefault) +
391 | createOptionsEl('targetWidth', { 50: 50, 200: 200, 800: 800, 2048: 2048 }) +
392 | createOptionsEl('targetHeight', { 50: 50, 200: 200, 800: 800, 2048: 2048 }) +
393 | createOptionsEl('allowEdit', true, camAllowEditDefault) +
394 | createOptionsEl('correctOrientation', true, camCorrectOrientationDefault) +
395 | createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault) +
396 | createOptionsEl('cameraDirection', Camera.Direction) +
397 | '
';
398 | const getpicture_div = '
';
399 | const test_procedure = 'Recommended Test Procedure ' +
400 | 'Options not specified should be the default value' +
401 | ' Status box should update with image and info whenever an image is taken or selected from library' +
402 | '
' +
403 | '
All default options. Should be able to edit once picture is taken and will be saved to library. ' +
404 | 'sourceType=PHOTOLIBRARY Should be able to see picture that was just taken in previous test and edit when selected ' +
405 | 'sourceType=Camera allowEdit=false saveToPhotoAlbum=false Should not be able to edit when taken and will not save to library ' +
406 | 'encodingType=PNG allowEdit=true saveToPhotoAlbum=true cameraDirection=FRONT Should bring up front camera. Verify in status box info URL that image is encoded as PNG. ' +
407 | 'sourceType=SAVEDPHOTOALBUM mediaType=VIDEO Should only be able to select a video ' +
408 | 'sourceType=SAVEDPHOTOALBUM mediaType=PICTURE allowEdit=false Should only be able to select a picture and not edit ' +
409 | 'sourceType=PHOTOLIBRARY mediaType=ALLMEDIA allowEdit=true Should be able to select pics and videos and edit picture if selected ' +
410 | 'sourceType=CAMERA targetWidth & targetHeight=50 allowEdit=false Do Get File Metadata test below and take note of size Repeat test but with width and height=800. Size should be significantly larger. ' +
411 | 'quality=0 targetWidth & targetHeight=default allowEdit=false Do Get File Metadata test below and take note of size Repeat test but with quality=80. Size should be significantly larger. ' +
412 | ' ';
413 | const inputs_div = 'Native File Inputs ' +
414 | 'For the following tests, status box should update with file selected' +
415 | 'input type=file
' +
416 | 'capture=camera
' +
417 | 'capture=camcorder
' +
418 | 'capture=microphone
';
419 | const actions_div = 'Actions ' +
420 | 'For the following tests, ensure that an image is set in status box' +
421 | '
' +
422 | 'Expected result: Get metadata about file selected. Status box will show, along with the metadata, "Call to FileEntry.getMetadata success, Call to FileEntry.setMetadata success, Call to FileEntry.getParent success"' +
423 | '
' +
424 | 'Expected result: Read contents of file. Status box will show "Got file: {some metadata}, FileReader.readAsDataURL() - length = someNumber"' +
425 | '
' +
426 | 'Expected result: Copy image to new location and move file to different location. Status box will show "Call to FileEntry.copyTo success:{some metadata}, Call to FileEntry.moveTo success:{some metadata}"' +
427 | '
' +
428 | 'Expected result: Write image to library. Status box will show "Call to FileWriter.write success:{some metadata}, Call to FileWriter.truncate success:{some metadata}"' +
429 | '
' +
430 | 'Expected result: Upload image to server. Status box may print out progress. Once finished will show "upload complete"' +
431 | '
' +
432 | 'Expected result: Display image using canvas. Image will be displayed in status box under "canvas:"' +
433 | '
' +
434 | 'Expected result: Remove image from library. Status box will show "FileEntry.remove success:["OK"]';
435 |
436 | contentEl.innerHTML = info_div + options_div + getpicture_div + test_procedure + inputs_div + actions_div;
437 |
438 | const elements = document.getElementsByClassName('testInputTag');
439 | const listener = function (e) {
440 | testInputTag(e.target);
441 | };
442 | for (let i = 0; i < elements.length; ++i) {
443 | const item = elements[i];
444 | item.addEventListener('change', listener, false);
445 | }
446 |
447 | createActionButton('Get picture', function () {
448 | getPicture();
449 | }, 'getpicture');
450 |
451 | createActionButton('Clear Status', function () {
452 | clearStatus();
453 | }, 'getpicture');
454 |
455 | createActionButton('Get File Metadata', function () {
456 | getFileInfo();
457 | }, 'metadata');
458 |
459 | createActionButton('Read with FileReader', function () {
460 | readFile();
461 | }, 'reader');
462 |
463 | createActionButton('Copy Image', function () {
464 | copyImage();
465 | }, 'copy');
466 |
467 | createActionButton('Write Image', function () {
468 | writeImage();
469 | }, 'write');
470 |
471 | createActionButton('Draw Using Canvas', function () {
472 | displayImageUsingCanvas();
473 | }, 'draw_canvas');
474 |
475 | createActionButton('Remove Image', function () {
476 | removeImage();
477 | }, 'remove');
478 | };
479 |
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | // Type definitions for Apache Cordova Camera plugin
2 | // Project: https://github.com/apache/cordova-plugin-camera
3 | // Definitions by: Microsoft Open Technologies Inc
4 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
5 | //
6 | // Copyright (c) Microsoft Open Technologies Inc
7 | // Licensed under the MIT license.
8 |
9 | interface Navigator {
10 | /**
11 | * This plugin provides an API for taking pictures and for choosing images from the system's image library.
12 | */
13 | camera: Camera;
14 | }
15 |
16 | /**
17 | * This plugin provides an API for taking pictures and for choosing images from the system's image library.
18 | */
19 | interface Camera {
20 | /**
21 | * Removes intermediate photos taken by the camera from temporary storage.
22 | * @param onSuccess Success callback, that called when cleanup succeeds.
23 | * @param onError Error callback, that get an error message.
24 | */
25 | cleanup(
26 | onSuccess: () => void,
27 | onError: (message: string) => void): void;
28 | /**
29 | * Takes a photo using the camera, or retrieves a photo from the device's image gallery.
30 | * @param cameraSuccess Success callback, that get the image
31 | * as a base64-encoded String, or as the URI for the image file.
32 | * @param cameraError Error callback, that get an error message.
33 | * @param cameraOptions Optional parameters to customize the camera settings.
34 | */
35 | getPicture(
36 | cameraSuccess: (data: string) => void,
37 | cameraError: (message: string) => void,
38 | cameraOptions?: CameraOptions): void;
39 | // Next will work only on iOS
40 | //getPicture(
41 | // cameraSuccess: (data: string) => void,
42 | // cameraError: (message: string) => void,
43 | // cameraOptions?: CameraOptions): CameraPopoverHandle;
44 | }
45 |
46 | interface CameraOptions {
47 | /** Picture quality in range 0-100. Default is 50 */
48 | quality?: number;
49 | /**
50 | * Choose the format of the return value.
51 | * Defined in navigator.camera.DestinationType. Default is FILE_URI.
52 | * DATA_URL : 0, Return image as base64-encoded string
53 | * FILE_URI : 1, Return image file URI
54 | */
55 | destinationType?: number;
56 | /**
57 | * Set the source of the picture.
58 | * Defined in navigator.camera.PictureSourceType. Default is CAMERA.
59 | * PHOTOLIBRARY : 0,
60 | * CAMERA : 1,
61 | * SAVEDPHOTOALBUM : 2
62 | */
63 | sourceType?: number;
64 | /** Allow simple editing of image before selection. */
65 | allowEdit?: boolean;
66 | /**
67 | * Choose the returned image file's encoding.
68 | * Defined in navigator.camera.EncodingType. Default is JPEG
69 | * JPEG : 0 Return JPEG encoded image
70 | * PNG : 1 Return PNG encoded image
71 | */
72 | encodingType?: number;
73 | /**
74 | * Width in pixels to scale image. Must be used with targetHeight.
75 | * Aspect ratio remains constant.
76 | */
77 | targetWidth?: number;
78 | /**
79 | * Height in pixels to scale image. Must be used with targetWidth.
80 | * Aspect ratio remains constant.
81 | */
82 | targetHeight?: number;
83 | /**
84 | * Set the type of media to select from. Only works when PictureSourceType
85 | * is PHOTOLIBRARY or SAVEDPHOTOALBUM. Defined in nagivator.camera.MediaType
86 | * PICTURE: 0 allow selection of still pictures only. DEFAULT.
87 | * Will return format specified via DestinationType
88 | * VIDEO: 1 allow selection of video only, WILL ALWAYS RETURN FILE_URI
89 | * ALLMEDIA : 2 allow selection from all media types
90 | */
91 | mediaType?: number;
92 | /** Rotate the image to correct for the orientation of the device during capture. */
93 | correctOrientation?: boolean;
94 | /** Save the image to the photo album on the device after capture. */
95 | saveToPhotoAlbum?: boolean;
96 | /**
97 | * Choose the camera to use (front- or back-facing).
98 | * Defined in navigator.camera.Direction. Default is BACK.
99 | * FRONT: 0
100 | * BACK: 1
101 | */
102 | cameraDirection?: number;
103 | /** iOS-only options that specify popover location in iPad. Defined in CameraPopoverOptions. */
104 | popoverOptions?: CameraPopoverOptions;
105 | }
106 |
107 | /**
108 | * A handle to the popover dialog created by navigator.camera.getPicture. Used on iOS only.
109 | */
110 | interface CameraPopoverHandle {
111 | /**
112 | * Set the position of the popover.
113 | * @param popoverOptions the CameraPopoverOptions that specify the new position.
114 | */
115 | setPosition(popoverOptions: CameraPopoverOptions): void;
116 | }
117 |
118 | /**
119 | * iOS-only parameters that specify the anchor element location and arrow direction
120 | * of the popover when selecting images from an iPad's library or album.
121 | */
122 | interface CameraPopoverOptions {
123 | x: number;
124 | y: number;
125 | width: number;
126 | height: number;
127 | /**
128 | * Direction the arrow on the popover should point. Defined in Camera.PopoverArrowDirection
129 | * Matches iOS UIPopoverArrowDirection constants.
130 | * ARROW_UP : 1,
131 | * ARROW_DOWN : 2,
132 | * ARROW_LEFT : 4,
133 | * ARROW_RIGHT : 8,
134 | * ARROW_ANY : 15
135 | */
136 | arrowDir : number;
137 | popoverWidth: number;
138 | popoverHeight: number;
139 | }
140 |
141 | declare class CameraPopoverOptions implements CameraPopoverOptions {
142 | constructor(x?: number, y?: number, width?: number, height?: number, arrowDir?: number);
143 | }
144 |
145 | declare var Camera: {
146 | // Camera constants, defined in Camera plugin
147 | DestinationType: {
148 | DATA_URL: number;
149 | FILE_URI: number;
150 | }
151 | Direction: {
152 | BACK: number;
153 | FRONT: number;
154 | }
155 | EncodingType: {
156 | JPEG: number;
157 | PNG: number;
158 | }
159 | MediaType: {
160 | PICTURE: number;
161 | VIDEO: number;
162 | ALLMEDIA: number;
163 | }
164 | PictureSourceType: {
165 | PHOTOLIBRARY: number;
166 | CAMERA: number;
167 | SAVEDPHOTOALBUM: number;
168 | }
169 | // Used only on iOS
170 | PopoverArrowDirection: {
171 | ARROW_UP: number;
172 | ARROW_DOWN: number;
173 | ARROW_LEFT: number;
174 | ARROW_RIGHT: number;
175 | ARROW_ANY: number;
176 | }
177 | };
178 |
--------------------------------------------------------------------------------
/www/Camera.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | const argscheck = require('cordova/argscheck');
23 | const exec = require('cordova/exec');
24 | const Camera = require('./Camera');
25 | // XXX: commented out
26 | // CameraPopoverHandle = require('./CameraPopoverHandle');
27 |
28 | /**
29 | * @namespace navigator
30 | */
31 |
32 | /**
33 | * @exports camera
34 | */
35 | const cameraExport = {};
36 |
37 | // Tack on the Camera Constants to the base camera plugin.
38 | for (const key in Camera) {
39 | cameraExport[key] = Camera[key];
40 | }
41 |
42 | /**
43 | * Callback function that provides an error message.
44 | * @callback module:camera.onError
45 | * @param {string} message - The message is provided by the device's native code.
46 | */
47 |
48 | /**
49 | * Callback function that provides the image data.
50 | * @callback module:camera.onSuccess
51 | * @param {string} imageData - Base64 encoding of the image data, _or_ the image file URI, depending on [`cameraOptions`]{@link module:camera.CameraOptions} in effect.
52 | * @example
53 | * // Show image
54 | * //
55 | * function cameraCallback(imageData) {
56 | * var image = document.getElementById('myImage');
57 | * image.src = "data:image/jpeg;base64," + imageData;
58 | * }
59 | */
60 |
61 | /**
62 | * Optional parameters to customize the camera settings.
63 | * * [Quirks](#CameraOptions-quirks)
64 | * @typedef module:camera.CameraOptions
65 | * @type {Object}
66 | * @property {number} [quality=50] - Quality of the saved image, expressed as a range of 0-100, where 100 is typically full resolution with no loss from file compression. (Note that information about the camera's resolution is unavailable.)
67 | * @property {module:Camera.DestinationType} [destinationType=FILE_URI] - Choose the format of the return value.
68 | * @property {module:Camera.PictureSourceType} [sourceType=CAMERA] - Set the source of the picture.
69 | * @property {Boolean} [allowEdit=false] - Allow simple editing of image before selection.
70 | * @property {module:Camera.EncodingType} [encodingType=JPEG] - Choose the returned image file's encoding.
71 | * @property {number} [targetWidth] - Width in pixels to scale image. Must be used with `targetHeight`. Aspect ratio remains constant.
72 | * @property {number} [targetHeight] - Height in pixels to scale image. Must be used with `targetWidth`. Aspect ratio remains constant.
73 | * @property {module:Camera.MediaType} [mediaType=PICTURE] - Set the type of media to select from. Only works when `PictureSourceType` is `PHOTOLIBRARY` or `SAVEDPHOTOALBUM`.
74 | * @property {Boolean} [correctOrientation] - Rotate the image to correct for the orientation of the device during capture.
75 | * @property {Boolean} [saveToPhotoAlbum] - Save the image to the photo album on the device after capture.
76 | * @property {module:CameraPopoverOptions} [popoverOptions] - iOS-only options that specify popover location in iPad.
77 | * @property {module:Camera.Direction} [cameraDirection=BACK] - Choose the camera to use (front- or back-facing).
78 | */
79 |
80 | /**
81 | * @description Takes a photo using the camera, or retrieves a photo from the device's
82 | * image gallery. The image is passed to the success callback as a
83 | * Base64-encoded `String`, or as the URI for the image file.
84 | *
85 | * The `camera.getPicture` function opens the device's default camera
86 | * application that allows users to snap pictures by default - this behavior occurs,
87 | * when `Camera.sourceType` equals [`Camera.PictureSourceType.CAMERA`]{@link module:Camera.PictureSourceType}.
88 | * Once the user snaps the photo, the camera application closes and the application is restored.
89 | *
90 | * If `Camera.sourceType` is `Camera.PictureSourceType.PHOTOLIBRARY` or
91 | * `Camera.PictureSourceType.SAVEDPHOTOALBUM`, then a dialog displays
92 | * that allows users to select an existing image.
93 | *
94 | * The return value is sent to the [`cameraSuccess`]{@link module:camera.onSuccess} callback function, in
95 | * one of the following formats, depending on the specified
96 | * `cameraOptions`:
97 | *
98 | * - A `String` containing the Base64-encoded photo image.
99 | * - A `String` representing the image file location on local storage (default).
100 | *
101 | * You can do whatever you want with the encoded image or URI, for
102 | * example:
103 | *
104 | * - Render the image in an ` ` tag, as in the example below
105 | * - Save the data locally (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.)
106 | * - Post the data to a remote server
107 | *
108 | * __NOTE__: Photo resolution on newer devices is quite good. Photos
109 | * selected from the device's gallery are not downscaled to a lower
110 | * quality, even if a `quality` parameter is specified. To avoid common
111 | * memory problems, set `Camera.destinationType` to `FILE_URI` rather
112 | * than `DATA_URL`.
113 | *
114 | * __Supported Platforms__
115 | *
116 | * - Android
117 | * - Browser
118 | * - iOS
119 | *
120 | * More examples [here](#camera-getPicture-examples). Quirks [here](#camera-getPicture-quirks).
121 | *
122 | * @example
123 | * navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
124 | * @param {module:camera.onSuccess} successCallback
125 | * @param {module:camera.onError} errorCallback
126 | * @param {module:camera.CameraOptions} options CameraOptions
127 | */
128 | cameraExport.getPicture = function (successCallback, errorCallback, options) {
129 | argscheck.checkArgs('fFO', 'Camera.getPicture', arguments);
130 | options = options || {};
131 | const getValue = argscheck.getValue;
132 |
133 | const quality = getValue(options.quality, 50);
134 | const destinationType = getValue(options.destinationType, Camera.DestinationType.FILE_URI);
135 | const sourceType = getValue(options.sourceType, Camera.PictureSourceType.CAMERA);
136 | const targetWidth = getValue(options.targetWidth, -1);
137 | const targetHeight = getValue(options.targetHeight, -1);
138 | const encodingType = getValue(options.encodingType, Camera.EncodingType.JPEG);
139 | const mediaType = getValue(options.mediaType, Camera.MediaType.PICTURE);
140 | const allowEdit = !!options.allowEdit;
141 | const correctOrientation = !!options.correctOrientation;
142 | const saveToPhotoAlbum = !!options.saveToPhotoAlbum;
143 | const popoverOptions = getValue(options.popoverOptions, null);
144 | const cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK);
145 |
146 | if (allowEdit) {
147 | console.warn('allowEdit is deprecated. It does not work reliably on all platforms. Utilise a dedicated image editing library instead. allowEdit functionality is scheduled to be removed in a future release.');
148 | }
149 |
150 | const args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType,
151 | mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection];
152 |
153 | exec(successCallback, errorCallback, 'Camera', 'takePicture', args);
154 | // XXX: commented out
155 | // return new CameraPopoverHandle();
156 | };
157 |
158 | /**
159 | * Removes intermediate image files that are kept in temporary storage
160 | * after calling [`camera.getPicture`]{@link module:camera.getPicture}. Applies only when the value of
161 | * `Camera.sourceType` equals `Camera.PictureSourceType.CAMERA` and the
162 | * `Camera.destinationType` equals `Camera.DestinationType.FILE_URI`.
163 | *
164 | * __Supported Platforms__
165 | *
166 | * - iOS
167 | *
168 | * @example
169 | * navigator.camera.cleanup(onSuccess, onFail);
170 | *
171 | * function onSuccess() {
172 | * console.log("Camera cleanup success.")
173 | * }
174 | *
175 | * function onFail(message) {
176 | * alert('Failed because: ' + message);
177 | * }
178 | */
179 | cameraExport.cleanup = function (successCallback, errorCallback) {
180 | exec(successCallback, errorCallback, 'Camera', 'cleanup', []);
181 | };
182 |
183 | module.exports = cameraExport;
184 |
--------------------------------------------------------------------------------
/www/CameraConstants.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | /**
23 | * @module Camera
24 | */
25 | module.exports = {
26 | /**
27 | * @description
28 | * Defines the output format of `Camera.getPicture` call.
29 | *
30 | * @enum {number}
31 | */
32 | DestinationType: {
33 | /** 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 */
34 | DATA_URL: 0,
35 | /** Return file uri (content://media/external/images/media/2 for Android) */
36 | FILE_URI: 1
37 | },
38 | /**
39 | * @enum {number}
40 | */
41 | EncodingType: {
42 | /** Return JPEG encoded image */
43 | JPEG: 0,
44 | /** Return PNG encoded image */
45 | PNG: 1
46 | },
47 | /**
48 | * @enum {number}
49 | */
50 | MediaType: {
51 | /** Allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType */
52 | PICTURE: 0,
53 | /** Allow selection of video only, ONLY RETURNS URL */
54 | VIDEO: 1,
55 | /** Allow selection from all media types */
56 | ALLMEDIA: 2
57 | },
58 | /**
59 | * @description
60 | * Defines the output format of `Camera.getPicture` call.
61 | *
62 | * @enum {number}
63 | */
64 | PictureSourceType: {
65 | /** Choose image from the device's photo library (same as SAVEDPHOTOALBUM for Android) */
66 | PHOTOLIBRARY: 0,
67 | /** Take picture from camera */
68 | CAMERA: 1,
69 | /** Choose image only from the device's Camera Roll album (same as PHOTOLIBRARY for Android) */
70 | SAVEDPHOTOALBUM: 2
71 | },
72 | /**
73 | * Matches iOS UIPopoverArrowDirection constants to specify arrow location on popover.
74 | * @enum {number}
75 | */
76 | PopoverArrowDirection: {
77 | ARROW_UP: 1,
78 | ARROW_DOWN: 2,
79 | ARROW_LEFT: 4,
80 | ARROW_RIGHT: 8,
81 | ARROW_ANY: 15
82 | },
83 | /**
84 | * @enum {number}
85 | */
86 | Direction: {
87 | /** Use the back-facing camera */
88 | BACK: 0,
89 | /** Use the front-facing camera */
90 | FRONT: 1
91 | }
92 | };
93 |
--------------------------------------------------------------------------------
/www/CameraPopoverHandle.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | /**
23 | * @ignore in favour of iOS' one
24 | * A handle to an image picker popover.
25 | */
26 | const CameraPopoverHandle = function () {
27 | this.setPosition = function (popoverOptions) {
28 | console.log('CameraPopoverHandle.setPosition is only supported on iOS.');
29 | };
30 | };
31 |
32 | module.exports = CameraPopoverHandle;
33 |
--------------------------------------------------------------------------------
/www/CameraPopoverOptions.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | const Camera = require('./Camera');
23 |
24 | /**
25 | * @namespace navigator
26 | */
27 |
28 | /**
29 | * iOS-only parameters that specify the anchor element location and arrow
30 | * direction of the popover when selecting images from an iPad's library
31 | * or album.
32 | * Note that the size of the popover may change to adjust to the
33 | * direction of the arrow and orientation of the screen. Make sure to
34 | * account for orientation changes when specifying the anchor element
35 | * location.
36 | * @module CameraPopoverOptions
37 | * @param {Number} [x=0] - x pixel coordinate of screen element onto which to anchor the popover.
38 | * @param {Number} [y=32] - y pixel coordinate of screen element onto which to anchor the popover.
39 | * @param {Number} [width=320] - width, in pixels, of the screen element onto which to anchor the popover.
40 | * @param {Number} [height=480] - height, in pixels, of the screen element onto which to anchor the popover.
41 | * @param {module:Camera.PopoverArrowDirection} [arrowDir=ARROW_ANY] - Direction the arrow on the popover should point.
42 | * @param {Number} [popoverWidth=0] - width of the popover (0 or not specified will use apple's default width).
43 | * @param {Number} [popoverHeight=0] - height of the popover (0 or not specified will use apple's default height).
44 | */
45 | const CameraPopoverOptions = function (x, y, width, height, arrowDir, popoverWidth, popoverHeight) {
46 | // information of rectangle that popover should be anchored to
47 | this.x = x || 0;
48 | this.y = y || 32;
49 | this.width = width || 320;
50 | this.height = height || 480;
51 | this.arrowDir = arrowDir || Camera.PopoverArrowDirection.ARROW_ANY;
52 | this.popoverWidth = popoverWidth || 0;
53 | this.popoverHeight = popoverHeight || 0;
54 | };
55 |
56 | module.exports = CameraPopoverOptions;
57 |
--------------------------------------------------------------------------------
/www/ios/CameraPopoverHandle.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing,
14 | * software distributed under the License is distributed on an
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | * KIND, either express or implied. See the License for the
17 | * specific language governing permissions and limitations
18 | * under the License.
19 | *
20 | */
21 |
22 | const exec = require('cordova/exec');
23 |
24 | /**
25 | * @namespace navigator
26 | */
27 |
28 | /**
29 | * A handle to an image picker popover.
30 | *
31 | * __Supported Platforms__
32 | *
33 | * - iOS
34 | *
35 | * @example
36 | * navigator.camera.getPicture(onSuccess, onFail,
37 | * {
38 | * destinationType: Camera.DestinationType.FILE_URI,
39 | * sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
40 | * popoverOptions: new CameraPopoverOptions(300, 300, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY, 300, 600)
41 | * });
42 | *
43 | * // Reposition the popover if the orientation changes.
44 | * window.onorientationchange = function() {
45 | * var cameraPopoverHandle = new CameraPopoverHandle();
46 | * var cameraPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY, 400, 500);
47 | * cameraPopoverHandle.setPosition(cameraPopoverOptions);
48 | * }
49 | * @module CameraPopoverHandle
50 | */
51 | const CameraPopoverHandle = function () {
52 | /**
53 | * Can be used to reposition the image selection dialog,
54 | * for example, when the device orientation changes.
55 | * @memberof CameraPopoverHandle
56 | * @instance
57 | * @method setPosition
58 | * @param {module:CameraPopoverOptions} popoverOptions
59 | */
60 | this.setPosition = function (popoverOptions) {
61 | const args = [popoverOptions];
62 | exec(null, null, 'Camera', 'repositionPopover', args);
63 | };
64 | };
65 |
66 | module.exports = CameraPopoverHandle;
67 |
--------------------------------------------------------------------------------