Compare commits
1 Commits
master
...
bugfix/pr5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8270dbb227 |
@ -1,27 +0,0 @@
|
||||
aliases:
|
||||
- &save-cache-yarn
|
||||
key: yarn-packages-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
- ~/.cache/yarn
|
||||
- &restore-cache-yarn
|
||||
name: Restore Yarn Package Cache
|
||||
keys:
|
||||
- yarn-packages-{{ checksum "yarn.lock" }}
|
||||
|
||||
defaults: &defaults
|
||||
working_directory: ~/react-native-image-picker
|
||||
docker:
|
||||
- image: circleci/node:10
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache: *restore-cache-yarn
|
||||
- run:
|
||||
name: Yarn Install
|
||||
command: |
|
||||
yarn install --frozen-lockfile --no-progress --non-interactive --cache-folder ~/.cache/yarn
|
||||
- save_cache: *save-cache-yarn
|
||||
@ -1,7 +0,0 @@
|
||||
typings
|
||||
node_modules
|
||||
example/android-bundle.js
|
||||
example/ios-bundle.js
|
||||
|
||||
# generated by bob
|
||||
lib
|
||||
52
.eslintrc.js
@ -1,52 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
const typescriptEslintRecommended = require('@typescript-eslint/eslint-plugin/dist/configs/recommended.json');
|
||||
const typescriptEslintPrettier = require('eslint-config-prettier/@typescript-eslint');
|
||||
|
||||
module.exports = {
|
||||
extends: ['@react-native-community'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
// Apply the recommended Typescript defaults and the prettier overrides to all Typescript files
|
||||
rules: Object.assign(
|
||||
typescriptEslintRecommended.rules,
|
||||
typescriptEslintPrettier.rules,
|
||||
{
|
||||
'@typescript-eslint/explicit-member-accessibility': 'off',
|
||||
},
|
||||
),
|
||||
},
|
||||
{
|
||||
files: ['example/**/*.ts', 'example/**/*.tsx'],
|
||||
rules: {
|
||||
// Turn off rules which are useless and annoying for the example files files
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'react-native/no-inline-styles': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/__tests__/**/*.ts', '**/*.spec.ts'],
|
||||
env: {
|
||||
jest: true,
|
||||
},
|
||||
rules: {
|
||||
// Turn off rules which are useless and annoying for unit test files
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
rules: {
|
||||
'no-dupe-class-members': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
1
.gitattributes
vendored
@ -1 +0,0 @@
|
||||
*.pbxproj -text
|
||||
41
.github/stale.yml
vendored
@ -1,41 +0,0 @@
|
||||
# Configuration for probot-stale based on: https://github.com/facebook/react-native/blob/master/.github/stale.yml
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 60
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
|
||||
daysUntilClose: 7
|
||||
|
||||
# Issues or Pull Requests.
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- discussion
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Set to true to ignore issues with an assignee (defaults to false)
|
||||
exemptAssignees: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: stale
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions. You may also mark this issue as a "discussion" and I
|
||||
will leave this open.
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
closeComment: >
|
||||
Closing this issue after a prolonged period of inactivity. Fell free to reopen
|
||||
this issue, if this still affecting you.
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 30
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
only: issues
|
||||
70
.gitignore
vendored
@ -1,17 +1,15 @@
|
||||
# OSX
|
||||
#
|
||||
.DS_Store
|
||||
### Android Studio ###
|
||||
.idea/
|
||||
.gradle/
|
||||
local.properties
|
||||
|
||||
# node.js
|
||||
#
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
### Xcode ###
|
||||
|
||||
|
||||
# Xcode
|
||||
#
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData/
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
@ -20,42 +18,22 @@ build/
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
xcuserdata/
|
||||
|
||||
## Other
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
project.xcworkspace
|
||||
*.xccheckout
|
||||
*.xcscmblueprint
|
||||
|
||||
# CocoaPods
|
||||
/ios/Pods/
|
||||
### /Xcode ###
|
||||
|
||||
# Android/IntelliJ
|
||||
#
|
||||
build/
|
||||
.idea
|
||||
.gradle
|
||||
local.properties
|
||||
### OS X
|
||||
.DS_Store
|
||||
|
||||
### Node
|
||||
node_modules
|
||||
*.log
|
||||
yarn.lock
|
||||
|
||||
## Android iml
|
||||
*.iml
|
||||
|
||||
# BUCK
|
||||
buck-out/
|
||||
\.buckd/
|
||||
debug.keystore
|
||||
|
||||
# Editor config
|
||||
.vscode
|
||||
|
||||
# Outputs
|
||||
coverage
|
||||
|
||||
.tmp
|
||||
example/android-bundle.js
|
||||
example/ios-bundle.js
|
||||
index.android.bundle
|
||||
index.ios.bundle
|
||||
|
||||
# generated by bob
|
||||
lib/
|
||||
@ -1,4 +1,3 @@
|
||||
example/
|
||||
Example/
|
||||
images/
|
||||
node_modules/
|
||||
yarn.lock
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
{
|
||||
"requirePragma": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"bracketSpacing": false,
|
||||
"jsxBracketSameLine": true
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
{
|
||||
"ignore_dirs": [".git", "node_modules", "example"]
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
# Global owners
|
||||
* @johan-dutoit @janicduplessis
|
||||
@ -1,49 +0,0 @@
|
||||
# Contributing to React Native ImagePicker
|
||||
|
||||
## Development Process
|
||||
All work on React Native ImagePicker happens directly on GitHub. Contributors send pull requests which go through a review process.
|
||||
|
||||
> **Working on your first pull request?** You can learn how from this *free* series: [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
|
||||
|
||||
1. Fork the repo and create your branch from `master` (a guide on [how to fork a repository](https://help.github.com/articles/fork-a-repo/)).
|
||||
2. Run `yarn` or `npm install` to install all required dependencies.
|
||||
3. Now you are ready to make your changes!
|
||||
|
||||
## Tests & Verifications
|
||||
Currently we use `TypeScript` for typechecking, `eslint` with `prettier` for linting and formatting the code, and `jest` for unit testing.
|
||||
|
||||
* `yarn test`: Run all tests and validations.
|
||||
* `yarn validate:android`: Run Spotless style checker on the Java code.
|
||||
* `yarn validate:eslint`: Run `eslint`.
|
||||
* `yarn validate:eslint --fix`: Run `eslint` and automatically fix issues. This is useful for correcting code formatting.
|
||||
* `yarn validate:typescript`: Run `typescript` typechecking.
|
||||
* `yarn test:jest`: Run unit tests with `jest`.
|
||||
|
||||
## Sending a pull request
|
||||
When you're sending a pull request:
|
||||
|
||||
* Prefer small pull requests focused on one change.
|
||||
* Verify that all tests and validations are passing.
|
||||
* Follow the pull request template when opening a pull request.
|
||||
|
||||
## Commit message convention
|
||||
We prefix our commit messages with one of the following to signify the kind of change:
|
||||
|
||||
* **build**: Changes that affect the build system or external dependencies.
|
||||
* **ci**, **chore**: Changes to our CI configuration files and scripts.
|
||||
* **docs**: Documentation only changes.
|
||||
* **feat**: A new feature.
|
||||
* **fix**: A bug fix.
|
||||
* **perf**: A code change that improves performance.
|
||||
* **refactor**: A code change that neither fixes a bug nor adds a feature.
|
||||
* **style**: Changes that do not affect the meaning of the code.
|
||||
* **test**: Adding missing tests or correcting existing tests.
|
||||
|
||||
## Release process
|
||||
We use [Semantic Release](http://semantic-release.org) to automatically release new versions of the library when changes are merged into master. Using the commit message convention described above, it will detect if we need to release a patch, minor, or major version of the library.
|
||||
|
||||
## Reporting issues
|
||||
You can report issues on our [bug tracker](https://github.com/react-native-community/react-native-ImagePicker/issues). Please search for existing issues and follow the issue template when opening an issue.
|
||||
|
||||
## License
|
||||
By contributing to React Native ImagePicker, you agree that your contributions will be licensed under the **MIT** license.
|
||||
65
Example/.flowconfig
Normal file
@ -0,0 +1,65 @@
|
||||
[ignore]
|
||||
|
||||
# We fork some components by platform.
|
||||
.*/*.web.js
|
||||
.*/*.android.js
|
||||
|
||||
# Some modules have their own node_modules with overlap
|
||||
.*/node_modules/node-haste/.*
|
||||
|
||||
# Ugh
|
||||
.*/node_modules/babel.*
|
||||
.*/node_modules/babylon.*
|
||||
.*/node_modules/invariant.*
|
||||
|
||||
# Ignore react and fbjs where there are overlaps, but don't ignore
|
||||
# anything that react-native relies on
|
||||
.*/node_modules/fbjs/lib/Map.js
|
||||
.*/node_modules/fbjs/lib/Promise.js
|
||||
.*/node_modules/fbjs/lib/fetch.js
|
||||
.*/node_modules/fbjs/lib/ExecutionEnvironment.js
|
||||
.*/node_modules/fbjs/lib/isEmpty.js
|
||||
.*/node_modules/fbjs/lib/crc32.js
|
||||
.*/node_modules/fbjs/lib/ErrorUtils.js
|
||||
|
||||
# Flow has a built-in definition for the 'react' module which we prefer to use
|
||||
# over the currently-untyped source
|
||||
.*/node_modules/react/react.js
|
||||
.*/node_modules/react/lib/React.js
|
||||
.*/node_modules/react/lib/ReactDOM.js
|
||||
|
||||
# Ignore commoner tests
|
||||
.*/node_modules/commoner/test/.*
|
||||
|
||||
# See https://github.com/facebook/flow/issues/442
|
||||
.*/react-tools/node_modules/commoner/lib/reader.js
|
||||
|
||||
# Ignore jest
|
||||
.*/node_modules/jest-cli/.*
|
||||
|
||||
# Ignore Website
|
||||
.*/website/.*
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
node_modules/react-native/Libraries/react-native/react-native-interface.js
|
||||
|
||||
[options]
|
||||
module.system=haste
|
||||
|
||||
munge_underscores=true
|
||||
|
||||
module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
|
||||
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\)$' -> 'RelativeImageStub'
|
||||
|
||||
suppress_type=$FlowIssue
|
||||
suppress_type=$FlowFixMe
|
||||
suppress_type=$FixMe
|
||||
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
|
||||
[version]
|
||||
0.21.0
|
||||
34
Example/.gitignore
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
# OSX
|
||||
#
|
||||
.DS_Store
|
||||
|
||||
# Xcode
|
||||
#
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
project.xcworkspace
|
||||
|
||||
# Android/IJ
|
||||
#
|
||||
.idea
|
||||
.gradle
|
||||
local.properties
|
||||
|
||||
# node.js
|
||||
#
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
@ -1,56 +1,53 @@
|
||||
/** @format */
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Image,
|
||||
PixelRatio,
|
||||
AppRegistry,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
PixelRatio,
|
||||
TouchableOpacity,
|
||||
Image,
|
||||
} from 'react-native';
|
||||
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
|
||||
export default class App extends React.Component {
|
||||
|
||||
state = {
|
||||
avatarSource: null,
|
||||
videoSource: null,
|
||||
videoSource: null
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.selectPhotoTapped = this.selectPhotoTapped.bind(this);
|
||||
this.selectVideoTapped = this.selectVideoTapped.bind(this);
|
||||
}
|
||||
|
||||
selectPhotoTapped() {
|
||||
const options = {
|
||||
quality: 1.0,
|
||||
maxWidth: 500,
|
||||
maxHeight: 500,
|
||||
storageOptions: {
|
||||
skipBackup: true,
|
||||
},
|
||||
skipBackup: true
|
||||
}
|
||||
};
|
||||
|
||||
ImagePicker.showImagePicker(options, response => {
|
||||
ImagePicker.showImagePicker(options, (response) => {
|
||||
console.log('Response = ', response);
|
||||
|
||||
if (response.didCancel) {
|
||||
console.log('User cancelled photo picker');
|
||||
} else if (response.error) {
|
||||
}
|
||||
else if (response.error) {
|
||||
console.log('ImagePicker Error: ', response.error);
|
||||
} else if (response.customButton) {
|
||||
}
|
||||
else if (response.customButton) {
|
||||
console.log('User tapped custom button: ', response.customButton);
|
||||
} else {
|
||||
let source = {uri: response.uri};
|
||||
}
|
||||
else {
|
||||
let source = { uri: response.uri };
|
||||
|
||||
// You can also display the image using data:
|
||||
// let source = { uri: 'data:image/jpeg;base64,' + response.data };
|
||||
|
||||
this.setState({
|
||||
avatarSource: source,
|
||||
avatarSource: source
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -61,21 +58,24 @@ export default class App extends React.Component {
|
||||
title: 'Video Picker',
|
||||
takePhotoButtonTitle: 'Take Video...',
|
||||
mediaType: 'video',
|
||||
videoQuality: 'medium',
|
||||
videoQuality: 'medium'
|
||||
};
|
||||
|
||||
ImagePicker.showImagePicker(options, response => {
|
||||
ImagePicker.showImagePicker(options, (response) => {
|
||||
console.log('Response = ', response);
|
||||
|
||||
if (response.didCancel) {
|
||||
console.log('User cancelled video picker');
|
||||
} else if (response.error) {
|
||||
}
|
||||
else if (response.error) {
|
||||
console.log('ImagePicker Error: ', response.error);
|
||||
} else if (response.customButton) {
|
||||
}
|
||||
else if (response.customButton) {
|
||||
console.log('User tapped custom button: ', response.customButton);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
this.setState({
|
||||
videoSource: response.uri,
|
||||
videoSource: response.uri
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -85,13 +85,10 @@ export default class App extends React.Component {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<TouchableOpacity onPress={this.selectPhotoTapped.bind(this)}>
|
||||
<View
|
||||
style={[styles.avatar, styles.avatarContainer, {marginBottom: 20}]}>
|
||||
{this.state.avatarSource === null ? (
|
||||
<Text>Select a Photo</Text>
|
||||
) : (
|
||||
<Image style={styles.avatar} source={this.state.avatarSource} />
|
||||
)}
|
||||
<View style={[styles.avatar, styles.avatarContainer, {marginBottom: 20}]}>
|
||||
{ this.state.avatarSource === null ? <Text>Select a Photo</Text> :
|
||||
<Image style={styles.avatar} source={this.state.avatarSource} />
|
||||
}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
@ -101,14 +98,13 @@ export default class App extends React.Component {
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
{this.state.videoSource && (
|
||||
<Text style={{margin: 8, textAlign: 'center'}}>
|
||||
{this.state.videoSource}
|
||||
</Text>
|
||||
)}
|
||||
{ this.state.videoSource &&
|
||||
<Text style={{margin: 8, textAlign: 'center'}}>{this.state.videoSource}</Text>
|
||||
}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@ -116,17 +112,17 @@ const styles = StyleSheet.create({
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
backgroundColor: '#F5FCFF'
|
||||
},
|
||||
avatarContainer: {
|
||||
borderColor: '#9B9B9B',
|
||||
borderWidth: 1 / PixelRatio.get(),
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
avatar: {
|
||||
borderRadius: 75,
|
||||
width: 150,
|
||||
height: 150,
|
||||
},
|
||||
height: 150
|
||||
}
|
||||
});
|
||||
18
Example/android/Example.iml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id="Example" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="java-gradle" name="Java-Gradle">
|
||||
<configuration>
|
||||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
|
||||
<option name="BUILDABLE" value="false" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@ -1,17 +1,18 @@
|
||||
import re
|
||||
|
||||
# To learn about Buck see [Docs](https://buckbuild.com/).
|
||||
# To run your application with Buck:
|
||||
# - install Buck
|
||||
# - `npm start` - to start the packager
|
||||
# - `cd android`
|
||||
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
|
||||
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US`
|
||||
# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
|
||||
# - `buck install -r android/app` - compile, install and run application
|
||||
#
|
||||
|
||||
lib_deps = []
|
||||
|
||||
for jarfile in glob(['libs/*.jar']):
|
||||
name = 'jars__' + jarfile[jarfile.rindex('/') + 1: jarfile.rindex('.jar')]
|
||||
name = 'jars__' + re.sub(r'^.*/([^/]+)\.jar$', r'\1', jarfile)
|
||||
lib_deps.append(':' + name)
|
||||
prebuilt_jar(
|
||||
name = name,
|
||||
@ -19,7 +20,7 @@ for jarfile in glob(['libs/*.jar']):
|
||||
)
|
||||
|
||||
for aarfile in glob(['libs/*.aar']):
|
||||
name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')]
|
||||
name = 'aars__' + re.sub(r'^.*/([^/]+)\.aar$', r'\1', aarfile)
|
||||
lib_deps.append(':' + name)
|
||||
android_prebuilt_aar(
|
||||
name = name,
|
||||
@ -27,39 +28,39 @@ for aarfile in glob(['libs/*.aar']):
|
||||
)
|
||||
|
||||
android_library(
|
||||
name = "all-libs",
|
||||
exported_deps = lib_deps,
|
||||
name = 'all-libs',
|
||||
exported_deps = lib_deps
|
||||
)
|
||||
|
||||
android_library(
|
||||
name = "app-code",
|
||||
srcs = glob([
|
||||
"src/main/java/**/*.java",
|
||||
]),
|
||||
deps = [
|
||||
":all-libs",
|
||||
":build_config",
|
||||
":res",
|
||||
],
|
||||
name = 'app-code',
|
||||
srcs = glob([
|
||||
'src/main/java/**/*.java',
|
||||
]),
|
||||
deps = [
|
||||
':all-libs',
|
||||
':build_config',
|
||||
':res',
|
||||
],
|
||||
)
|
||||
|
||||
android_build_config(
|
||||
name = "build_config",
|
||||
package = "com.example",
|
||||
name = 'build_config',
|
||||
package = 'com.autoblogvr',
|
||||
)
|
||||
|
||||
android_resource(
|
||||
name = "res",
|
||||
package = "com.example",
|
||||
res = "src/main/res",
|
||||
name = 'res',
|
||||
res = 'src/main/res',
|
||||
package = 'com.autoblogvr',
|
||||
)
|
||||
|
||||
android_binary(
|
||||
name = "app",
|
||||
keystore = "//android/keystores:debug",
|
||||
manifest = "src/main/AndroidManifest.xml",
|
||||
package_type = "debug",
|
||||
deps = [
|
||||
":app-code",
|
||||
],
|
||||
name = 'app',
|
||||
package_type = 'debug',
|
||||
manifest = 'src/main/AndroidManifest.xml',
|
||||
keystore = '//android/keystores:debug',
|
||||
deps = [
|
||||
':app-code',
|
||||
],
|
||||
)
|
||||
@ -9,7 +9,7 @@ import com.android.build.OutputFile
|
||||
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
|
||||
* bundle directly from the development server. Below you can see all the possible configurations
|
||||
* and their defaults. If you decide to add a configuration block, make sure to add it before the
|
||||
* `apply from: "../../node_modules/react-native/react.gradle"` line.
|
||||
* `apply from: "react.gradle"` line.
|
||||
*
|
||||
* project.ext.react = [
|
||||
* // the name of the generated asset file containing your JS bundle
|
||||
@ -33,13 +33,6 @@ import com.android.build.OutputFile
|
||||
* // bundleInPaidRelease: true,
|
||||
* // bundleInBeta: true,
|
||||
*
|
||||
* // whether to disable dev mode in custom build variants (by default only disabled in release)
|
||||
* // for example: to disable dev mode in the staging build type (if configured)
|
||||
* devDisabledInStaging: true,
|
||||
* // The configuration property can be in the following formats
|
||||
* // 'devDisabledIn${productFlavor}${buildType}'
|
||||
* // 'devDisabledIn${buildType}'
|
||||
*
|
||||
* // the root of your project, i.e. where "package.json" lives
|
||||
* root: "../../",
|
||||
*
|
||||
@ -62,20 +55,10 @@ import com.android.build.OutputFile
|
||||
* // date; if you have any other folders that you want to ignore for performance reasons (gradle
|
||||
* // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
|
||||
* // for example, you might want to remove it from here.
|
||||
* inputExcludes: ["android/**", "ios/**"],
|
||||
*
|
||||
* // override which node gets called and with what additional arguments
|
||||
* nodeExecutableAndArgs: ["node"],
|
||||
*
|
||||
* // supply additional arguments to the packager
|
||||
* extraPackagerArgs: []
|
||||
* inputExcludes: ["android/**", "ios/**"]
|
||||
* ]
|
||||
*/
|
||||
|
||||
project.ext.react = [
|
||||
entryFile: "index.js"
|
||||
]
|
||||
|
||||
apply from: "../../node_modules/react-native/react.gradle"
|
||||
|
||||
/**
|
||||
@ -94,13 +77,13 @@ def enableSeparateBuildPerCPUArchitecture = false
|
||||
def enableProguardInReleaseBuilds = false
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "23.0.1"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.example"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 22
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
ndk {
|
||||
@ -137,15 +120,9 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':react-native-image-picker')
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
|
||||
implementation "com.facebook.react:react-native:+" // From node_modules
|
||||
}
|
||||
compile fileTree(dir: "libs", include: ["*.jar"])
|
||||
compile "com.android.support:appcompat-v7:23.0.1"
|
||||
compile "com.facebook.react:react-native:+" // From node_modules
|
||||
|
||||
// Run this once to be able to run the application with BUCK
|
||||
// puts all compile dependencies into folder libs for BUCK to use
|
||||
task copyDownloadableDepsToLibs(type: Copy) {
|
||||
from configurations.compile
|
||||
into 'libs'
|
||||
compile project(':react-native-image-picker')
|
||||
}
|
||||
67
Example/android/app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Disabling obfuscation is useful if you collect stack traces from production crashes
|
||||
# (unless you are using a system that supports de-obfuscate the stack traces).
|
||||
-dontobfuscate
|
||||
|
||||
# React Native
|
||||
|
||||
# Keep our interfaces so they can be used by other ProGuard rules.
|
||||
# See http://sourceforge.net/p/proguard/bugs/466/
|
||||
-keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
|
||||
-keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
|
||||
|
||||
# Do not strip any method/class that is annotated with @DoNotStrip
|
||||
-keep @com.facebook.proguard.annotations.DoNotStrip class *
|
||||
-keepclassmembers class * {
|
||||
@com.facebook.proguard.annotations.DoNotStrip *;
|
||||
}
|
||||
|
||||
-keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {
|
||||
void set*(***);
|
||||
*** get*();
|
||||
}
|
||||
|
||||
-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
|
||||
-keep class * extends com.facebook.react.bridge.NativeModule { *; }
|
||||
-keepclassmembers,includedescriptorclasses class * { native <methods>; }
|
||||
-keepclassmembers class * { @com.facebook.react.uimanager.UIProp <fields>; }
|
||||
-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp <methods>; }
|
||||
-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup <methods>; }
|
||||
|
||||
-dontwarn com.facebook.react.**
|
||||
|
||||
# okhttp
|
||||
|
||||
-keepattributes Signature
|
||||
-keepattributes *Annotation*
|
||||
-keep class com.squareup.okhttp.** { *; }
|
||||
-keep interface com.squareup.okhttp.** { *; }
|
||||
-dontwarn com.squareup.okhttp.**
|
||||
|
||||
# okio
|
||||
|
||||
-keep class sun.misc.Unsafe { *; }
|
||||
-dontwarn java.nio.file.*
|
||||
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
|
||||
-dontwarn okio.**
|
||||
|
||||
# stetho
|
||||
|
||||
-dontwarn com.facebook.stetho.**
|
||||
@ -2,21 +2,21 @@
|
||||
package="com.example">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
android:allowBackup="true"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:allowBackup="false"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
@ -1,17 +1,19 @@
|
||||
package com.example;
|
||||
|
||||
import android.app.Application;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.ReactApplication;
|
||||
import com.imagepicker.ImagePickerPackage;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.shell.MainReactPackage;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.imagepicker.ImagePickerPackage;
|
||||
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
|
||||
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
|
||||
@ -27,21 +29,10 @@ public class MainApplication extends Application implements ReactApplication {
|
||||
new ImagePickerPackage()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJSMainModuleName() {
|
||||
return "index";
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
return mReactNativeHost;
|
||||
}
|
||||
}
|
||||
BIN
Example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
Example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
Example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
Example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
@ -1,19 +1,11 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
buildToolsVersion = "27.0.3"
|
||||
minSdkVersion = 16
|
||||
compileSdkVersion = 27
|
||||
targetSdkVersion = 26
|
||||
supportLibVersion = "27.1.1"
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.1.4'
|
||||
classpath 'com.android.tools.build:gradle:2.2.+'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
@ -23,7 +15,6 @@ buildscript {
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
google()
|
||||
jcenter()
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
@ -31,9 +22,3 @@ allprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '4.4'
|
||||
distributionUrl = distributionUrl.replace("bin", "all")
|
||||
}
|
||||
@ -16,3 +16,5 @@
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
android.useDeprecatedNdk=true
|
||||
BIN
Example/android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
@ -1,5 +1,6 @@
|
||||
#Thu Jun 09 11:55:07 EDT 2016
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
|
||||
110
example/android/gradlew → Example/android/gradlew
vendored
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
@ -6,6 +6,47 @@
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
@ -20,49 +61,9 @@ while [ -h "$PRG" ] ; do
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
@ -89,7 +90,7 @@ location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
@ -113,7 +114,6 @@ fi
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
@ -154,19 +154,11 @@ if $cygwin ; then
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
@ -8,14 +8,14 @@
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
@ -46,9 +46,10 @@ echo location of your Java installation.
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
@ -59,6 +60,11 @@ set _SKIP=2
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
6
Example/android/settings.gradle
Normal file
@ -0,0 +1,6 @@
|
||||
rootProject.name = 'Example'
|
||||
|
||||
include ':app'
|
||||
|
||||
include ':react-native-image-picker'
|
||||
project(':react-native-image-picker').projectDir = new File(settingsDir, '../../android')
|
||||
15
Example/index.android.js
Normal file
@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
AppRegistry
|
||||
} from 'react-native';
|
||||
import App from './App';
|
||||
|
||||
class Example extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<App />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AppRegistry.registerComponent('Example', () => Example);
|
||||
15
Example/index.ios.js
Normal file
@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
AppRegistry
|
||||
} from 'react-native';
|
||||
import App from './App';
|
||||
|
||||
class Example extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<App />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AppRegistry.registerComponent('Example', () => Example);
|
||||
833
Example/ios/Example.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,833 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
|
||||
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
|
||||
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
|
||||
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
|
||||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
|
||||
019E52E21DEE2CD7000A5FCC /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 019E52C01DEE2CC7000A5FCC /* libRCTAnimation.a */; };
|
||||
01BBD31C1C9077A5000A3935 /* libRNImagePicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 01BBD31B1C907630000A3935 /* libRNImagePicker.a */; };
|
||||
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
|
||||
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
|
||||
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
|
||||
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTActionSheet;
|
||||
};
|
||||
00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTGeolocation;
|
||||
};
|
||||
00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
|
||||
remoteInfo = RCTImage;
|
||||
};
|
||||
00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B511DB1A9E6C8500147676;
|
||||
remoteInfo = RCTNetwork;
|
||||
};
|
||||
00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
|
||||
remoteInfo = RCTVibration;
|
||||
};
|
||||
019E52BF1DEE2CC7000A5FCC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 019E52B91DEE2CC7000A5FCC /* RCTAnimation.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTAnimation;
|
||||
};
|
||||
019E52C11DEE2CC7000A5FCC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 019E52B91DEE2CC7000A5FCC /* RCTAnimation.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 2D2A28201D9B03D100D4039D;
|
||||
remoteInfo = "RCTAnimation-tvOS";
|
||||
};
|
||||
019E52C61DEE2CC7000A5FCC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 2D2A283A1D9B042B00D4039D;
|
||||
remoteInfo = "RCTImage-tvOS";
|
||||
};
|
||||
019E52CA1DEE2CC7000A5FCC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 2D2A28471D9B043800D4039D;
|
||||
remoteInfo = "RCTLinking-tvOS";
|
||||
};
|
||||
019E52CE1DEE2CC7000A5FCC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 2D2A28541D9B044C00D4039D;
|
||||
remoteInfo = "RCTNetwork-tvOS";
|
||||
};
|
||||
019E52D21DEE2CC7000A5FCC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 2D2A28611D9B046600D4039D;
|
||||
remoteInfo = "RCTSettings-tvOS";
|
||||
};
|
||||
019E52D61DEE2CC7000A5FCC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 2D2A287B1D9B048500D4039D;
|
||||
remoteInfo = "RCTText-tvOS";
|
||||
};
|
||||
019E52DB1DEE2CC7000A5FCC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 2D2A28881D9B049200D4039D;
|
||||
remoteInfo = "RCTWebSocket-tvOS";
|
||||
};
|
||||
019E52DF1DEE2CC7000A5FCC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 2D2A28131D9B038B00D4039D;
|
||||
remoteInfo = "React-tvOS";
|
||||
};
|
||||
01BBD31A1C907630000A3935 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 01BBD30C1C90762F000A3935 /* RNImagePicker.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 014A3B5C1C6CF33500B6D375;
|
||||
remoteInfo = RNImagePicker;
|
||||
};
|
||||
139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTSettings;
|
||||
};
|
||||
139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
|
||||
remoteInfo = RCTWebSocket;
|
||||
};
|
||||
146834031AC3E56700842450 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
|
||||
remoteInfo = React;
|
||||
};
|
||||
78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTLinking;
|
||||
};
|
||||
832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
|
||||
remoteInfo = RCTText;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = "<group>"; };
|
||||
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = "<group>"; };
|
||||
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = "<group>"; };
|
||||
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = "<group>"; };
|
||||
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = "<group>"; };
|
||||
019E52B91DEE2CC7000A5FCC /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; };
|
||||
01BBD30C1C90762F000A3935 /* RNImagePicker.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNImagePicker.xcodeproj; path = ../../ios/RNImagePicker.xcodeproj; sourceTree = "<group>"; };
|
||||
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
|
||||
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Example/AppDelegate.h; sourceTree = "<group>"; tabWidth = 4; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Example/AppDelegate.m; sourceTree = "<group>"; tabWidth = 4; };
|
||||
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Example/Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Example/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Example/main.m; sourceTree = "<group>"; };
|
||||
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
|
||||
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
|
||||
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
146834051AC3E58100842450 /* libReact.a in Frameworks */,
|
||||
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
|
||||
019E52E21DEE2CD7000A5FCC /* libRCTAnimation.a in Frameworks */,
|
||||
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
|
||||
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
|
||||
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
|
||||
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,
|
||||
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
|
||||
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
|
||||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
|
||||
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
|
||||
01BBD31C1C9077A5000A3935 /* libRNImagePicker.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
00C302A81ABCB8CE00DB3ED1 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
00C302B61ABCB90400DB3ED1 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
00C302BC1ABCB91800DB3ED1 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00C302C01ABCB91800DB3ED1 /* libRCTImage.a */,
|
||||
019E52C71DEE2CC7000A5FCC /* libRCTImage-tvOS.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
00C302D41ABCB9D200DB3ED1 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */,
|
||||
019E52CF1DEE2CC7000A5FCC /* libRCTNetwork-tvOS.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
00C302E01ABCB9EE00DB3ED1 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
019E52BA1DEE2CC7000A5FCC /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
019E52C01DEE2CC7000A5FCC /* libRCTAnimation.a */,
|
||||
019E52C21DEE2CC7000A5FCC /* libRCTAnimation-tvOS.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
01BBD30D1C90762F000A3935 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
01BBD31B1C907630000A3935 /* libRNImagePicker.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
139105B71AF99BAD00B5F7CC /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,
|
||||
019E52D31DEE2CC7000A5FCC /* libRCTSettings-tvOS.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
139FDEE71B06529A00C62182 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
|
||||
019E52DC1DEE2CC7000A5FCC /* libRCTWebSocket-tvOS.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FAE1A68108700A75B9A /* Example */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
);
|
||||
name = Example;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
146834001AC3E56700842450 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
146834041AC3E56700842450 /* libReact.a */,
|
||||
019E52E01DEE2CC7000A5FCC /* libReact-tvOS.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
78C398B11ACF4ADC00677621 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
78C398B91ACF4ADC00677621 /* libRCTLinking.a */,
|
||||
019E52CB1DEE2CC7000A5FCC /* libRCTLinking-tvOS.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
01BBD30C1C90762F000A3935 /* RNImagePicker.xcodeproj */,
|
||||
146833FF1AC3E56700842450 /* React.xcodeproj */,
|
||||
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
|
||||
019E52B91DEE2CC7000A5FCC /* RCTAnimation.xcodeproj */,
|
||||
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
|
||||
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,
|
||||
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
|
||||
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */,
|
||||
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */,
|
||||
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
|
||||
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
|
||||
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
832341B11AAA6A8300B99B32 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
832341B51AAA6A8300B99B32 /* libRCTText.a */,
|
||||
019E52D71DEE2CC7000A5FCC /* libRCTText-tvOS.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* Example */,
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 2;
|
||||
};
|
||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* Example.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
13B07F861A680F5B00A75B9A /* Example */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Example" */;
|
||||
buildPhases = (
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Example;
|
||||
productName = "Hello World";
|
||||
productReference = 13B07F961A680F5B00A75B9A /* Example.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0820;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
13B07F861A680F5B00A75B9A = {
|
||||
DevelopmentTeam = X4WMF529W9;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Example" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
{
|
||||
ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
|
||||
ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 019E52BA1DEE2CC7000A5FCC /* Products */;
|
||||
ProjectRef = 019E52B91DEE2CC7000A5FCC /* RCTAnimation.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
|
||||
ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */;
|
||||
ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 78C398B11ACF4ADC00677621 /* Products */;
|
||||
ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */;
|
||||
ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */;
|
||||
ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 832341B11AAA6A8300B99B32 /* Products */;
|
||||
ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */;
|
||||
ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 139FDEE71B06529A00C62182 /* Products */;
|
||||
ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 146834001AC3E56700842450 /* Products */;
|
||||
ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 01BBD30D1C90762F000A3935 /* Products */;
|
||||
ProjectRef = 01BBD30C1C90762F000A3935 /* RNImagePicker.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* Example */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTActionSheet.a;
|
||||
remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTGeolocation.a;
|
||||
remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTImage.a;
|
||||
remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTNetwork.a;
|
||||
remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTVibration.a;
|
||||
remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
019E52C01DEE2CC7000A5FCC /* libRCTAnimation.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTAnimation.a;
|
||||
remoteRef = 019E52BF1DEE2CC7000A5FCC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
019E52C21DEE2CC7000A5FCC /* libRCTAnimation-tvOS.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = "libRCTAnimation-tvOS.a";
|
||||
remoteRef = 019E52C11DEE2CC7000A5FCC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
019E52C71DEE2CC7000A5FCC /* libRCTImage-tvOS.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = "libRCTImage-tvOS.a";
|
||||
remoteRef = 019E52C61DEE2CC7000A5FCC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
019E52CB1DEE2CC7000A5FCC /* libRCTLinking-tvOS.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = "libRCTLinking-tvOS.a";
|
||||
remoteRef = 019E52CA1DEE2CC7000A5FCC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
019E52CF1DEE2CC7000A5FCC /* libRCTNetwork-tvOS.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = "libRCTNetwork-tvOS.a";
|
||||
remoteRef = 019E52CE1DEE2CC7000A5FCC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
019E52D31DEE2CC7000A5FCC /* libRCTSettings-tvOS.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = "libRCTSettings-tvOS.a";
|
||||
remoteRef = 019E52D21DEE2CC7000A5FCC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
019E52D71DEE2CC7000A5FCC /* libRCTText-tvOS.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = "libRCTText-tvOS.a";
|
||||
remoteRef = 019E52D61DEE2CC7000A5FCC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
019E52DC1DEE2CC7000A5FCC /* libRCTWebSocket-tvOS.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = "libRCTWebSocket-tvOS.a";
|
||||
remoteRef = 019E52DB1DEE2CC7000A5FCC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
019E52E01DEE2CC7000A5FCC /* libReact-tvOS.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = "libReact-tvOS.a";
|
||||
remoteRef = 019E52DF1DEE2CC7000A5FCC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
01BBD31B1C907630000A3935 /* libRNImagePicker.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRNImagePicker.a;
|
||||
remoteRef = 01BBD31A1C907630000A3935 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTSettings.a;
|
||||
remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTWebSocket.a;
|
||||
remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
146834041AC3E56700842450 /* libReact.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libReact.a;
|
||||
remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTLinking.a;
|
||||
remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
832341B51AAA6A8300B99B32 /* libRCTText.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTText.a;
|
||||
remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Bundle React Native code and images";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
13B07FB21A68108700A75B9A /* Base */,
|
||||
);
|
||||
name = LaunchScreen.xib;
|
||||
path = Example;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
DEAD_CODE_STRIPPING = NO;
|
||||
DEVELOPMENT_TEAM = X4WMF529W9;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../node_modules/react-native/React/**",
|
||||
);
|
||||
INFOPLIST_FILE = Example/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = Example;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
DEVELOPMENT_TEAM = X4WMF529W9;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../node_modules/react-native/React/**",
|
||||
);
|
||||
INFOPLIST_FILE = Example/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = Example;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../node_modules/react-native/React/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
83CBBA211A601CBA00E9B192 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../node_modules/react-native/React/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Example" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13B07F941A680F5B00A75B9A /* Debug */,
|
||||
13B07F951A680F5B00A75B9A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Example" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
83CBBA211A601CBA00E9B192 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0940"
|
||||
LastUpgradeVersion = "0820"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "NO"
|
||||
@ -34,20 +34,6 @@
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "ExampleTests.xctest"
|
||||
BlueprintName = "ExampleTests"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
@ -56,16 +42,6 @@
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "ExampleTests.xctest"
|
||||
BlueprintName = "ExampleTests"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
16
Example/ios/Example/AppDelegate.h
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (nonatomic, strong) UIWindow *window;
|
||||
|
||||
@end
|
||||
30
Example/ios/Example/AppDelegate.m
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "RCTBundleURLProvider.h"
|
||||
#import "RCTRootView.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
NSURL *jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
|
||||
|
||||
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"Example" initialProperties:nil launchOptions:launchOptions];
|
||||
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
|
||||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
UIViewController *rootViewController = [UIViewController new];
|
||||
rootViewController.view = rootView;
|
||||
self.window.rootViewController = rootViewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -7,7 +7,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
@ -22,6 +22,17 @@
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string></string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string></string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string></string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
@ -36,19 +47,5 @@
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
|
||||
<dict>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>localhost</key>
|
||||
<dict>
|
||||
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
14
Example/package.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Example",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node node_modules/react-native/local-cli/cli.js start",
|
||||
"adb-reverse": "adb reverse tcp:8081 tcp:8081"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "15.4.1",
|
||||
"react-native": "^0.40.0",
|
||||
"react-native-image-picker": "file:../"
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-present, Facebook, Inc.
|
||||
Copyright (c) 2015 Marc Shilling
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
SOFTWARE.
|
||||
|
||||
251
README.md
@ -1,94 +1,197 @@
|
||||
# React Native Image Picker
|
||||
|
||||
[](https://badge.fury.io/js/react-native-image-picker)
|
||||
[](https://npmcharts.com/compare/react-native-image-picker?minimal=true)
|
||||

|
||||

|
||||
[](https://gitter.im/react-native-image-picker/Lobby)
|
||||
# React Native Image Picker [](https://badge.fury.io/js/react-native-image-picker) [](https://www.npmjs.org/package/react-native-image-picker)  
|
||||
|
||||
A React Native module that allows you to use native UI to select a photo/video from the device library or directly from the camera, like so:
|
||||
|
||||
🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧
|
||||
|
||||
🚧🚧🚧🚧[Help & Input Wanted](https://github.com/react-native-community/react-native-image-picker/issues/1358) 🚧🚧🚧🚧
|
||||
|
||||
🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧
|
||||
| iOS | Android |
|
||||
| --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <img title="iOS" src="https://github.com/react-community/react-native-image-picker/blob/master/images/ios-image.png"> | <img title="Android" src="https://github.com/react-community/react-native-image-picker/blob/master/images/android-image.png"> |
|
||||
iOS | Android
|
||||
------- | ----
|
||||
<img title="iOS" src="https://github.com/marcshilling/react-native-image-picker/blob/master/images/ios-image.png"> | <img title="Android" src="https://github.com/marcshilling/react-native-image-picker/blob/master/images/android-image.png">
|
||||
|
||||
#### _Before you open an issue_
|
||||
This library started as a basic bridge of the native iOS image picker, and I want to keep it that way. As such, functionality beyond what the native `UIImagePickerController` supports will not be supported here. **Multiple image selection, more control over the crop tool, and landscape support** are things missing from the native iOS functionality - **not issues with my library**. If you need these things, [react-native-image-crop-picker](https://github.com/ivpusic/react-native-image-crop-picker) might be a better choice for you.
|
||||
|
||||
This library started as a basic bridge of the native iOS image picker, and I want to keep it that way. As such, functionality beyond what the native `UIImagePickerController` supports will not be supported here. **Multiple image selection, more control over the crop tool, and landscape support** are things missing from the native iOS functionality - **not issues with my library**. If you need these things, [react-native-image-crop-picker](https://github.com/ivpusic/react-native-image-crop-picker) might be a better choice for you.
|
||||
## Table of contents
|
||||
- [Install](#install)
|
||||
- [Usage](#usage)
|
||||
- [Direct launch](#directly-launching-the-camera-or-image-library)
|
||||
- [Options](#options)
|
||||
- [Response object](#the-response-object)
|
||||
|
||||
## React Native Compatibility
|
||||
To use this library you need to ensure you match up with the correct version of React Native you are using.
|
||||
## Install
|
||||
|
||||
p.s. React Native introduced AndroidX support in 0.60, which is a **breaking change** for most libraries (incl. this one) using native Android functionality.
|
||||
### NOTE: THIS PACKAGE IS NOW BUILT FOR REACT NATIVE 0.40 OR GREATER! IF YOU NEED TO SUPPORT REACT NATIVE < 0.40, YOU SHOULD INSTALL THIS PACKAGE `@0.24`
|
||||
|
||||
| `@react-native-community/imagepicker` version | Required React Native Version |
|
||||
| ----------------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| `1.x.x` | `>= 0.60` or `>= 0.59` if using [Jetifier](https://github.com/mikehardy/jetifier) |
|
||||
| `0.x.x` | `<= 0.59` |
|
||||
`npm install react-native-image-picker@latest --save`
|
||||
|
||||
### Automatic Installation
|
||||
|
||||
## Getting Started
|
||||
`react-native link`
|
||||
|
||||
```
|
||||
yarn add react-native-image-picker
|
||||
IMPORTANT NOTE: You'll still need to perform step 4 for iOS and steps 2, 3, and 5 for Android of the manual instructions below.
|
||||
|
||||
# RN >= 0.60
|
||||
npx pod-install
|
||||
### Manual Installation
|
||||
|
||||
# RN < 0.60
|
||||
react-native link react-native-image-picker
|
||||
#### iOS
|
||||
|
||||
1. In the XCode's "Project navigator", right click on your project's Libraries folder ➜ `Add Files to <...>`
|
||||
2. Go to `node_modules` ➜ `react-native-image-picker` ➜ `ios` ➜ select `RNImagePicker.xcodeproj`
|
||||
3. Add `RNImagePicker.a` to `Build Phases -> Link Binary With Libraries`
|
||||
4. For iOS 10+, Add the `NSPhotoLibraryUsageDescription`, `NSCameraUsageDescription`, and `NSMicrophoneUsageDescription` (if allowing video) keys to your `Info.plist` with strings describing why your app needs these permissions. **Note: You will get a SIGABRT crash if you don't complete this step**
|
||||
5. Compile and have fun
|
||||
|
||||
#### Android
|
||||
1. Add the following lines to `android/settings.gradle`:
|
||||
```gradle
|
||||
include ':react-native-image-picker'
|
||||
project(':react-native-image-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-picker/android')
|
||||
```
|
||||
|
||||
2. Update the android build tools version to `2.2.+` in `android/build.gradle`:
|
||||
```gradle
|
||||
buildscript {
|
||||
...
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.+' // <- USE 2.2.+ version
|
||||
}
|
||||
...
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
3. Update the gradle version to `2.14.1` in `android/gradle/wrapper/gradle-wrapper.properties`:
|
||||
```
|
||||
...
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
|
||||
```
|
||||
|
||||
4. Add the compile line to the dependencies in `android/app/build.gradle`:
|
||||
```gradle
|
||||
dependencies {
|
||||
compile project(':react-native-image-picker')
|
||||
}
|
||||
```
|
||||
|
||||
5. Add the required permissions in `AndroidManifest.xml`:
|
||||
```xml
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
```
|
||||
|
||||
6. Add the import and link the package in `MainApplication.java`:
|
||||
```java
|
||||
import com.imagepicker.ImagePickerPackage; // <-- add this import
|
||||
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new MainReactPackage(),
|
||||
new ImagePickerPackage() // <-- add this line
|
||||
// OR if you want to customize dialog style
|
||||
new ImagePickerPackage(R.style.my_dialog_style)
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### Android (Optional)
|
||||
|
||||
Customization settings of dialog `android/app/res/values/themes.xml`:
|
||||
```xml
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="DefaultExplainingPermissionsTheme" parent="Theme.AppCompat.Light.Dialog.Alert">
|
||||
<!-- Used for the buttons -->
|
||||
<item name="colorAccent">@color/your_color</item>
|
||||
|
||||
<!-- Used for the title and text -->
|
||||
<item name="android:textColorPrimary">@color/your_color</item>
|
||||
|
||||
<!-- Used for the background -->
|
||||
<item name="android:background">@color/your_color</item>
|
||||
</style>
|
||||
<resources>
|
||||
```
|
||||
|
||||
You will also need to add `UsageDescription` on iOS and some permissions on Android, refer to the [Install doc](docs/Install.md).
|
||||
If `MainActivity` is not instance of `ReactActivity`, you will need to implement `OnImagePickerPermissionsCallback` to `MainActivity`:
|
||||
```java
|
||||
import com.imagepicker.permissions.OnImagePickerPermissionsCallback; // <- add this import
|
||||
import com.facebook.react.modules.core.PermissionListener; // <- add this import
|
||||
|
||||
public class MainActivity extends YourActivity implements OnImagePickerPermissionsCallback {
|
||||
private PermissionListener listener; // <- add this attribute
|
||||
|
||||
// Your methods here
|
||||
|
||||
// Copy from here
|
||||
|
||||
@Override
|
||||
public void setPermissionListener(PermissionListener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
|
||||
{
|
||||
if (listener != null)
|
||||
{
|
||||
listener.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
// To here
|
||||
}
|
||||
```
|
||||
This code allows to pass result of request permissions to native part.
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
var ImagePicker = require('react-native-image-picker');
|
||||
|
||||
// More info on all the options is below in the API Reference... just some common use cases shown here
|
||||
const options = {
|
||||
// More info on all the options is below in the README...just some common use cases shown here
|
||||
var options = {
|
||||
title: 'Select Avatar',
|
||||
customButtons: [{ name: 'fb', title: 'Choose Photo from Facebook' }],
|
||||
customButtons: [
|
||||
{name: 'fb', title: 'Choose Photo from Facebook'},
|
||||
],
|
||||
storageOptions: {
|
||||
skipBackup: true,
|
||||
path: 'images',
|
||||
},
|
||||
path: 'images'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The first arg is the options object for customization (it can also be null or omitted for default options),
|
||||
* The second arg is the callback which sends object: response (more info in the API Reference)
|
||||
* The second arg is the callback which sends object: response (more info below in README)
|
||||
*/
|
||||
ImagePicker.showImagePicker(options, (response) => {
|
||||
console.log('Response = ', response);
|
||||
|
||||
if (response.didCancel) {
|
||||
console.log('User cancelled image picker');
|
||||
} else if (response.error) {
|
||||
}
|
||||
else if (response.error) {
|
||||
console.log('ImagePicker Error: ', response.error);
|
||||
} else if (response.customButton) {
|
||||
}
|
||||
else if (response.customButton) {
|
||||
console.log('User tapped custom button: ', response.customButton);
|
||||
} else {
|
||||
const source = { uri: response.uri };
|
||||
}
|
||||
else {
|
||||
let source = { uri: response.uri };
|
||||
|
||||
// You can also display the image using data:
|
||||
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
|
||||
// let source = { uri: 'data:image/jpeg;base64,' + response.data };
|
||||
|
||||
this.setState({
|
||||
avatarSource: source,
|
||||
avatarSource: source
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Then later, if you want to display this image in your render() method:
|
||||
|
||||
```javascript
|
||||
<Image source={this.state.avatarSource} style={styles.uploadAvatar} />
|
||||
```
|
||||
@ -97,25 +200,69 @@ Then later, if you want to display this image in your render() method:
|
||||
|
||||
To Launch the Camera or Image Library directly (skipping the alert dialog) you can
|
||||
do the following:
|
||||
|
||||
```javascript
|
||||
// Launch Camera:
|
||||
ImagePicker.launchCamera(options, (response) => {
|
||||
ImagePicker.launchCamera(options, (response) => {
|
||||
// Same code as in above section!
|
||||
});
|
||||
|
||||
// Open Image Library:
|
||||
ImagePicker.launchImageLibrary(options, (response) => {
|
||||
ImagePicker.launchImageLibrary(options, (response) => {
|
||||
// Same code as in above section!
|
||||
});
|
||||
```
|
||||
|
||||
#### Notes
|
||||
|
||||
#### Note
|
||||
On iOS, don't assume that the absolute uri returned will persist. See [#107](/../../issues/107)
|
||||
|
||||
For more, read the [API Reference](docs/Reference.md).
|
||||
### Options
|
||||
|
||||
## License
|
||||
option | iOS | Android | Info
|
||||
------ | ---- | ------- | ----
|
||||
title | OK | OK | Specify `null` or empty string to remove the title
|
||||
cancelButtonTitle | OK | OK | Specify `null` or empty string to remove this button (Android only)
|
||||
takePhotoButtonTitle | OK | OK | Specify `null` or empty string to remove this button
|
||||
chooseFromLibraryButtonTitle | OK | OK | Specify `null` or empty string to remove this button
|
||||
customButtons | OK | OK | An array containing objects with the name and title of buttons
|
||||
cameraType | OK | - | 'front' or 'back'
|
||||
mediaType | OK | OK | 'photo', 'video', or 'mixed' on iOS, 'photo' or 'video' on Android
|
||||
maxWidth | OK | OK | Photos only
|
||||
maxHeight | OK | OK | Photos only
|
||||
quality | OK | OK | 0 to 1, photos only
|
||||
videoQuality | OK | OK | 'low', 'medium', or 'high' on iOS, 'low' or 'high' on Android
|
||||
durationLimit | OK | OK | Max video recording time, in seconds
|
||||
rotation | - | OK | Photos only, 0 to 360 degrees of rotation
|
||||
allowsEditing | OK | - | bool - enables built in iOS functionality to resize the image after selection
|
||||
noData | OK | OK | If true, disables the base64 `data` field from being generated (greatly improves performance on large photos)
|
||||
storageOptions | OK | OK | If this key is provided, the image will be saved in your app's `Documents` directory on iOS, or your app's `Pictures` directory on Android (rather than a temporary directory)
|
||||
storageOptions.skipBackup | OK | - | If true, the photo will NOT be backed up to iCloud
|
||||
storageOptions.path | OK | - | If set, will save the image at `Documents/[path]/` rather than the root `Documents`
|
||||
storageOptions.cameraRoll | OK | OK | If true, the cropped photo will be saved to the iOS Camera Roll or Android DCIM folder.
|
||||
storageOptions.waitUntilSaved | OK | - | If true, will delay the response callback until after the photo/video was saved to the Camera Roll. If the photo or video was just taken, then the file name and timestamp fields are only provided in the response object when this is true.
|
||||
permissionDenied.title | - | OK | Title of explaining permissions dialog. By default `Permission denied`.
|
||||
permissionDenied.text | - | OK | Message of explaining permissions dialog. By default `To be able to take pictures with your camera and choose images from your library.`.
|
||||
permissionDenied.reTryTitle | - | OK | Title of re-try button. By default `re-try`
|
||||
permissionDenied.okTitle | - | OK | Title of ok button. By default `I'm sure`
|
||||
|
||||
[MIT](LICENSE.md)
|
||||
### The Response Object
|
||||
|
||||
key | iOS | Android | Description
|
||||
------ | ---- | ------- | ----------------------
|
||||
didCancel | OK | OK | Informs you if the user cancelled the process
|
||||
error | OK | OK | Contains an error message, if there is one
|
||||
customButton | OK | OK | If the user tapped one of your custom buttons, contains the name of it
|
||||
data | OK | OK | The base64 encoded image data (photos only)
|
||||
uri | OK | OK | The uri to the local file asset on the device (photo or video)
|
||||
origURL | OK | - | The URL of the original asset in photo library, if it exists
|
||||
isVertical | OK | OK | Will be true if the image is vertically oriented
|
||||
width | OK | OK | Image dimensions
|
||||
height | OK | OK | Image dimensions
|
||||
fileSize | OK | OK | The file size (photos only)
|
||||
type | - | OK | The file type (photos only)
|
||||
fileName | OK (photos and videos) | OK (photos) | The file name
|
||||
path | - | OK | The file path
|
||||
latitude | OK | OK | Latitude metadata, if available
|
||||
longitude | OK | OK | Longitude metadata, if available
|
||||
timestamp | OK | OK | Timestamp metadata, if available, in ISO8601 UTC format
|
||||
originalRotation | - | OK | Rotation degrees (photos only) *See [#109](/../../issues/199)*
|
||||
|
||||
@ -1,65 +1,62 @@
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
def computeVersionName() {
|
||||
// dynamically retrieve version from package.json
|
||||
def slurper = new JsonSlurper()
|
||||
def json = slurper.parse(file('../package.json'), "utf-8")
|
||||
return json.version
|
||||
}
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath 'com.android.tools.build:gradle:2.2.+'
|
||||
}
|
||||
}
|
||||
|
||||
def getExtOrDefault(name) {
|
||||
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['ReactNativeImagePicker_' + name]
|
||||
}
|
||||
|
||||
def getExtOrIntegerDefault(name) {
|
||||
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['ReactNativeImagePicker_' + name]).toInteger()
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
|
||||
buildToolsVersion getExtOrDefault('buildToolsVersion')
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion getExtOrIntegerDefault('minSdkVersion')
|
||||
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 25
|
||||
versionCode 1
|
||||
versionName computeVersionName()
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
testOptions {
|
||||
unitTests {
|
||||
includeAndroidResources = true
|
||||
}
|
||||
unitTests.returnDefaultValues = true
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
maven {
|
||||
url "$projectDir/../node_modules/react-native/android"
|
||||
url "$projectDir/../Example/node_modules/react-native/android"
|
||||
}
|
||||
maven {
|
||||
url "$projectDir/../node_modules/jsc-android/dist"
|
||||
url "$projectDir/../../react-native/android"
|
||||
}
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api "com.facebook.react:react-native:+" // From node_modules
|
||||
compile "com.facebook.react:react-native:+" // From node_modules
|
||||
|
||||
testCompile "junit:junit:4.10"
|
||||
testCompile "org.assertj:assertj-core:1.7.0"
|
||||
testCompile "org.robolectric:robolectric:3.3.2"
|
||||
|
||||
testImplementation('org.robolectric:robolectric:4.3.1') {
|
||||
// https://github.com/robolectric/robolectric/issues/5245
|
||||
exclude group: 'com.google.auto.service', module: 'auto-service'
|
||||
}
|
||||
|
||||
testImplementation "org.powermock:powermock-api-mockito:${POWERMOCK_VERSION}"
|
||||
testImplementation "org.powermock:powermock-module-junit4:${POWERMOCK_VERSION}"
|
||||
testImplementation "org.powermock:powermock-module-junit4-rule:${POWERMOCK_VERSION}"
|
||||
testImplementation "org.powermock:powermock-classloading-xstream:${POWERMOCK_VERSION}"
|
||||
testCompile "org.easytesting:fest-assert-core:${FEST_ASSERT_CORE_VERSION}"
|
||||
testCompile "org.powermock:powermock-api-mockito:${POWERMOCK_VERSION}"
|
||||
testCompile "org.powermock:powermock-module-junit4-rule:${POWERMOCK_VERSION}"
|
||||
testCompile "org.powermock:powermock-classloading-xstream:${POWERMOCK_VERSION}"
|
||||
testCompile "org.mockito:mockito-core:${MOCKITO_CORE_VERSION}"
|
||||
}
|
||||
|
||||
@ -1,9 +1,3 @@
|
||||
POWERMOCK_VERSION=1.6.6
|
||||
|
||||
ReactNativeImagePicker_compileSdkVersion=28
|
||||
ReactNativeImagePicker_buildToolsVersion=28.0.3
|
||||
ReactNativeImagePicker_targetSdkVersion=27
|
||||
ReactNativeImagePicker_minSdkVersion=16
|
||||
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
MOCKITO_CORE_VERSION=1.+
|
||||
POWERMOCK_VERSION=1.6.2
|
||||
FEST_ASSERT_CORE_VERSION=2.0M10
|
||||
@ -1,6 +1,6 @@
|
||||
#Mon Jun 24 15:04:47 BST 2019
|
||||
#Mon Dec 28 10:00:20 PST 2015
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
>
|
||||
<application>
|
||||
<provider
|
||||
android:name="com.imagepicker.FileProvider"
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
package com.imagepicker;
|
||||
|
||||
public class FileProvider extends androidx.core.content.FileProvider {
|
||||
}
|
||||
@ -6,17 +6,15 @@ import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.Settings;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StyleRes;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
import android.util.Patterns;
|
||||
@ -30,12 +28,11 @@ import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.imagepicker.media.ImageConfig;
|
||||
import com.imagepicker.permissions.PermissionUtils;
|
||||
import com.imagepicker.permissions.OnImagePickerPermissionsCallback;
|
||||
import com.imagepicker.utils.MediaUtils;
|
||||
import com.imagepicker.utils.MediaUtils.ReadExifResult;
|
||||
import com.imagepicker.utils.ReadableMapUtils;
|
||||
import com.imagepicker.utils.RealPathUtil;
|
||||
import com.imagepicker.utils.UI;
|
||||
|
||||
@ -48,22 +45,16 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import com.facebook.react.modules.core.PermissionListener;
|
||||
import com.facebook.react.modules.core.PermissionAwareActivity;
|
||||
|
||||
import static com.imagepicker.utils.MediaUtils.*;
|
||||
import static com.imagepicker.utils.MediaUtils.createNewFile;
|
||||
import static com.imagepicker.utils.MediaUtils.getResizedImage;
|
||||
|
||||
@ReactModule(name = ImagePickerModule.NAME)
|
||||
public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
implements ActivityEventListener
|
||||
{
|
||||
public static final String NAME = "ImagePickerManager";
|
||||
|
||||
public static final int DEFAULT_EXPLAINING_PERMISSION_DIALIOG_THEME = R.style.DefaultExplainingPermissionsTheme;
|
||||
|
||||
public static final int REQUEST_LAUNCH_IMAGE_CAPTURE = 13001;
|
||||
public static final int REQUEST_LAUNCH_IMAGE_LIBRARY = 13002;
|
||||
@ -76,13 +67,10 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
private final int dialogThemeId;
|
||||
|
||||
protected Callback callback;
|
||||
private Callback permissionRequestCallback;
|
||||
|
||||
private ReadableMap options;
|
||||
protected Uri cameraCaptureURI;
|
||||
private Boolean noData = false;
|
||||
private Boolean pickVideo = false;
|
||||
private Boolean pickBoth = false;
|
||||
private ImageConfig imageConfig = new ImageConfig(null, null, 0, 0, 100, 0, false);
|
||||
|
||||
@Deprecated
|
||||
@ -112,18 +100,18 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
|
||||
if (!permissionsGranted)
|
||||
{
|
||||
responseHelper.invokeError(permissionRequestCallback, "Permissions weren't granted");
|
||||
responseHelper.invokeError(callback, "Permissions weren't granted");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (requestCode)
|
||||
{
|
||||
case REQUEST_PERMISSIONS_FOR_CAMERA:
|
||||
launchCamera(options, permissionRequestCallback);
|
||||
launchCamera(options, callback);
|
||||
break;
|
||||
|
||||
case REQUEST_PERMISSIONS_FOR_LIBRARY:
|
||||
launchImageLibrary(options, permissionRequestCallback);
|
||||
launchImageLibrary(options, callback);
|
||||
break;
|
||||
|
||||
}
|
||||
@ -131,11 +119,6 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
}
|
||||
};
|
||||
|
||||
public ImagePickerModule(ReactApplicationContext reactContext)
|
||||
{
|
||||
this(reactContext, DEFAULT_EXPLAINING_PERMISSION_DIALIOG_THEME);
|
||||
}
|
||||
|
||||
public ImagePickerModule(ReactApplicationContext reactContext,
|
||||
@StyleRes final int dialogThemeId)
|
||||
{
|
||||
@ -148,7 +131,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
return "ImagePickerManager";
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@ -213,10 +196,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
|
||||
public void doOnCancel()
|
||||
{
|
||||
if (callback != null) {
|
||||
responseHelper.invokeCancel(callback);
|
||||
callback = null;
|
||||
}
|
||||
responseHelper.invokeCancel(callback);
|
||||
}
|
||||
|
||||
public void launchCamera()
|
||||
@ -228,8 +208,6 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
@ReactMethod
|
||||
public void launchCamera(final ReadableMap options, final Callback callback)
|
||||
{
|
||||
permissionRequestCallback = callback;
|
||||
|
||||
if (!isCameraAvailable())
|
||||
{
|
||||
responseHelper.invokeError(callback, "Camera not available");
|
||||
@ -243,7 +221,6 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
return;
|
||||
}
|
||||
|
||||
this.callback = callback;
|
||||
this.options = options;
|
||||
|
||||
if (!permissionsCheck(currentActivity, callback, REQUEST_PERMISSIONS_FOR_CAMERA))
|
||||
@ -271,15 +248,10 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
requestCode = REQUEST_LAUNCH_IMAGE_CAPTURE;
|
||||
cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
|
||||
final File original = createNewFile(reactContext, this.options, false);
|
||||
final File original = createNewFile(reactContext);
|
||||
imageConfig = imageConfig.withOriginalFile(original);
|
||||
|
||||
if (imageConfig.original != null) {
|
||||
cameraCaptureURI = RealPathUtil.compatUriFromFile(reactContext, imageConfig.original);
|
||||
}else {
|
||||
responseHelper.invokeError(callback, "Couldn't get file path for photo");
|
||||
return;
|
||||
}
|
||||
cameraCaptureURI = RealPathUtil.compatUriFromFile(reactContext, imageConfig.original);
|
||||
if (cameraCaptureURI == null)
|
||||
{
|
||||
responseHelper.invokeError(callback, "Couldn't get file path for photo");
|
||||
@ -294,16 +266,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
return;
|
||||
}
|
||||
|
||||
// Workaround for Android bug.
|
||||
// grantUriPermission also needed for KITKAT,
|
||||
// see https://code.google.com/p/android/issues/detail?id=76683
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
|
||||
List<ResolveInfo> resInfoList = reactContext.getPackageManager().queryIntentActivities(cameraIntent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
for (ResolveInfo resolveInfo : resInfoList) {
|
||||
String packageName = resolveInfo.activityInfo.packageName;
|
||||
reactContext.grantUriPermission(packageName, cameraCaptureURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
}
|
||||
this.callback = callback;
|
||||
|
||||
try
|
||||
{
|
||||
@ -324,15 +287,12 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
@ReactMethod
|
||||
public void launchImageLibrary(final ReadableMap options, final Callback callback)
|
||||
{
|
||||
permissionRequestCallback = callback;
|
||||
|
||||
final Activity currentActivity = getCurrentActivity();
|
||||
if (currentActivity == null) {
|
||||
responseHelper.invokeError(callback, "can't find current Activity");
|
||||
return;
|
||||
}
|
||||
|
||||
this.callback = callback;
|
||||
this.options = options;
|
||||
|
||||
if (!permissionsCheck(currentActivity, callback, REQUEST_PERMISSIONS_FOR_LIBRARY))
|
||||
@ -355,11 +315,6 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
requestCode = REQUEST_LAUNCH_IMAGE_LIBRARY;
|
||||
libraryIntent = new Intent(Intent.ACTION_PICK,
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||
|
||||
if (pickBoth)
|
||||
{
|
||||
libraryIntent.setType("image/* video/*");
|
||||
}
|
||||
}
|
||||
|
||||
if (libraryIntent.resolveActivity(reactContext.getPackageManager()) == null)
|
||||
@ -368,15 +323,11 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
return;
|
||||
}
|
||||
|
||||
this.callback = callback;
|
||||
|
||||
try
|
||||
{
|
||||
String chooseWhichLibraryTitle = null;
|
||||
if (ReadableMapUtils.hasAndNotEmptyString(options, "chooseWhichLibraryTitle"))
|
||||
{
|
||||
chooseWhichLibraryTitle = options.getString("chooseWhichLibraryTitle");
|
||||
}
|
||||
|
||||
currentActivity.startActivityForResult(Intent.createChooser(libraryIntent, chooseWhichLibraryTitle), requestCode);
|
||||
currentActivity.startActivityForResult(libraryIntent, requestCode);
|
||||
}
|
||||
catch (ActivityNotFoundException e)
|
||||
{
|
||||
@ -480,7 +431,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
}
|
||||
else
|
||||
{
|
||||
imageConfig = getResizedImage(reactContext, this.options, imageConfig, initialWidth, initialHeight, requestCode);
|
||||
imageConfig = getResizedImage(reactContext, imageConfig, initialWidth, initialHeight);
|
||||
if (imageConfig.resized == null)
|
||||
{
|
||||
removeUselessFiles(requestCode, imageConfig);
|
||||
@ -495,6 +446,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
|
||||
updatedResultResponse(uri, imageConfig.resized.getAbsolutePath());
|
||||
fileScan(reactContext, imageConfig.resized.getAbsolutePath());
|
||||
MediaUtils.removeOriginIfNeeded(imageConfig, requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -576,18 +528,10 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
final int cameraPermission = ActivityCompat
|
||||
.checkSelfPermission(activity, Manifest.permission.CAMERA);
|
||||
|
||||
boolean permissionsGranted = false;
|
||||
final boolean permissionsGrated = writePermission == PackageManager.PERMISSION_GRANTED &&
|
||||
cameraPermission == PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
switch (requestCode) {
|
||||
case REQUEST_PERMISSIONS_FOR_LIBRARY:
|
||||
permissionsGranted = writePermission == PackageManager.PERMISSION_GRANTED;
|
||||
break;
|
||||
case REQUEST_PERMISSIONS_FOR_CAMERA:
|
||||
permissionsGranted = cameraPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!permissionsGranted)
|
||||
if (!permissionsGrated)
|
||||
{
|
||||
final Boolean dontAskAgain = ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) && ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA);
|
||||
|
||||
@ -628,33 +572,16 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
innerActivity.startActivityForResult(intent, 1);
|
||||
}
|
||||
});
|
||||
if (dialog != null) {
|
||||
dialog.show();
|
||||
}
|
||||
dialog.show();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
String[] PERMISSIONS;
|
||||
switch (requestCode) {
|
||||
case REQUEST_PERMISSIONS_FOR_LIBRARY:
|
||||
PERMISSIONS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
||||
break;
|
||||
case REQUEST_PERMISSIONS_FOR_CAMERA:
|
||||
PERMISSIONS = new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
||||
break;
|
||||
default:
|
||||
PERMISSIONS = new String[]{};
|
||||
break;
|
||||
}
|
||||
|
||||
String[] PERMISSIONS = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};
|
||||
if (activity instanceof ReactActivity)
|
||||
{
|
||||
((ReactActivity) activity).requestPermissions(PERMISSIONS, requestCode, listener);
|
||||
}
|
||||
else if (activity instanceof PermissionAwareActivity) {
|
||||
((PermissionAwareActivity) activity).requestPermissions(PERMISSIONS, requestCode, listener);
|
||||
}
|
||||
else if (activity instanceof OnImagePickerPermissionsCallback)
|
||||
{
|
||||
((OnImagePickerPermissionsCallback) activity).setPermissionListener(listener);
|
||||
@ -665,8 +592,6 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
final String errorDescription = new StringBuilder(activity.getClass().getSimpleName())
|
||||
.append(" must implement ")
|
||||
.append(OnImagePickerPermissionsCallback.class.getSimpleName())
|
||||
.append(" or ")
|
||||
.append(PermissionAwareActivity.class.getSimpleName())
|
||||
.toString();
|
||||
throw new UnsupportedOperationException(errorDescription);
|
||||
}
|
||||
@ -742,26 +667,20 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
private void putExtraFileInfo(@NonNull final String path,
|
||||
@NonNull final ResponseHelper responseHelper)
|
||||
{
|
||||
// size && filename
|
||||
try {
|
||||
// size && filename
|
||||
File f = new File(path);
|
||||
responseHelper.putDouble("fileSize", f.length());
|
||||
responseHelper.putString("fileName", f.getName());
|
||||
// type
|
||||
String extension = MimeTypeMap.getFileExtensionFromUrl(path);
|
||||
String fileName = f.getName();
|
||||
if (extension != "") {
|
||||
responseHelper.putString("type", MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension));
|
||||
} else {
|
||||
int i = fileName.lastIndexOf('.');
|
||||
if (i > 0) {
|
||||
extension = fileName.substring(i+1);
|
||||
responseHelper.putString("type", MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// type
|
||||
String extension = MimeTypeMap.getFileExtensionFromUrl(path);
|
||||
if (extension != null) {
|
||||
responseHelper.putString("type", MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension));
|
||||
}
|
||||
}
|
||||
|
||||
private void parseOptions(final ReadableMap options) {
|
||||
@ -771,10 +690,6 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
|
||||
}
|
||||
imageConfig = imageConfig.updateFromOptions(options);
|
||||
pickVideo = false;
|
||||
pickBoth = false;
|
||||
if (options.hasKey("mediaType") && options.getString("mediaType").equals("mixed")) {
|
||||
pickBoth = true;
|
||||
}
|
||||
if (options.hasKey("mediaType") && options.getString("mediaType").equals("video")) {
|
||||
pickVideo = true;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package com.imagepicker;
|
||||
|
||||
import androidx.annotation.StyleRes;
|
||||
import android.support.annotation.StyleRes;
|
||||
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
@ -13,11 +13,12 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ImagePickerPackage implements ReactPackage {
|
||||
public static final int DEFAULT_EXPLAINING_PERMISSION_DIALIOG_THEME = R.style.DefaultExplainingPermissionsTheme;
|
||||
private @StyleRes final int dialogThemeId;
|
||||
|
||||
public ImagePickerPackage()
|
||||
{
|
||||
this.dialogThemeId = ImagePickerModule.DEFAULT_EXPLAINING_PERMISSION_DIALIOG_THEME;
|
||||
this.dialogThemeId = DEFAULT_EXPLAINING_PERMISSION_DIALIOG_THEME;
|
||||
}
|
||||
|
||||
public ImagePickerPackage(@StyleRes final int dialogThemeId)
|
||||
@ -30,7 +31,7 @@ public class ImagePickerPackage implements ReactPackage {
|
||||
return Arrays.<NativeModule>asList(new ImagePickerModule(reactContext, dialogThemeId));
|
||||
}
|
||||
|
||||
// Deprecated RN 0.47
|
||||
@Override
|
||||
public List<Class<? extends JavaScriptModule>> createJSModules() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@ -39,4 +40,4 @@ public class ImagePickerPackage implements ReactPackage {
|
||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package com.imagepicker;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
@ -73,9 +73,6 @@ public class ResponseHelper
|
||||
|
||||
public void invokeResponse(@NonNull final Callback callback)
|
||||
{
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
callback.invoke(response);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
package com.imagepicker.media;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
@ -78,18 +77,9 @@ public class ImageConfig
|
||||
|
||||
public @NonNull ImageConfig withOriginalFile(@Nullable final File original)
|
||||
{
|
||||
if (original != null) {
|
||||
//if it is a GIF file, always set quality to 100 to prevent compression
|
||||
String extension = MimeTypeMap.getFileExtensionFromUrl(original.getAbsolutePath());
|
||||
int quality = this.quality;
|
||||
if(extension.contains("gif")){
|
||||
quality = 100;
|
||||
}
|
||||
}
|
||||
|
||||
return new ImageConfig(
|
||||
original, this.resized, this.maxWidth,
|
||||
this.maxHeight, quality, this.rotation,
|
||||
this.maxHeight, this.quality, this.rotation,
|
||||
this.saveToCameraRoll
|
||||
);
|
||||
}
|
||||
@ -117,12 +107,12 @@ public class ImageConfig
|
||||
int maxWidth = 0;
|
||||
if (options.hasKey("maxWidth"))
|
||||
{
|
||||
maxWidth = (int) options.getDouble("maxWidth");
|
||||
maxWidth = options.getInt("maxWidth");
|
||||
}
|
||||
int maxHeight = 0;
|
||||
if (options.hasKey("maxHeight"))
|
||||
{
|
||||
maxHeight = (int) options.getDouble("maxHeight");
|
||||
maxHeight = options.getInt("maxHeight");
|
||||
}
|
||||
int quality = 100;
|
||||
if (options.hasKey("quality"))
|
||||
@ -132,7 +122,7 @@ public class ImageConfig
|
||||
int rotation = 0;
|
||||
if (options.hasKey("rotation"))
|
||||
{
|
||||
rotation = (int) options.getDouble("rotation");
|
||||
rotation = options.getInt("rotation");
|
||||
}
|
||||
boolean saveToCameraRoll = false;
|
||||
if (options.hasKey("storageOptions"))
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package com.imagepicker.permissions;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import android.support.annotation.NonNull;
|
||||
import com.facebook.react.modules.core.PermissionListener;
|
||||
|
||||
/**
|
||||
|
||||
@ -2,13 +2,13 @@ package com.imagepicker.permissions;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableNativeMap;
|
||||
import com.imagepicker.ImagePickerModule;
|
||||
import com.imagepicker.R;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@ -26,16 +26,7 @@ public class PermissionUtils
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!options.hasKey("permissionDenied"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
final ReadableMap permissionDenied = options.getMap("permissionDenied");
|
||||
if (((ReadableNativeMap) permissionDenied).toHashMap().size() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final String title = permissionDenied.getString("title");
|
||||
final String text = permissionDenied.getString("text");
|
||||
final String btnReTryTitle = permissionDenied.getString("reTryTitle");
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package com.imagepicker.permissions;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Created by rusfearuth on 03.03.17.
|
||||
*/
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package com.imagepicker.utils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
@ -8,8 +8,8 @@ import android.media.ExifInterface;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
@ -20,6 +20,7 @@ import com.imagepicker.media.ImageConfig;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
@ -36,55 +37,15 @@ import static com.imagepicker.ImagePickerModule.REQUEST_LAUNCH_IMAGE_CAPTURE;
|
||||
|
||||
public class MediaUtils
|
||||
{
|
||||
public static @Nullable File createNewFile(@NonNull final Context reactContext,
|
||||
@NonNull final ReadableMap options,
|
||||
@NonNull final boolean forceLocal)
|
||||
public static @NonNull File createNewFile(@NonNull final Context reactContext)
|
||||
{
|
||||
final String filename = new StringBuilder("image-")
|
||||
.append(UUID.randomUUID().toString())
|
||||
.append(".jpg")
|
||||
.toString();
|
||||
|
||||
// defaults to Public Pictures Directory
|
||||
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
||||
|
||||
if (ReadableMapUtils.hasAndNotNullReadableMap(options, "storageOptions"))
|
||||
{
|
||||
final ReadableMap storageOptions = options.getMap("storageOptions");
|
||||
|
||||
if (storageOptions.hasKey("privateDirectory"))
|
||||
{
|
||||
boolean saveToPrivateDirectory = storageOptions.getBoolean("privateDirectory");
|
||||
if (saveToPrivateDirectory)
|
||||
{
|
||||
// if privateDirectory is set then save to app's private files directory
|
||||
path = reactContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
|
||||
}
|
||||
}
|
||||
|
||||
if (ReadableMapUtils.hasAndNotEmptyString(storageOptions, "path"))
|
||||
{
|
||||
path = new File(path, storageOptions.getString("path"));
|
||||
}
|
||||
}
|
||||
else if (forceLocal)
|
||||
{
|
||||
path = reactContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
|
||||
}
|
||||
|
||||
final File path = reactContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
|
||||
File result = new File(path, filename);
|
||||
|
||||
try
|
||||
{
|
||||
path.mkdirs();
|
||||
result.createNewFile();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
result = null;
|
||||
}
|
||||
|
||||
path.mkdirs();
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -92,37 +53,24 @@ public class MediaUtils
|
||||
* Create a resized image to fulfill the maxWidth/maxHeight, quality and rotation values
|
||||
*
|
||||
* @param context
|
||||
* @param options
|
||||
* @param imageConfig
|
||||
* @param initialWidth
|
||||
* @param initialHeight
|
||||
* @return updated ImageConfig
|
||||
*/
|
||||
public static @NonNull ImageConfig getResizedImage(@NonNull final Context context,
|
||||
@NonNull final ReadableMap options,
|
||||
@NonNull final ImageConfig imageConfig,
|
||||
int initialWidth,
|
||||
int initialHeight,
|
||||
final int requestCode)
|
||||
final int initialWidth,
|
||||
final int initialHeight)
|
||||
{
|
||||
BitmapFactory.Options imageOptions = new BitmapFactory.Options();
|
||||
imageOptions.inScaled = false;
|
||||
imageOptions.inSampleSize = 1;
|
||||
|
||||
if (imageConfig.maxWidth != 0 || imageConfig.maxHeight != 0) {
|
||||
while ((imageConfig.maxWidth == 0 || initialWidth > 2 * imageConfig.maxWidth) &&
|
||||
(imageConfig.maxHeight == 0 || initialHeight > 2 * imageConfig.maxHeight)) {
|
||||
imageOptions.inSampleSize *= 2;
|
||||
initialHeight /= 2;
|
||||
initialWidth /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: OOM here
|
||||
Bitmap photo = BitmapFactory.decodeFile(imageConfig.original.getAbsolutePath(), imageOptions);
|
||||
|
||||
if (photo == null)
|
||||
{
|
||||
return imageConfig;
|
||||
return null;
|
||||
}
|
||||
|
||||
ImageConfig result = imageConfig;
|
||||
@ -177,8 +125,7 @@ public class MediaUtils
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
scaledPhoto.compress(Bitmap.CompressFormat.JPEG, result.quality, bytes);
|
||||
|
||||
final boolean forceLocal = requestCode == REQUEST_LAUNCH_IMAGE_CAPTURE;
|
||||
final File resized = createNewFile(context, options, !forceLocal);
|
||||
final File resized = createNewFile(context);
|
||||
|
||||
if (resized == null)
|
||||
{
|
||||
@ -197,9 +144,11 @@ public class MediaUtils
|
||||
|
||||
result = result.withResizedFile(resized);
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(result.resized))
|
||||
FileOutputStream fos;
|
||||
try
|
||||
{
|
||||
bytes.writeTo(fos);
|
||||
fos = new FileOutputStream(result.resized);
|
||||
fos.write(bytes.toByteArray());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
@ -267,14 +216,11 @@ public class MediaUtils
|
||||
ExifInterface exif = new ExifInterface(imageConfig.original.getAbsolutePath());
|
||||
|
||||
// extract lat, long, and timestamp and add to the response
|
||||
float[] latlng = new float[2];
|
||||
exif.getLatLong(latlng);
|
||||
float latitude = latlng[0];
|
||||
float longitude = latlng[1];
|
||||
if(latitude != 0f || longitude != 0f)
|
||||
float[] latLng = new float[2];
|
||||
if(exif.getLatLong(latLng))
|
||||
{
|
||||
responseHelper.putDouble("latitude", latitude);
|
||||
responseHelper.putDouble("longitude", longitude);
|
||||
responseHelper.putDouble("latitude", latLng[0]);
|
||||
responseHelper.putDouble("longitude", latLng[1]);
|
||||
}
|
||||
|
||||
final String timestamp = exif.getAttribute(ExifInterface.TAG_DATETIME);
|
||||
@ -354,26 +300,35 @@ public class MediaUtils
|
||||
* This is done via copy + deletion, because Android will throw an error
|
||||
* if you try to move a file across mount points, e.g. to the SD card.
|
||||
*/
|
||||
private static void moveFile(@NonNull final File oldFile,
|
||||
public static void moveFile(@NonNull final File oldFile,
|
||||
@NonNull final File newFile) throws IOException
|
||||
{
|
||||
FileChannel oldChannel = null;
|
||||
FileChannel newChannel = null;
|
||||
FileInputStream in = new FileInputStream(oldFile);
|
||||
FileOutputStream out = new FileOutputStream(newFile);
|
||||
|
||||
try
|
||||
{
|
||||
oldChannel = new FileInputStream(oldFile).getChannel();
|
||||
newChannel = new FileOutputStream(newFile).getChannel();
|
||||
oldChannel.transferTo(0, oldChannel.size(), newChannel);
|
||||
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
oldFile.delete();
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (oldChannel != null) oldChannel.close();
|
||||
if (newChannel != null) newChannel.close();
|
||||
if (in != null)
|
||||
{
|
||||
in.close();
|
||||
}
|
||||
if (out != null)
|
||||
{
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
@ -382,6 +337,16 @@ public class MediaUtils
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeOriginIfNeeded(@NonNull final ImageConfig imageConfig,
|
||||
final int requestCode)
|
||||
{
|
||||
if (requestCode != ImagePickerModule.REQUEST_LAUNCH_IMAGE_CAPTURE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
imageConfig.original.delete();
|
||||
}
|
||||
|
||||
|
||||
public static class RolloutPhotoResult
|
||||
{
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package com.imagepicker.utils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.imagepicker.utils;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
@ -9,9 +10,9 @@ import android.provider.DocumentsContract;
|
||||
import android.provider.MediaStore;
|
||||
import android.content.ContentUris;
|
||||
import android.os.Environment;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.FileProvider;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.FileProvider;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
@ -2,10 +2,10 @@ package com.imagepicker.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<files-path name="shared" path="."/>
|
||||
<external-path name="shared" path="."/>
|
||||
<external-files-path name="shared" path="."/>
|
||||
<root-path name="root" path="."/>
|
||||
</paths>
|
||||
<external-path name="app_images" path="."/>
|
||||
</paths>
|
||||
@ -45,7 +45,8 @@ import static org.powermock.api.mockito.PowerMockito.when;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@SuppressStaticInitializationFor("com.facebook.react.common.build.ReactBuildConfig")
|
||||
@PrepareForTest({Arguments.class})
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*", "jdk.internal.reflect.*"})
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
@Config(manifest = Config.NONE)
|
||||
public class ImagePickerModuleTest
|
||||
{
|
||||
private static final int DEFAULT_THEME = R.style.DefaultExplainingPermissionsTheme;
|
||||
@ -110,4 +111,4 @@ public class ImagePickerModuleTest
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,9 +15,6 @@ public class SampleCallback implements Callback
|
||||
@Override
|
||||
public void invoke(Object... args)
|
||||
{
|
||||
System.out.println(args.length);
|
||||
System.out.println(String.valueOf(args[0]));
|
||||
System.out.println(args[0].getClass());
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (lookingForError(args[i])) {
|
||||
break;
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
package com.imagepicker.testing;
|
||||
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StyleRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StyleRes;
|
||||
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.imagepicker.ImagePickerModule;
|
||||
import com.imagepicker.ResponseHelper;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Created by rusfearuth on 10.04.17.
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
package com.imagepicker.testing.mock;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.media.ExifInterface;
|
||||
import android.os.Build;
|
||||
|
||||
import org.robolectric.annotation.Implements;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Created by rusfearuth on 13.04.17.
|
||||
*/
|
||||
|
||||
@Implements(ExifInterface.class)
|
||||
public class MockExifInterface
|
||||
extends ExifInterface
|
||||
{
|
||||
private HashMap<String, String> metadata = new HashMap<>();
|
||||
|
||||
public MockExifInterface(String filename) throws
|
||||
IOException
|
||||
{
|
||||
super(filename);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
public MockExifInterface(FileDescriptor fileDescriptor) throws
|
||||
IOException
|
||||
{
|
||||
super(fileDescriptor);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
public MockExifInterface(InputStream inputStream) throws
|
||||
IOException
|
||||
{
|
||||
super(inputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String attr, String value)
|
||||
{
|
||||
metadata.put(attr, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAttribute(String attr)
|
||||
{
|
||||
return metadata.get(attr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAttributeInt(String attr, int defaultValue)
|
||||
{
|
||||
if (!metadata.containsKey(attr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
return Integer.valueOf(metadata.get(attr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getLatLong(float[] latLong)
|
||||
{
|
||||
if (!metadata.containsKey(ExifInterface.TAG_GPS_LATITUDE) ||
|
||||
!metadata.containsKey(ExifInterface.TAG_GPS_LONGITUDE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
latLong[0] = Float.valueOf(metadata.get(ExifInterface.TAG_GPS_LATITUDE));
|
||||
latLong[1] = Float.valueOf(metadata.get(ExifInterface.TAG_GPS_LONGITUDE));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,296 @@
|
||||
package com.imagepicker.testing.utils;
|
||||
|
||||
import android.app.Application;
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.ExifInterface;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.JavaOnlyArray;
|
||||
import com.facebook.react.bridge.JavaOnlyMap;
|
||||
import com.imagepicker.ImagePickerModule;
|
||||
import com.imagepicker.ResponseHelper;
|
||||
import com.imagepicker.media.ImageConfig;
|
||||
import com.imagepicker.testing.mock.MockExifInterface;
|
||||
import com.imagepicker.utils.MediaUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
|
||||
import org.powermock.modules.junit4.rule.PowerMockRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowBitmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNotSame;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.powermock.api.mockito.PowerMockito.when;
|
||||
import static org.powermock.api.mockito.PowerMockito.whenNew;
|
||||
|
||||
/**
|
||||
* Created by rusfearuth on 12.04.17.
|
||||
*/
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@SuppressStaticInitializationFor("com.facebook.react.common.build.ReactBuildConfig")
|
||||
@PrepareForTest({ Arguments.class, MediaUtils.class })
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
@Config(manifest = Config.NONE)
|
||||
public class MediaUtilsTest
|
||||
{
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
private ExifInterface exifMock;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
PowerMockito.mockStatic(Arguments.class);
|
||||
when(Arguments.createArray()).thenAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return new JavaOnlyArray();
|
||||
}
|
||||
});
|
||||
when(Arguments.createMap()).thenAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return new JavaOnlyMap();
|
||||
}
|
||||
});
|
||||
exifMock = new MockExifInterface("");
|
||||
whenNew(ExifInterface.class).withAnyArguments().thenReturn(exifMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatingFile() throws IOException
|
||||
{
|
||||
Application application = RuntimeEnvironment.application;
|
||||
File newFile = MediaUtils.createNewFile(application);
|
||||
assertNotNull("File was created", newFile);
|
||||
newFile.createNewFile();
|
||||
assertTrue("File exists", newFile.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetResizedFile()
|
||||
{
|
||||
Application application = RuntimeEnvironment.application;
|
||||
Bitmap original = ShadowBitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8);
|
||||
File file = MediaUtils.createNewFile(application);
|
||||
|
||||
assertTrue("Image was created", saveToFile(file, original));
|
||||
|
||||
ImageConfig config = new ImageConfig(file, null, 50, 50, 100, 0, false);
|
||||
ImageConfig resizedConfig = MediaUtils.getResizedImage(application, config, 10, 10);
|
||||
|
||||
assertNotNull("Image was resized", resizedConfig.resized);
|
||||
assertNotSame(
|
||||
"Original and resized files aren't the same",
|
||||
config.original.getAbsolutePath(),
|
||||
resizedConfig.resized.getAbsolutePath()
|
||||
);
|
||||
assertNotSame(
|
||||
"Original and resized files have different size",
|
||||
config.original.length(),
|
||||
resizedConfig.resized.length()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveUselessFiles()
|
||||
{
|
||||
Application application = RuntimeEnvironment.application;
|
||||
Bitmap original = ShadowBitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8);
|
||||
File originalFile = MediaUtils.createNewFile(application);
|
||||
|
||||
assertTrue("Original file was created", saveToFile(originalFile, original));
|
||||
|
||||
Bitmap resized = ShadowBitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8);
|
||||
File resizedFile = MediaUtils.createNewFile(application);
|
||||
|
||||
assertTrue("Resized file was created", saveToFile(resizedFile, resized));
|
||||
|
||||
assertTrue("Original file exists", originalFile.exists());
|
||||
assertTrue("Resized file exists", resizedFile.exists());
|
||||
|
||||
ImageConfig config = new ImageConfig(originalFile, resizedFile, 100, 100, 100, 0, false);
|
||||
|
||||
MediaUtils.removeUselessFiles(ImagePickerModule.REQUEST_LAUNCH_IMAGE_LIBRARY, config);
|
||||
|
||||
assertTrue("Original file exists, because requestCode is invalid", originalFile.exists());
|
||||
assertTrue("Resized file exists, because requestCode is invalid", resizedFile.exists());
|
||||
|
||||
MediaUtils.removeUselessFiles(ImagePickerModule.REQUEST_LAUNCH_IMAGE_CAPTURE, config);
|
||||
|
||||
assertFalse("Original file was removed", config.original.exists());
|
||||
assertFalse("Resized file was removed", config.resized.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadExifInterface() throws Exception
|
||||
{
|
||||
final SimpleDateFormat exifDatetimeFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
|
||||
final DateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
|
||||
final long currentTimestamp = System.currentTimeMillis();
|
||||
final String fileDateTime = exifDatetimeFormat.format(new Date(currentTimestamp));
|
||||
final String dateTimeForCheckout = isoFormat.format(new Date(currentTimestamp));
|
||||
|
||||
final Application application = RuntimeEnvironment.application;
|
||||
final Bitmap original = ShadowBitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8);
|
||||
final File originalFile = MediaUtils.createNewFile(application);
|
||||
final ImageConfig imageConfig = new ImageConfig(originalFile, null, 100, 100, 100, 0, false);
|
||||
|
||||
assertTrue("Original file was created", saveToFile(originalFile, original));
|
||||
|
||||
ExifInterface exif = new ExifInterface(originalFile.getAbsolutePath());
|
||||
exif.setAttribute(ExifInterface.TAG_ORIENTATION, String.valueOf(ExifInterface.ORIENTATION_ROTATE_270));
|
||||
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, String.valueOf(1.0f));
|
||||
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, String.valueOf(-1.0f));
|
||||
exif.setAttribute(ExifInterface.TAG_DATETIME, fileDateTime);
|
||||
exif.saveAttributes();
|
||||
|
||||
ResponseHelper helper = new ResponseHelper();
|
||||
helper.cleanResponse();
|
||||
MediaUtils.ReadExifResult result = MediaUtils.readExifInterface(helper, imageConfig);
|
||||
|
||||
assertNull("Exif interface was read", result.error);
|
||||
|
||||
assertNotNull("Orientation was read", helper.getResponse().getInt("originalRotation"));
|
||||
assertEquals("Orientation value is", helper.getResponse().getInt("originalRotation"), 270);
|
||||
|
||||
assertNotNull("Latitude was read", helper.getResponse().getDouble("latitude"));
|
||||
assertEquals("Latitude value is", Math.floor(helper.getResponse().getDouble("latitude")), Math.floor(1.0f));
|
||||
|
||||
assertNotNull("Longitude was read", helper.getResponse().getDouble("longitude"));
|
||||
assertEquals("Longitude value is", Math.floor(helper.getResponse().getDouble("longitude")), Math.floor(-1.0f));
|
||||
|
||||
assertNotNull("DateTime was read", helper.getResponse().getString("timestamp"));
|
||||
assertEquals("DateTIme value is", helper.getResponse().getString("timestamp"), dateTimeForCheckout);
|
||||
|
||||
assertNotNull("Vertical flag was generated", helper.getResponse().getBoolean("isVertical"));
|
||||
assertFalse("Is image vertical", helper.getResponse().getBoolean("isVertical"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRolloutPhotoFromCamera()
|
||||
{
|
||||
Application application = RuntimeEnvironment.application;
|
||||
Bitmap original = ShadowBitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8);
|
||||
File originalFile = MediaUtils.createNewFile(application);
|
||||
assertTrue("Original file was created", saveToFile(originalFile, original));
|
||||
|
||||
ImageConfig imageConfig = new ImageConfig(originalFile, null, 100, 100, 100, 0, true);
|
||||
MediaUtils.RolloutPhotoResult result = MediaUtils.rolloutPhotoFromCamera(imageConfig);
|
||||
|
||||
assertNull("Rollout of original file has done", result.error);
|
||||
assertNotSame("Original files are different", imageConfig.original.getAbsolutePath(), result.imageConfig.original.getAbsolutePath());
|
||||
assertEquals("Original file names are the same", imageConfig.original.getName(), result.imageConfig.original.getName());
|
||||
assertTrue("Original file was moved", result.imageConfig.original.getAbsolutePath().toLowerCase().contains("/dcim/"));
|
||||
assertFalse("Original file was moved", imageConfig.original.exists());
|
||||
|
||||
Bitmap resized = ShadowBitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8);
|
||||
File resizedFile = MediaUtils.createNewFile(application);
|
||||
assertTrue("Resized file was created", saveToFile(resizedFile, resized));
|
||||
|
||||
imageConfig = imageConfig.withResizedFile(resizedFile);
|
||||
result = MediaUtils.rolloutPhotoFromCamera(imageConfig);
|
||||
assertNull("Rollout of resized file has done", result.error);
|
||||
|
||||
assertNotSame("Different resized files", imageConfig.resized.getAbsolutePath(), result.imageConfig.resized.getAbsolutePath());
|
||||
assertEquals("Resized file names are the same", imageConfig.resized.getName(), result.imageConfig.resized.getName());
|
||||
assertTrue("Resized file was moved", result.imageConfig.resized.getAbsolutePath().toLowerCase().contains("/dcim/"));
|
||||
assertFalse("Resized file was moved", imageConfig.original.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveFile() throws IOException
|
||||
{
|
||||
Application application = RuntimeEnvironment.application;
|
||||
File oldFile = new File(application.getCacheDir(), "original.txt");
|
||||
oldFile.createNewFile();
|
||||
File targetDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
|
||||
File newFile = new File(targetDir, oldFile.getName());
|
||||
MediaUtils.moveFile(oldFile, newFile);
|
||||
|
||||
assertFalse("Old file has left", oldFile.exists());
|
||||
assertTrue("New file was copied", newFile.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveOriginIfNeeded() throws IOException
|
||||
{
|
||||
Application application = RuntimeEnvironment.application;
|
||||
Bitmap original = ShadowBitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8);
|
||||
File originalFile = MediaUtils.createNewFile(application);
|
||||
|
||||
assertTrue("Original file was created", saveToFile(originalFile, original));
|
||||
assertTrue("Original file exists", originalFile.exists());
|
||||
|
||||
ImageConfig imageConfig = new ImageConfig(originalFile, null, 100, 100, 100, 0, false);
|
||||
|
||||
MediaUtils.removeOriginIfNeeded(imageConfig, ImagePickerModule.REQUEST_LAUNCH_IMAGE_LIBRARY);
|
||||
assertTrue("Original file wasn't removed on REQUEST_LAUNCH_IMAGE_LIBRARY", originalFile.exists());
|
||||
|
||||
MediaUtils.removeOriginIfNeeded(imageConfig, ImagePickerModule.REQUEST_LAUNCH_IMAGE_CAPTURE);
|
||||
assertFalse("Original file was removed on REQUEST_LAUNCH_IMAGE_CAPTURE", originalFile.exists());
|
||||
}
|
||||
|
||||
private boolean saveToFile(@NonNull final File imageFile,
|
||||
@NonNull final Bitmap bitmap)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
FileOutputStream fos = null;
|
||||
try
|
||||
{
|
||||
fos = new FileOutputStream(imageFile);
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
|
||||
result = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (fos != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
fos.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
result = false;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.imagepicker.testing.utils;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.imagepicker.utils.MediaUtils;
|
||||
import com.imagepicker.utils.RealPathUtil;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.internal.SdkEnvironment;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* Created by rusfearuth on 13.04.17.
|
||||
*/
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class RealPathUtilTest
|
||||
{
|
||||
@Test
|
||||
public void testCompatUriFromFile()
|
||||
{
|
||||
File newFile = MediaUtils.createNewFile(RuntimeEnvironment.application);
|
||||
Uri uri = RealPathUtil.compatUriFromFile(RuntimeEnvironment.application, newFile);
|
||||
assertNotNull("Uri was created", uri);
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
};
|
||||
195
docs/Install.md
@ -1,195 +0,0 @@
|
||||
# Install
|
||||
|
||||
```
|
||||
yarn add react-native-image-picker
|
||||
|
||||
# RN >= 0.60
|
||||
cd ios && pod install
|
||||
|
||||
# RN < 0.60
|
||||
react-native link react-native-image-picker
|
||||
```
|
||||
|
||||
⚠️ If you need to support React Native < 0.40, you must install this package: `react-native-image-picker@0.24`.
|
||||
|
||||
## Post-install Steps
|
||||
|
||||
### iOS
|
||||
|
||||
For iOS 10+:
|
||||
|
||||
Add the `NSPhotoLibraryUsageDescription`, `NSCameraUsageDescription`, `NSPhotoLibraryAddUsageDescription` and `NSMicrophoneUsageDescription` (if allowing video) keys to your `Info.plist` with strings describing why your app needs these permissions.
|
||||
|
||||
**Note: You will get a SIGABRT crash if you don't complete this step**
|
||||
|
||||
```xml
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
...
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>$(PRODUCT_NAME) would like access to your photo gallery</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>$(PRODUCT_NAME) would like to use your camera</string>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string>$(PRODUCT_NAME) would like to save photos to your photo gallery</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>$(PRODUCT_NAME) would like to use your microphone (for videos)</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
⚠️ If you are planning on submitting your application to app store:
|
||||
|
||||
To be compliant with Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage, the permission request alert should specify how your app will use this feature to help users understand why your app is requesting access to their personal data.
|
||||
|
||||
```
|
||||
$(PRODUCT_NAME) would like access to your photo gallery to change your profile picture
|
||||
```
|
||||
|
||||
|
||||
### Android
|
||||
|
||||
Add the required permissions in `AndroidManifest.xml`:
|
||||
|
||||
```xml
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
```
|
||||
|
||||
### Android (Optional)
|
||||
|
||||
If you've defined _[project-wide properties](https://developer.android.com/studio/build/gradle-tips.html)_ (**recommended**) in your root `build.gradle`, this library will detect the presence of the following properties:
|
||||
|
||||
```groovy
|
||||
buildscript {...}
|
||||
allprojects {...}
|
||||
|
||||
/**
|
||||
+ Project-wide Gradle configuration properties
|
||||
*/
|
||||
ext {
|
||||
compileSdkVersion = 27
|
||||
targetSdkVersion = 27
|
||||
buildToolsVersion = "27.0.3"
|
||||
}
|
||||
```
|
||||
|
||||
Customization settings of dialog `android/app/res/values/themes.xml` (`android/app/res/values/style.xml` is a valid path as well):
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="DefaultExplainingPermissionsTheme" parent="Theme.AppCompat.Light.Dialog.Alert">
|
||||
<!-- Used for the buttons -->
|
||||
<item name="colorAccent">@color/your_color</item>
|
||||
|
||||
<!-- Used for the title and text -->
|
||||
<item name="android:textColorPrimary">@color/your_color</item>
|
||||
|
||||
<!-- Used for the background -->
|
||||
<item name="android:background">@color/your_color</item>
|
||||
</style>
|
||||
</resources>
|
||||
```
|
||||
|
||||
## Manual Installation
|
||||
|
||||
### iOS
|
||||
|
||||
1. In the XCode's "Project navigator", right click on your project's Libraries folder ➜ `Add Files to <...>`.
|
||||
1. Go to `node_modules` ➜ `react-native-image-picker` ➜ `ios` ➜ select `RNImagePicker.xcodeproj`.
|
||||
1. Add `libRNImagePicker.a` to `Build Phases -> Link Binary With Libraries`.
|
||||
1. Refer to [Post-install Steps](Install.md#post-install-steps).
|
||||
1. Compile and have fun.
|
||||
|
||||
### Android
|
||||
|
||||
1. Add the following lines to `android/settings.gradle`:
|
||||
|
||||
```gradle
|
||||
include ':react-native-image-picker'
|
||||
project(':react-native-image-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-picker/android')
|
||||
```
|
||||
|
||||
2. Update the android build tools version to `2.2.+` in `android/build.gradle`:
|
||||
|
||||
```gradle
|
||||
buildscript {
|
||||
...
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.+' // <- USE 2.2.+ version
|
||||
}
|
||||
...
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
3. Update the gradle version to `2.14.1` in `android/gradle/wrapper/gradle-wrapper.properties`:
|
||||
|
||||
```
|
||||
...
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
|
||||
```
|
||||
|
||||
4. Add the implementation line to the dependencies in `android/app/build.gradle`:
|
||||
|
||||
```gradle
|
||||
dependencies {
|
||||
implementation project(':react-native-image-picker')
|
||||
}
|
||||
```
|
||||
|
||||
5. Add the import and link the package in `MainApplication.java`:
|
||||
|
||||
```java
|
||||
import com.imagepicker.ImagePickerPackage; // <-- add this import
|
||||
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new MainReactPackage(),
|
||||
new ImagePickerPackage(), // <-- add this line
|
||||
// OR if you want to customize dialog style
|
||||
new ImagePickerPackage(R.style.my_dialog_style)
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
6. If `MainActivity` is not instance of `ReactActivity`, you will need to implement `OnImagePickerPermissionsCallback` to `MainActivity`:
|
||||
|
||||
```java
|
||||
import com.imagepicker.permissions.OnImagePickerPermissionsCallback; // <- add this import
|
||||
import com.facebook.react.modules.core.PermissionListener; // <- add this import
|
||||
|
||||
public class MainActivity extends YourActivity implements OnImagePickerPermissionsCallback {
|
||||
private PermissionListener listener; // <- add this attribute
|
||||
|
||||
// Your methods here
|
||||
|
||||
// Copy from here
|
||||
|
||||
@Override
|
||||
public void setPermissionListener(PermissionListener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
|
||||
{
|
||||
if (listener != null)
|
||||
{
|
||||
listener.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
// To here
|
||||
}
|
||||
```
|
||||
|
||||
This code allows to pass result of request permissions to native part.
|
||||
|
||||
7. Refer to [Post-install Steps](Install.md#post-install-steps).
|
||||
@ -1,95 +0,0 @@
|
||||
# API Reference
|
||||
|
||||
This document lays out the current public properties and methods for the React Native Image Picker.
|
||||
|
||||
## Methods
|
||||
|
||||
### `showImagePicker()`
|
||||
|
||||
```js
|
||||
static showImagePicker(options?, callback)
|
||||
```
|
||||
|
||||
Display the image picker.
|
||||
|
||||
See [Options](#options) for further information on `options`.
|
||||
|
||||
The `callback` will be called with a response object, refer to [The Response Object](#the-response-object).
|
||||
|
||||
### `launchCamera()`
|
||||
|
||||
```js
|
||||
static launchCamera(options?, callback)
|
||||
```
|
||||
|
||||
Skip the alert dialog and launch the camera directly.
|
||||
|
||||
See [Options](#options) for further information on `options`.
|
||||
|
||||
The `callback` will be called with a response object, refer to [The Response Object](#the-response-object).
|
||||
|
||||
### `launchImageLibrary()`
|
||||
|
||||
```js
|
||||
static launchImageLibrary(options?, callback)
|
||||
```
|
||||
|
||||
Skip the alert dialog and launch the image library directly.
|
||||
|
||||
See [Options](#options) for further information on `options`.
|
||||
|
||||
The `callback` will be called with a response object, refer to [The Response Object](#the-response-object).
|
||||
|
||||
## Options
|
||||
|
||||
| option | iOS | Android | Info |
|
||||
| ----------------------------- | --- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| title | OK | OK | Specify `null` or empty string to remove the title |
|
||||
| cancelButtonTitle | OK | OK | Specify `null` or empty string to remove this button |
|
||||
| takePhotoButtonTitle | OK | OK | Specify `null` or empty string to remove this button |
|
||||
| chooseFromLibraryButtonTitle | OK | OK | Specify `null` or empty string to remove this button |
|
||||
| chooseWhichLibraryTitle | - | OK | Specify `null` or empty string to use default Android title. Is shown when user has multiple apps that can open library. |
|
||||
| customButtons | OK | OK | An array containing objects with the name and title of buttons |
|
||||
| tintColor | OK | - | Text color to use on buttons |
|
||||
| cameraType | OK | - | 'front' or 'back' |
|
||||
| mediaType | OK | OK | 'photo', 'video', or 'mixed' |
|
||||
| maxWidth | OK | OK | Photos only |
|
||||
| maxHeight | OK | OK | Photos only |
|
||||
| quality | OK | OK | 0 to 1, photos only |
|
||||
| videoQuality | OK | OK | 'low', 'medium', or 'high' on iOS, 'low' or 'high' on Android |
|
||||
| durationLimit | OK | OK | Max video recording time, in seconds |
|
||||
| rotation | - | OK | Photos only, 0 to 360 degrees of rotation |
|
||||
| allowsEditing | OK | - | bool - enables built-in iOS functionality to resize the image after selection |
|
||||
| noData | OK | OK | If true, disables the base64 `data` field from being generated (greatly improves performance on large photos) |
|
||||
| storageOptions | OK | OK | If this key is provided, the image will be saved in your app's `Documents` directory on iOS (rather than a temporary directory). On Android this key does not affect the image location (Android always defaults to the public `Pictures` directory) |
|
||||
| storageOptions.skipBackup | OK | - | If true, the photo will NOT be backed up to iCloud |
|
||||
| storageOptions.path | OK | OK | If set, will save the image at `Documents/[path]/` rather than the root `Documents` for iOS, and `Pictures/[path]/` on Android. |
|
||||
| storageOptions.cameraRoll | OK | OK | If true, the cropped photo will be saved to the iOS Camera Roll or Android DCIM folder. |
|
||||
| storageOptions.waitUntilSaved | OK | - | If true, will delay the response callback until after the photo/video was saved to the Camera Roll. If the photo or video was just taken, then the file name and timestamp fields are only provided in the response object when this AND `cameraRoll` are both true. |
|
||||
| storageOptions.privateDirectory | - | OK | If true, the photo will be saved to the apps private files directory (Android/data/your_package/files/Pictures) |
|
||||
| permissionDenied.title | - | OK | Title of explaining permissions dialog. By default `Permission denied`. |
|
||||
| permissionDenied.text | - | OK | Message of explaining permissions dialog. By default `To be able to take pictures with your camera and choose images from your library.`. |
|
||||
| permissionDenied.reTryTitle | - | OK | Title of re-try button. By default `re-try` |
|
||||
| permissionDenied.okTitle | - | OK | Title of ok button. By default `I'm sure` |
|
||||
|
||||
## The Response Object
|
||||
|
||||
| key | iOS | Android | Description |
|
||||
| ---------------- | ---------------------- | ----------- | ---------------------------------------------------------------------- |
|
||||
| didCancel | OK | OK | Informs you if the user cancelled the process |
|
||||
| error | OK | OK | Contains an error message, if there is one |
|
||||
| customButton | OK | OK | If the user tapped one of your custom buttons, contains the name of it |
|
||||
| data | OK | OK | The base64 encoded image data (photos only) |
|
||||
| uri | OK | OK | The uri to the local file asset on the device (photo or video) |
|
||||
| origURL | OK | - | The URL of the original asset in photo library, if it exists |
|
||||
| isVertical | OK | OK | Will be true if the image is vertically oriented |
|
||||
| width | OK | OK | Image dimensions (photos only) |
|
||||
| height | OK | OK | Image dimensions (photos only) |
|
||||
| fileSize | OK | OK | The file size (photos only) |
|
||||
| type | OK | OK | The file type (photos only) |
|
||||
| fileName | OK (photos and videos) | OK (photos) | The file name, if available
|
||||
| path | - | OK | The file path |
|
||||
| latitude | OK | OK | Latitude metadata, if available |
|
||||
| longitude | OK | OK | Longitude metadata, if available |
|
||||
| timestamp | OK | OK | Timestamp metadata, if available, in ISO8601 UTC format |
|
||||
| originalRotation | - | OK | Rotation degrees (photos only) _See [#109](/../../issues/199)_ |
|
||||
@ -1,3 +0,0 @@
|
||||
{
|
||||
"presets": ["module:metro-react-native-babel-preset"]
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
|
||||
[android]
|
||||
target = Google Inc.:Google APIs:23
|
||||
|
||||
[maven_repositories]
|
||||
central = https://repo1.maven.org/maven2
|
||||
@ -1,70 +0,0 @@
|
||||
[ignore]
|
||||
; We fork some components by platform
|
||||
.*/*[.]android.js
|
||||
|
||||
; Ignore "BUCK" generated dirs
|
||||
<PROJECT_ROOT>/\.buckd/
|
||||
|
||||
; Ignore unexpected extra "@providesModule"
|
||||
.*/node_modules/.*/node_modules/fbjs/.*
|
||||
|
||||
; Ignore duplicate module providers
|
||||
; For RN Apps installed via npm, "Libraries" folder is inside
|
||||
; "node_modules/react-native" but in the source repo it is in the root
|
||||
.*/Libraries/react-native/React.js
|
||||
|
||||
; Ignore polyfills
|
||||
.*/Libraries/polyfills/.*
|
||||
|
||||
; Ignore metro
|
||||
.*/node_modules/metro/.*
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
node_modules/react-native/Libraries/react-native/react-native-interface.js
|
||||
node_modules/react-native/flow/
|
||||
node_modules/react-native/flow-github/
|
||||
|
||||
[options]
|
||||
emoji=true
|
||||
|
||||
esproposal.optional_chaining=enable
|
||||
esproposal.nullish_coalescing=enable
|
||||
|
||||
module.system=haste
|
||||
module.system.haste.use_name_reducers=true
|
||||
# get basename
|
||||
module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1'
|
||||
# strip .js or .js.flow suffix
|
||||
module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1'
|
||||
# strip .ios suffix
|
||||
module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1'
|
||||
module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1'
|
||||
module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1'
|
||||
module.system.haste.paths.blacklist=.*/__tests__/.*
|
||||
module.system.haste.paths.blacklist=.*/__mocks__/.*
|
||||
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Animated/src/polyfills/.*
|
||||
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/Libraries/.*
|
||||
|
||||
munge_underscores=true
|
||||
|
||||
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
|
||||
|
||||
module.file_ext=.js
|
||||
module.file_ext=.jsx
|
||||
module.file_ext=.json
|
||||
module.file_ext=.native.js
|
||||
|
||||
suppress_type=$FlowIssue
|
||||
suppress_type=$FlowFixMe
|
||||
suppress_type=$FlowFixMeProps
|
||||
suppress_type=$FlowFixMeState
|
||||
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
|
||||
|
||||
[version]
|
||||
^0.78.0
|
||||
1
example/.gitattributes
vendored
@ -1 +0,0 @@
|
||||
*.pbxproj -text
|
||||
56
example/.gitignore
vendored
@ -1,56 +0,0 @@
|
||||
# OSX
|
||||
#
|
||||
.DS_Store
|
||||
|
||||
# Xcode
|
||||
#
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
project.xcworkspace
|
||||
|
||||
# Android/IntelliJ
|
||||
#
|
||||
build/
|
||||
.idea
|
||||
.gradle
|
||||
local.properties
|
||||
*.iml
|
||||
|
||||
# node.js
|
||||
#
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# BUCK
|
||||
buck-out/
|
||||
\.buckd/
|
||||
*.keystore
|
||||
|
||||
# fastlane
|
||||
#
|
||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||
# screenshots whenever they are needed.
|
||||
# For more information about the recommended setup visit:
|
||||
# https://docs.fastlane.tools/best-practices/source-control/
|
||||
|
||||
*/fastlane/report.xml
|
||||
*/fastlane/Preview.html
|
||||
*/fastlane/screenshots
|
||||
|
||||
# Bundle artifact
|
||||
*.jsbundle
|
||||
@ -1,19 +0,0 @@
|
||||
# Example
|
||||
|
||||
An example for experimenting with react-native-image-picker.
|
||||
|
||||
## Usage
|
||||
|
||||
Install dependencies using:
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
Start the packager with:
|
||||
|
||||
```bash
|
||||
yarn start
|
||||
```
|
||||
|
||||
You will have to reinstall `react-native-image-picker` every time you do changes in the library: `rm -rf node_modules && yarn install` (from `./example` folder).
|
||||
17
example/android/app/proguard-rules.pro
vendored
@ -1,17 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 15 KiB |
BIN
example/android/gradle/wrapper/gradle-wrapper.jar
vendored
@ -1,8 +0,0 @@
|
||||
keystore(
|
||||
name = "debug",
|
||||
properties = "debug.keystore.properties",
|
||||
store = "debug.keystore",
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
)
|
||||
@ -1,4 +0,0 @@
|
||||
key.store=debug.keystore
|
||||
key.alias=androiddebugkey
|
||||
key.store.password=android
|
||||
key.alias.password=android
|
||||
@ -1,5 +0,0 @@
|
||||
rootProject.name = 'Example'
|
||||
include ':react-native-image-picker'
|
||||
project(':react-native-image-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-picker/android')
|
||||
|
||||
include ':app'
|
||||
@ -1,4 +0,0 @@
|
||||
{
|
||||
"name": "Example",
|
||||
"displayName": "Example"
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
/** @format */
|
||||
|
||||
import {AppRegistry} from 'react-native';
|
||||
import App from './App';
|
||||
import {name as appName} from './app.json';
|
||||
|
||||
AppRegistry.registerComponent(appName, () => App);
|
||||
@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||