├── jsconfig.json
├── android
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── rngrp
│ │ ├── RNGRPPackage.java
│ │ └── GRP.java
└── build.gradle
├── package.json
├── LICENSE
├── GRP.common.js
└── README.md
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES6",
4 | "module": "commonjs"
5 | }
6 | }
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-get-real-path",
3 | "version": "1.0.1",
4 | "description": "Get real file path from uri",
5 | "main": "GRP.common.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git@github.com:wraptime/react-native-get-real-path.git"
12 | },
13 | "keywords": [
14 | "react-component",
15 | "react-native",
16 | "android",
17 | "fs",
18 | "filesystem",
19 | "uri",
20 | "path"
21 | ],
22 | "author": "Anton Dobrovolskyy (https://github.com/anton6)",
23 | "license": "MIT",
24 | "dependencies": {
25 |
26 | },
27 | "devDependencies": {
28 | "react-native": "*"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rngrp/RNGRPPackage.java:
--------------------------------------------------------------------------------
1 | package com.rngrp;
2 |
3 | import java.util.*;
4 |
5 | import com.facebook.react.ReactPackage;
6 | import com.facebook.react.bridge.NativeModule;
7 | import com.facebook.react.bridge.JavaScriptModule;
8 | import com.facebook.react.bridge.ReactApplicationContext;
9 | import com.facebook.react.uimanager.ViewManager;
10 |
11 | public class RNGRPPackage implements ReactPackage {
12 |
13 | @Override
14 | public List createNativeModules(ReactApplicationContext reactContext) {
15 | List modules = new ArrayList<>();
16 | modules.add(new GRP(reactContext));
17 | return modules;
18 | }
19 |
20 | public List> createJSModules() {
21 | return Collections.emptyList();
22 | }
23 |
24 | @Override
25 | public List createViewManagers(ReactApplicationContext reactContext) {
26 | return Arrays.asList();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Wraptime
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:4.2.2'
9 | classpath 'com.google.gms:google-services:4.3.3'
10 | }
11 | }
12 |
13 | apply plugin: 'com.android.library'
14 |
15 | def _ext = rootProject.ext;
16 | def _compileSdkVersion = _ext.has('compileSdkVersion') ? _ext.compileSdkVersion : 30;
17 | def _buildToolsVersion = _ext.has('buildToolsVersion') ? _ext.buildToolsVersion : '30.0.2';
18 | def _minSdkVersion = _ext.has('minSdkVersion') ? _ext.minSdkVersion : 24;
19 | def _targetSdkVersion = _ext.has('targetSdkVersion') ? _ext.targetSdkVersion : 30;
20 |
21 | android {
22 | compileSdkVersion _compileSdkVersion
23 | buildToolsVersion _buildToolsVersion
24 |
25 | defaultConfig {
26 | minSdkVersion _minSdkVersion
27 | targetSdkVersion _targetSdkVersion
28 | versionCode 1
29 | versionName "1.0"
30 | }
31 | lintOptions {
32 | abortOnError false
33 | }
34 | }
35 |
36 | dependencies {
37 | implementation 'com.facebook.react:react-native:+'
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/GRP.common.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // This file supports both iOS and Android
4 |
5 | // Stop bluebird going nuts because it can't find "self"
6 | if (typeof self === 'undefined') {
7 | global.self = global;
8 | }
9 |
10 | var GRP = require('react-native').NativeModules.GRP;
11 |
12 | function promisify(func) {
13 | return function promiseFunc(options) {
14 | return new Promise(function executor(resolve, reject) {
15 | func(options, function cb(err, val) {
16 | if (err) {
17 | return reject(err);
18 | } else {
19 | return resolve(val);
20 | }
21 | });
22 | });
23 | }
24 | }
25 |
26 | var _getRealPathFromURI = promisify(GRP ? GRP.getRealPathFromURI : (fileUri) => { return fileUri; });
27 |
28 | var convertError = (err) => {
29 | if (err.isOperational && err.cause) {
30 | err = err.cause;
31 | }
32 |
33 | var error = new Error(err.description || err.message);
34 | error.code = err.code;
35 | throw error;
36 | };
37 |
38 | var RNGRP = {
39 | getRealPathFromURI(fileUri) {
40 | return _getRealPathFromURI(fileUri)
41 | .then(path => path)
42 | .catch(convertError);
43 | }
44 | };
45 |
46 | module.exports = RNGRP;
47 |
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## react-native-get-real-path
2 |
3 | Get real file path from file uri
4 |
5 | ## Installation (iOS)
6 |
7 | Currently No Support
8 |
9 | ## Installation (Android)
10 |
11 | `npm i react-native-get-real-path@https://github.com/Wraptime/react-native-get-real-path.git --save`
12 |
13 | Make alterations to the following files:
14 |
15 | * `android/settings.gradle`
16 |
17 | ```gradle
18 | ...
19 | include ':react-native-get-real-path'
20 | project(':react-native-get-real-path').projectDir = new File(settingsDir, '../node_modules/react-native-get-real-path/android')
21 | ```
22 |
23 | * `android/app/build.gradle`
24 |
25 | ```gradle
26 | ...
27 | dependencies {
28 | ...
29 | implementation project(':react-native-get-real-path')
30 | }
31 | ```
32 |
33 | * register module (in MainActivity.java)
34 |
35 | * For react-native below 0.19.0 (use `cat ./node_modules/react-native/package.json | grep version`)
36 |
37 | ```java
38 | import com.rngrp.RNGRPPackage; // <--- import
39 |
40 | public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
41 |
42 | ......
43 |
44 | @Override
45 | protected void onCreate(Bundle savedInstanceState) {
46 | super.onCreate(savedInstanceState);
47 | mReactRootView = new ReactRootView(this);
48 |
49 | mReactInstanceManager = ReactInstanceManager.builder()
50 | .setApplication(getApplication())
51 | .setBundleAssetName("index.android.bundle")
52 | .setJSMainModuleName("index.android")
53 | .addPackage(new MainReactPackage())
54 | .addPackage(new RNGRPPackage()) // <------- add package
55 | .setUseDeveloperSupport(BuildConfig.DEBUG)
56 | .setInitialLifecycleState(LifecycleState.RESUMED)
57 | .build();
58 |
59 | mReactRootView.startReactApplication(mReactInstanceManager, "ExampleRN", null);
60 |
61 | setContentView(mReactRootView);
62 | }
63 |
64 | ......
65 |
66 | }
67 | ```
68 |
69 | * For react-native 0.19.0 and higher
70 | ```java
71 | import com.rngrp.RNGRPPackage; // <------- add package
72 |
73 | public class MainActivity extends ReactActivity {
74 | // ...
75 | @Override
76 | protected List getPackages() {
77 | return Arrays.asList(
78 | new MainReactPackage(), // <---- add comma
79 | new RNGRPPackage() // <---------- add package
80 | );
81 | }
82 | ```
83 |
84 | ## Example usage (Android only)
85 |
86 | ```javascript
87 | // require the module
88 | var RNGRP = require('react-native-get-real-path');
89 |
90 | RNGRP.getRealPathFromURI(fileUri).then(filePath =>
91 | console.log(filePath)
92 | )
93 | ```
94 |
95 | ## Use Case - get images from CameraRoll as base64
96 |
97 | * Required: react-native-fs
98 | https://github.com/johanneslumpe/react-native-fs
99 |
100 | ```javascript
101 | RNGRP.getRealPathFromURI(imageUri).then(path =>
102 | RNFS.readFile(path, 'base64').then(imageBase64 =>
103 | console.log(imageBase64)
104 | )
105 | )
106 | ```
107 |
108 | * For iOS you can checkout: https://github.com/scottdixon/react-native-upload-from-camera-roll/
109 |
110 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rngrp/GRP.java:
--------------------------------------------------------------------------------
1 | package com.rngrp;
2 |
3 | import java.io.InputStream;
4 | import java.io.IOException;
5 | import java.io.FileNotFoundException;
6 | import java.io.OutputStream;
7 | import java.io.FileOutputStream;
8 | import java.io.File;
9 | import java.util.Date;
10 | import java.util.Random;
11 |
12 | import android.content.ContentUris;
13 | import android.content.Context;
14 | import android.net.Uri;
15 | import android.os.Build;
16 | import android.os.Environment;
17 | import android.provider.DocumentsContract;
18 | import android.provider.MediaStore;
19 | import android.database.Cursor;
20 |
21 | import com.facebook.react.bridge.NativeModule;
22 | import com.facebook.react.bridge.ReactApplicationContext;
23 | import com.facebook.react.bridge.ReactContext;
24 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
25 | import com.facebook.react.bridge.ReactMethod;
26 | import com.facebook.react.bridge.Callback;
27 | import com.facebook.react.bridge.WritableMap;
28 | import com.facebook.react.bridge.Arguments;
29 |
30 | public class GRP extends ReactContextBaseJavaModule {
31 |
32 | public GRP(ReactApplicationContext reactContext) {
33 | super(reactContext);
34 | }
35 |
36 | @Override
37 | public String getName() {
38 | return "GRP";
39 | }
40 |
41 | private WritableMap makeErrorPayload(Exception ex) {
42 | WritableMap error = Arguments.createMap();
43 | error.putString("message", ex.getMessage());
44 | return error;
45 | }
46 |
47 | @ReactMethod
48 | public void getRealPathFromURI(String uriString, Callback callback) {
49 | Uri uri = Uri.parse(uriString);
50 | try {
51 | Context context = getReactApplicationContext();
52 | final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
53 | if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
54 | if (isMediaDocument(uri)) {
55 | // http://www.banbaise.com/archives/745
56 | final String docId = DocumentsContract.getDocumentId(uri);
57 | final String[] split = docId.split(":");
58 | final String type = split[0];
59 |
60 | Uri contentUri = null;
61 | if ("image".equals(type)) {
62 | contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
63 | } else if ("video".equals(type)) {
64 | contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
65 | } else if ("audio".equals(type)) {
66 | contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
67 | }
68 |
69 | final String selection = "_id=?";
70 | final String[] selectionArgs = new String[] { split[1] };
71 |
72 | callback.invoke(null, getDataColumn(context, contentUri, selection, selectionArgs));
73 | } else if (isDownloadsDocument(uri)) {
74 |
75 | final String id = DocumentsContract.getDocumentId(uri);
76 |
77 | if (id.startsWith("raw:")) {
78 | callback.invoke(null, id.replaceFirst("raw:", ""));
79 | } else {
80 | String[] contentUriPrefixesToTry = new String[]{
81 | "content://downloads/public_downloads",
82 | "content://downloads/my_downloads",
83 | "content://downloads/all_downloads"
84 | };
85 |
86 | String path = null;
87 | for (String contentUriPrefix : contentUriPrefixesToTry) {
88 | Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
89 | try {
90 | path = getDataColumn(context, contentUri, null, null);
91 | if (path != null) {
92 | break;
93 | }
94 | } catch (Exception e) {}
95 | }
96 |
97 | if (path == null) {
98 | long millis = System.currentTimeMillis();
99 | String datetime = new Date().toString();
100 | datetime = datetime.replace(" ", "");
101 | datetime = datetime.replace(":", "");
102 | final String displayName = random() + "_" + datetime + "_" + millis;
103 |
104 | path = writeFile(context, uri, displayName.replace(".", ""));
105 | }
106 |
107 | callback.invoke(null, path);
108 | }
109 | } else if (isExternalStorageDocument(uri)) {
110 | final String docId = DocumentsContract.getDocumentId(uri);
111 | final String[] split = docId.split(":");
112 | final String type = split[0];
113 |
114 | if ("primary".equalsIgnoreCase(type)) {
115 | callback.invoke(null, Environment.getExternalStorageDirectory() + "/" + split[1]);
116 | } else {
117 | String[] proj = {MediaStore.Images.Media.DATA};
118 | Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
119 | int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
120 | cursor.moveToFirst();
121 | String path = cursor.getString(column_index);
122 | cursor.close();
123 |
124 | callback.invoke(null, path);
125 | }
126 | }
127 | }
128 | else if ("content".equalsIgnoreCase(uri.getScheme())) {
129 | callback.invoke(null,getDataColumn(context, uri, null, null));
130 | }
131 | else if ("file".equalsIgnoreCase(uri.getScheme())) {
132 | callback.invoke(null, uri.getPath());
133 | }
134 | } catch (Exception ex) {
135 | ex.printStackTrace();
136 | callback.invoke(makeErrorPayload(ex));
137 | }
138 | }
139 |
140 | public static String random() {
141 | Random generator = new Random();
142 | StringBuilder randomStringBuilder = new StringBuilder();
143 | int randomLength = generator.nextInt(10);
144 | char tempChar;
145 | for (int i = 0; i < randomLength; i++){
146 | tempChar = (char) (generator.nextInt(96) + 32);
147 | randomStringBuilder.append(tempChar);
148 | }
149 | return randomStringBuilder.toString();
150 | }
151 |
152 | public static boolean isMediaDocument(Uri uri) {
153 | return "com.android.providers.media.documents".equals(uri.getAuthority());
154 | }
155 |
156 | public static boolean isDownloadsDocument(Uri uri) {
157 | return "com.android.providers.downloads.documents".equals(uri.getAuthority());
158 | }
159 | public static boolean isExternalStorageDocument(Uri uri) {
160 | return "com.android.externalstorage.documents".equals(uri.getAuthority());
161 | }
162 | public static String getDataColumn(Context context, Uri uri, String selection,
163 | String[] selectionArgs) {
164 | // https://github.com/hiddentao/cordova-plugin-filepath/pull/6
165 | Cursor cursor = null;
166 | final String[] projection = {MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DISPLAY_NAME};
167 |
168 | try {
169 | /* get `_data` */
170 | cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
171 | if (cursor != null && cursor.moveToFirst()) {
172 | int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
173 | /* bingo! */
174 | final String filepath = cursor.getString(column_index);
175 |
176 | if (filepath != null) {
177 | return filepath;
178 | } else {
179 | column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME);
180 | final String displayName = cursor.getString(column_index);
181 |
182 | return writeFile(context, uri, displayName);
183 | }
184 | }
185 | } catch (Exception e) {
186 | if (cursor != null) {
187 | final int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME);
188 | final String displayName = cursor.getString(column_index);
189 |
190 | return writeFile(context, uri, displayName);
191 | }
192 | } finally {
193 | if (cursor != null)
194 | cursor.close();
195 | }
196 | return null;
197 | }
198 | public static String writeFile(Context context, Uri uri, String displayName) {
199 | InputStream input = null;
200 | try {
201 | input = context.getContentResolver().openInputStream(uri);
202 | /* save stream to temp file */
203 | try {
204 | File file = new File(context.getCacheDir(), displayName);
205 | OutputStream output = new FileOutputStream(file);
206 | try {
207 | byte[] buffer = new byte[4 * 1024]; // or other buffer size
208 | int read;
209 |
210 | while ((read = input.read(buffer)) != -1) {
211 | output.write(buffer, 0, read);
212 | }
213 | output.flush();
214 |
215 | final String outputPath = file.getAbsolutePath();
216 | return outputPath;
217 |
218 | } finally {
219 | output.close();
220 | }
221 | } catch (Exception e1a) {
222 | //
223 | } finally {
224 | try {
225 | input.close();
226 | } catch (IOException e1b) {
227 | //
228 | }
229 | }
230 | } catch (FileNotFoundException e2) {
231 | //
232 | } finally {
233 | if (input != null) {
234 | try {
235 | input.close();
236 | } catch (IOException e3) {
237 | //
238 | }
239 | }
240 | }
241 |
242 | return null;
243 | }
244 | }
245 |
--------------------------------------------------------------------------------