Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 80 additions & 9 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,30 +1,97 @@
import java.nio.file.Paths

def resolveReactNativeDirectory() {
def reactNativeLocation = safeExtGet("REACT_NATIVE_NODE_MODULES_DIR", null)
if (reactNativeLocation != null) {
return file(reactNativeLocation)
}

// monorepo workaround
// react-native can be hoisted or in project's own node_modules
def reactNativeFromProjectNodeModules = file("${rootProject.projectDir}/../node_modules/react-native")
if (reactNativeFromProjectNodeModules.exists()) {
return reactNativeFromProjectNodeModules
}

def reactNativeFromNodeModulesWithAsyncStorage = file("${projectDir}/../../react-native")
if (reactNativeFromNodeModulesWithAsyncStorage.exists()) {
return reactNativeFromNodeModulesWithAsyncStorage
}

throw new Exception(
"[react-native-document-picker] Unable to resolve react-native location in " +
"node_modules. You should add project extension property (in app/build.gradle) " +
"`REACT_NATIVE_NODE_MODULES_DIR` with path to react-native."
)
}

def getReactNativeMinorVersion() {
def REACT_NATIVE_DIR = resolveReactNativeDirectory()

def reactProperties = new Properties()
file("$REACT_NATIVE_DIR/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }

def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME")
def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.startsWith("0.0.0-") ? 1000 : REACT_NATIVE_VERSION.split("\\.")[1].toInteger()

return REACT_NATIVE_MINOR_VERSION
}

def isNewArchitectureEnabled() {
// To opt-in for the New Architecture, you can either:
// - Set `newArchEnabled` to true inside the `gradle.properties` file
// - Invoke gradle with `-newArchEnabled=true`
// - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
}

buildscript {
if (project == rootProject) {
repositories {
google()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
}
// dependencies {
// classpath 'com.android.tools.build:gradle:7.2.2'
// }
}
}

apply plugin: 'com.android.library'
if (isNewArchitectureEnabled()) {
apply(plugin: "com.facebook.react")
}

def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}

android {
compileSdkVersion safeExtGet('compileSdkVersion', 29)
buildToolsVersion safeExtGet('buildToolsVersion', '29.0.2')

// Used to override the NDK path/version by allowing users to customize
// the NDK path/version from their root project (e.g. for M1 support)
if (rootProject.hasProperty("ndkPath")) {
ndkPath rootProject.ext.ndkPath
}
if (rootProject.hasProperty("ndkVersion")) {
ndkVersion rootProject.ext.ndkVersion
}

compileSdkVersion safeExtGet('compileSdkVersion', 30)
buildToolsVersion safeExtGet('buildToolsVersion', '30.0.3')
defaultConfig {
minSdkVersion safeExtGet('minSdkVersion', 21)
targetSdkVersion safeExtGet('targetSdkVersion', 29)
versionCode 1
versionName "1.0"
targetSdkVersion safeExtGet('targetSdkVersion', 30)
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
}

sourceSets.main {
java {
if (!isNewArchitectureEnabled()) {
srcDirs += 'src/paper/java'
}
}
}

buildTypes {
Expand Down Expand Up @@ -52,5 +119,9 @@ repositories {

dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
if (isNewArchitectureEnabled() && getReactNativeMinorVersion() < 71) {
implementation project(":ReactAndroid")
} else {
implementation 'com.facebook.react:react-native:+' // from node_modules
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,11 @@
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.module.annotations.ReactModule;

import java.io.File;
import java.io.FileOutputStream;
Expand All @@ -39,8 +37,7 @@
import java.util.List;
import java.util.UUID;

@ReactModule(name = DocumentPickerModule.NAME)
public class DocumentPickerModule extends ReactContextBaseJavaModule {
public class RNDocumentPickerModule extends NativeDocumentPickerSpec {
public static final String NAME = "RNDocumentPicker";
private static final int READ_REQUEST_CODE = 41;
private static final int PICK_DIR_REQUEST_CODE = 42;
Expand All @@ -64,6 +61,14 @@ public class DocumentPickerModule extends ReactContextBaseJavaModule {
private static final String FIELD_TYPE = "type";
private static final String FIELD_SIZE = "size";

private Promise promise;
private String copyTo;

public RNDocumentPickerModule(ReactApplicationContext reactContext) {
super(reactContext);
reactContext.addActivityEventListener(activityEventListener);
}

private final ActivityEventListener activityEventListener = new BaseActivityEventListener() {
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
Expand All @@ -89,14 +94,6 @@ private String[] readableArrayToStringArray(ReadableArray readableArray) {
return array;
}

private Promise promise;
private String copyTo;

public DocumentPickerModule(ReactApplicationContext reactContext) {
super(reactContext);
reactContext.addActivityEventListener(activityEventListener);
}

@Override
public void onCatalystInstanceDestroy() {
super.onCatalystInstanceDestroy();
Expand Down Expand Up @@ -167,6 +164,11 @@ public void pickDirectory(Promise promise) {
}
}

@Override
public void releaseSecureAccess(ReadableArray uris, Promise promise) {
promise.reject("RNDocumentPicker:releaseSecureAccess", "releaseSecureAccess is not supported on Android");
}

private void onPickDirectoryResult(int resultCode, Intent data) {
if (resultCode == Activity.RESULT_CANCELED) {
sendError(E_DOCUMENT_PICKER_CANCELED, "User canceled directory picker");
Expand Down Expand Up @@ -267,8 +269,6 @@ private WritableMap getMetadata(Uri uri) {
if (!cursor.isNull(displayNameIndex)) {
String fileName = cursor.getString(displayNameIndex);
map.putString(FIELD_NAME, fileName);
} else {
map.putNull(FIELD_NAME);
}
int mimeIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_MIME_TYPE);
if (!cursor.isNull(mimeIndex)) {
Expand All @@ -277,8 +277,6 @@ private WritableMap getMetadata(Uri uri) {
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
if (!cursor.isNull(sizeIndex)) {
map.putInt(FIELD_SIZE, cursor.getInt(sizeIndex));
} else {
map.putNull(FIELD_SIZE);
}
}
}
Expand All @@ -288,48 +286,63 @@ private WritableMap getMetadata(Uri uri) {
}

private void prepareFileUri(Context context, WritableMap map, Uri uri) {
if (copyTo == null) {
map.putNull(FIELD_FILE_COPY_URI);
} else {
copyFileToLocalStorage(context, map, uri);
}
}

private void copyFileToLocalStorage(Context context, WritableMap map, Uri uri) {
File dir = context.getCacheDir();
if (copyTo.equals("documentDirectory")) {
dir = context.getFilesDir();
}
// we don't want to rename the file so we put it into a unique location
dir = new File(dir, UUID.randomUUID().toString());
try {
boolean didCreateDir = dir.mkdir();
if (!didCreateDir) {
throw new IOException("failed to create directory at " + dir.getAbsolutePath());
if (copyTo != null) {
File dir = context.getCacheDir();
if (copyTo.equals("documentDirectory")) {
dir = context.getFilesDir();
}
String fileName = map.getString(FIELD_NAME);
if (fileName == null) {
fileName = String.valueOf(System.currentTimeMillis());
// we don't want to rename the file so we put it into a unique location
dir = new File(dir, UUID.randomUUID().toString());
try {
boolean didCreateDir = dir.mkdir();
if (!didCreateDir) {
throw new IOException("failed to create directory at " + dir.getAbsolutePath());
}
String fileName = map.getString(FIELD_NAME);
if (fileName == null) {
fileName = String.valueOf(System.currentTimeMillis());
}
File destFile = new File(dir, fileName);
String copyPath = copyFile(context, uri, destFile);
map.putString(FIELD_FILE_COPY_URI, copyPath);
} catch (Exception e) {
e.printStackTrace();
map.putNull(FIELD_FILE_COPY_URI);
map.putString(FIELD_COPY_ERROR, e.getLocalizedMessage());
}
File destFile = new File(dir, fileName);
Uri copyPath = copyFile(context, uri, destFile);
map.putString(FIELD_FILE_COPY_URI, copyPath.toString());
} catch (Exception e) {
e.printStackTrace();
} else {
map.putNull(FIELD_FILE_COPY_URI);
map.putString(FIELD_COPY_ERROR, e.getLocalizedMessage());
}
}

public static Uri copyFile(Context context, Uri uri, File destFile) throws IOException {
try(InputStream inputStream = context.getContentResolver().openInputStream(uri);
FileOutputStream outputStream = new FileOutputStream(destFile)) {
byte[] buf = new byte[8192];
int len;
while ((len = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, len);
public static String copyFile(Context context, Uri uri, File destFile) throws IOException {
InputStream in = null;
FileOutputStream out = null;
try {
in = context.getContentResolver().openInputStream(uri);
if (in != null) {
out = new FileOutputStream(destFile);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.close();
in.close();
return destFile.toURI().toString();
} else {
throw new NullPointerException("Invalid input stream");
}
return Uri.fromFile(destFile);
} catch (Exception e) {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ignored) {}
throw e;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.reactnativedocumentpicker;

import androidx.annotation.Nullable;

import com.facebook.react.TurboReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;

import java.util.HashMap;
import java.util.Map;

public class RNDocumentPickerPackage extends TurboReactPackage {

@Nullable
@Override
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
if (name.equals(RNDocumentPickerModule.NAME)) {
return new RNDocumentPickerModule(reactContext);
} else {
return null;
}
}

@Override
public ReactModuleInfoProvider getReactModuleInfoProvider() {
return () -> {
boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
moduleInfos.put(
RNDocumentPickerModule.NAME,
new ReactModuleInfo(
RNDocumentPickerModule.NAME,
RNDocumentPickerModule.NAME,
// "DocumentPickerModule",
false, // canOverrideExistingModule
false, // needsEagerInit
true, // hasConstants
false, // isCxxModule
isTurboModule // isTurboModule
));
return moduleInfos;
};
}
}
Loading