Skip to content

Commit dea7c81

Browse files
author
Ron Radtke
committed
Update:
* Media store support fixes #95 fixes #62 fixes #100 fixes #91 Merge remote-tracking branch 'origin/develop'
2 parents 6801d80 + 71d1c44 commit dea7c81

23 files changed

+1460
-753
lines changed

README.md

Lines changed: 471 additions & 406 deletions
Large diffs are not rendered by default.

android/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ android {
5959

6060
dependencies {
6161
implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}"
62+
implementation 'org.apache.commons:commons-lang3:3.0'
6263
}
6364

6465
afterEvaluate { project ->

android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtil.java

Lines changed: 86 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22

33
import android.app.Activity;
44
import android.app.DownloadManager;
5+
import android.content.ActivityNotFoundException;
56
import android.content.Intent;
6-
import android.content.pm.PackageManager;
77
import android.net.Uri;
88
import android.os.Build;
9+
import android.util.SparseArray;
910

11+
import androidx.annotation.NonNull;
12+
import androidx.annotation.RequiresApi;
1013
import androidx.core.content.FileProvider;
1114

12-
import android.util.SparseArray;
13-
import android.content.ActivityNotFoundException;
14-
15+
import com.ReactNativeBlobUtil.Utils.FileDescription;
1516
import com.facebook.react.bridge.ActivityEventListener;
1617
import com.facebook.react.bridge.Callback;
1718
import com.facebook.react.bridge.LifecycleEventListener;
@@ -21,24 +22,22 @@
2122
import com.facebook.react.bridge.ReactMethod;
2223
import com.facebook.react.bridge.ReadableArray;
2324
import com.facebook.react.bridge.ReadableMap;
24-
25-
// Cookies
2625
import com.facebook.react.bridge.WritableMap;
27-
import com.facebook.react.modules.network.ForwardingCookieHandler;
2826
import com.facebook.react.modules.network.CookieJarContainer;
27+
import com.facebook.react.modules.network.ForwardingCookieHandler;
2928
import com.facebook.react.modules.network.OkHttpClientProvider;
3029

31-
import okhttp3.JavaNetCookieJar;
32-
import okhttp3.OkHttpClient;
33-
34-
import javax.annotation.Nullable;
35-
3630
import java.io.File;
3731
import java.util.Map;
3832
import java.util.concurrent.LinkedBlockingQueue;
3933
import java.util.concurrent.ThreadPoolExecutor;
4034
import java.util.concurrent.TimeUnit;
4135

36+
import javax.annotation.Nullable;
37+
38+
import okhttp3.JavaNetCookieJar;
39+
import okhttp3.OkHttpClient;
40+
4241
import static android.app.Activity.RESULT_OK;
4342
import static com.ReactNativeBlobUtil.ReactNativeBlobUtilConst.GET_CONTENT_INTENT;
4443

@@ -81,6 +80,7 @@ public void onNewIntent(Intent intent) {
8180
});
8281
}
8382

83+
@NonNull
8484
@Override
8585
public String getName() {
8686
return "ReactNativeBlobUtil";
@@ -114,9 +114,13 @@ public void run() {
114114
@ReactMethod
115115
public void actionViewIntent(String path, String mime, @Nullable String chooserTitle, final Promise promise) {
116116
try {
117-
Uri uriForFile = FileProvider.getUriForFile(this.getReactApplicationContext(),
118-
this.getReactApplicationContext().getPackageName() + ".provider", new File(path));
119-
117+
Uri uriForFile = null;
118+
if (!ReactNativeBlobUtilUtils.isContentUri(path)) {
119+
uriForFile = FileProvider.getUriForFile(this.getReactApplicationContext(),
120+
this.getReactApplicationContext().getPackageName() + ".provider", new File(path));
121+
} else {
122+
uriForFile = Uri.parse(path);
123+
}
120124
Intent intent = new Intent(Intent.ACTION_VIEW);
121125
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
122126
// Create the intent with data and type
@@ -170,7 +174,7 @@ public void onHostDestroy() {
170174

171175
@ReactMethod
172176
public void writeArrayChunk(final String streamId, final ReadableArray dataArray, final Callback callback) {
173-
ReactNativeBlobUtilFS.writeArrayChunk(streamId, dataArray, callback);
177+
ReactNativeBlobUtilStream.writeArrayChunk(streamId, dataArray, callback);
174178
}
175179

176180
@ReactMethod
@@ -210,17 +214,17 @@ public void ls(String path, Promise promise) {
210214

211215
@ReactMethod
212216
public void writeStream(String path, String encode, boolean append, Callback callback) {
213-
new ReactNativeBlobUtilFS(this.getReactApplicationContext()).writeStream(path, encode, append, callback);
217+
new ReactNativeBlobUtilStream(this.getReactApplicationContext()).writeStream(path, encode, append, callback);
214218
}
215219

216220
@ReactMethod
217221
public void writeChunk(String streamId, String data, Callback callback) {
218-
ReactNativeBlobUtilFS.writeChunk(streamId, data, callback);
222+
ReactNativeBlobUtilStream.writeChunk(streamId, data, callback);
219223
}
220224

221225
@ReactMethod
222226
public void closeStream(String streamId, Callback callback) {
223-
ReactNativeBlobUtilFS.closeStream(streamId, callback);
227+
ReactNativeBlobUtilStream.closeStream(streamId, callback);
224228
}
225229

226230
@ReactMethod
@@ -313,7 +317,7 @@ public void readStream(final String path, final String encoding, final int buffe
313317
fsThreadPool.execute(new Runnable() {
314318
@Override
315319
public void run() {
316-
ReactNativeBlobUtilFS fs = new ReactNativeBlobUtilFS(ctx);
320+
ReactNativeBlobUtilStream fs = new ReactNativeBlobUtilStream(ctx);
317321
fs.readStream(path, encoding, bufferSize, tick, streamId);
318322
}
319323
});
@@ -386,7 +390,7 @@ public void addCompleteDownload(ReadableMap config, Promise promise) {
386390
promise.reject("EINVAL", "ReactNativeBlobUtil.addCompleteDownload config or path missing.");
387391
return;
388392
}
389-
String path = ReactNativeBlobUtilFS.normalizePath(config.getString("path"));
393+
String path = ReactNativeBlobUtilUtils.normalizePath(config.getString("path"));
390394
if (path == null) {
391395
promise.reject("EINVAL", "ReactNativeBlobUtil.addCompleteDownload can not resolve URI:" + config.getString("path"));
392396
return;
@@ -418,4 +422,65 @@ public void getSDCardDir(Promise promise) {
418422
public void getSDCardApplicationDir(Promise promise) {
419423
ReactNativeBlobUtilFS.getSDCardApplicationDir(this.getReactApplicationContext(), promise);
420424
}
425+
426+
@ReactMethod
427+
public void createMediaFile(ReadableMap filedata, String mt, Promise promise) {
428+
if (!(filedata.hasKey("name") && filedata.hasKey("parentFolder") && filedata.hasKey("mimeType"))) {
429+
promise.reject("ReactNativeBlobUtil.createMediaFile", "invalid filedata: " + filedata.toString());
430+
return;
431+
}
432+
if (mt == null) promise.reject("ReactNativeBlobUtil.createMediaFile", "invalid mediatype");
433+
434+
FileDescription file = new FileDescription(filedata.getString("name"), filedata.getString("mimeType"), filedata.getString("parentFolder"));
435+
Uri res = ReactNativeBlobUtilMediaCollection.createNewMediaFile(file, ReactNativeBlobUtilMediaCollection.MediaType.valueOf(mt));
436+
if (res != null) promise.resolve(res.toString());
437+
else promise.reject("ReactNativeBlobUtil.createMediaFile", "File could not be created");
438+
}
439+
440+
@RequiresApi(api = Build.VERSION_CODES.Q)
441+
@ReactMethod
442+
public void writeToMediaFile(String fileUri, String path, Promise promise) {
443+
boolean res = ReactNativeBlobUtilMediaCollection.writeToMediaFile(Uri.parse(fileUri), path, promise);
444+
if(res) promise.resolve("Success");
445+
}
446+
447+
@ReactMethod
448+
public void copyToInternal(String contentUri, String destpath, Promise promise) {
449+
ReactNativeBlobUtilMediaCollection.copyToInternal(Uri.parse(contentUri), destpath, promise);
450+
}
451+
452+
@ReactMethod
453+
public void getBlob(String contentUri, String encoding, Promise promise) {
454+
ReactNativeBlobUtilMediaCollection.getBlob(Uri.parse(contentUri), encoding, promise);
455+
}
456+
457+
@RequiresApi(api = Build.VERSION_CODES.Q)
458+
@ReactMethod
459+
public void copyToMediaStore(ReadableMap filedata, String mt, String path, Promise promise) {
460+
if (!(filedata.hasKey("name") && filedata.hasKey("parentFolder") && filedata.hasKey("mimeType"))) {
461+
promise.reject("ReactNativeBlobUtil.createMediaFile", "invalid filedata: " + filedata.toString());
462+
return;
463+
}
464+
if (mt == null) {
465+
promise.reject("ReactNativeBlobUtil.createMediaFile", "invalid mediatype");
466+
return;
467+
}
468+
if (path == null) {
469+
promise.reject("ReactNativeBlobUtil.createMediaFile", "invalid path");
470+
return;
471+
}
472+
473+
FileDescription file = new FileDescription(filedata.getString("name"), filedata.getString("mimeType"), filedata.getString("parentFolder"));
474+
Uri fileuri = ReactNativeBlobUtilMediaCollection.createNewMediaFile(file, ReactNativeBlobUtilMediaCollection.MediaType.valueOf(mt));
475+
476+
if (fileuri == null) {
477+
promise.reject("ReactNativeBlobUtil.createMediaFile", "File could not be created");
478+
return;
479+
}
480+
481+
boolean res = ReactNativeBlobUtilMediaCollection.writeToMediaFile(fileuri, path, promise);
482+
483+
if(res) promise.resolve(fileuri.toString());
484+
}
485+
421486
}

android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilBody.java

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package com.ReactNativeBlobUtil;
22

3-
import androidx.annotation.NonNull;
4-
3+
import android.net.Uri;
54
import android.util.Base64;
65

6+
import androidx.annotation.NonNull;
7+
78
import com.facebook.react.bridge.Arguments;
89
import com.facebook.react.bridge.ReactApplicationContext;
910
import com.facebook.react.bridge.ReadableArray;
@@ -19,8 +20,6 @@
1920
import java.io.InputStream;
2021
import java.util.ArrayList;
2122

22-
import android.net.Uri;
23-
2423
import okhttp3.MediaType;
2524
import okhttp3.RequestBody;
2625
import okio.BufferedSink;
@@ -145,17 +144,17 @@ private InputStream getRequestStream() throws Exception {
145144
// upload from storage
146145
if (rawBody.startsWith(ReactNativeBlobUtilConst.FILE_PREFIX)) {
147146
String orgPath = rawBody.substring(ReactNativeBlobUtilConst.FILE_PREFIX.length());
148-
orgPath = ReactNativeBlobUtilFS.normalizePath(orgPath);
147+
orgPath = ReactNativeBlobUtilUtils.normalizePath(orgPath);
149148
// upload file from assets
150-
if (ReactNativeBlobUtilFS.isAsset(orgPath)) {
149+
if (ReactNativeBlobUtilUtils.isAsset(orgPath)) {
151150
try {
152151
String assetName = orgPath.replace(ReactNativeBlobUtilConst.FILE_PREFIX_BUNDLE_ASSET, "");
153152
return ReactNativeBlobUtil.RCTContext.getAssets().open(assetName);
154153
} catch (Exception e) {
155154
throw new Exception("error when getting request stream from asset : " + e.getLocalizedMessage());
156155
}
157156
} else {
158-
File f = new File(ReactNativeBlobUtilFS.normalizePath(orgPath));
157+
File f = new File(ReactNativeBlobUtilUtils.normalizePath(orgPath));
159158
try {
160159
if (!f.exists())
161160
f.createNewFile();
@@ -187,7 +186,7 @@ private InputStream getRequestStream() throws Exception {
187186
* Create a temp file that contains content of multipart form data content
188187
*
189188
* @return The cache file object
190-
* @throws IOException
189+
* @throws IOException .
191190
*/
192191
private File createMultipartBodyCache() throws IOException {
193192
String boundary = "ReactNativeBlobUtil-" + mTaskId;
@@ -215,9 +214,9 @@ private File createMultipartBodyCache() throws IOException {
215214
// upload from storage
216215
if (data.startsWith(ReactNativeBlobUtilConst.FILE_PREFIX)) {
217216
String orgPath = data.substring(ReactNativeBlobUtilConst.FILE_PREFIX.length());
218-
orgPath = ReactNativeBlobUtilFS.normalizePath(orgPath);
217+
orgPath = ReactNativeBlobUtilUtils.normalizePath(orgPath);
219218
// path starts with content://
220-
if (ReactNativeBlobUtilFS.isAsset(orgPath)) {
219+
if (ReactNativeBlobUtilUtils.isAsset(orgPath)) {
221220
try {
222221
String assetName = orgPath.replace(ReactNativeBlobUtilConst.FILE_PREFIX_BUNDLE_ASSET, "");
223222
InputStream in = ctx.getAssets().open(assetName);
@@ -228,7 +227,7 @@ private File createMultipartBodyCache() throws IOException {
228227
}
229228
// data from normal files
230229
else {
231-
File file = new File(ReactNativeBlobUtilFS.normalizePath(orgPath));
230+
File file = new File(ReactNativeBlobUtilUtils.normalizePath(orgPath));
232231
if (file.exists()) {
233232
FileInputStream fs = new FileInputStream(file);
234233
pipeStreamToFileStream(fs, os);
@@ -282,7 +281,7 @@ private File createMultipartBodyCache() throws IOException {
282281
*
283282
* @param stream The input stream
284283
* @param sink The request body buffer sink
285-
* @throws IOException
284+
* @throws IOException .
286285
*/
287286
private void pipeStreamToSink(InputStream stream, BufferedSink sink) throws IOException {
288287
byte[] chunk = new byte[10240];
@@ -332,9 +331,9 @@ private ArrayList<FormField> countFormDataLength() throws IOException {
332331
// upload from storage
333332
if (data.startsWith(ReactNativeBlobUtilConst.FILE_PREFIX)) {
334333
String orgPath = data.substring(ReactNativeBlobUtilConst.FILE_PREFIX.length());
335-
orgPath = ReactNativeBlobUtilFS.normalizePath(orgPath);
334+
orgPath = ReactNativeBlobUtilUtils.normalizePath(orgPath);
336335
// path starts with asset://
337-
if (ReactNativeBlobUtilFS.isAsset(orgPath)) {
336+
if (ReactNativeBlobUtilUtils.isAsset(orgPath)) {
338337
try {
339338
String assetName = orgPath.replace(ReactNativeBlobUtilConst.FILE_PREFIX_BUNDLE_ASSET, "");
340339
long length = ctx.getAssets().open(assetName).available();
@@ -345,7 +344,7 @@ private ArrayList<FormField> countFormDataLength() throws IOException {
345344
}
346345
// general files
347346
else {
348-
File file = new File(ReactNativeBlobUtilFS.normalizePath(orgPath));
347+
File file = new File(ReactNativeBlobUtilUtils.normalizePath(orgPath));
349348
total += file.length();
350349
}
351350
} else if (data.startsWith(ReactNativeBlobUtilConst.CONTENT_PREFIX)) {

android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConfig.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ class ReactNativeBlobUtilConfig {
2525
ReactNativeBlobUtilConfig(ReadableMap options) {
2626
if (options == null)
2727
return;
28-
this.fileCache = options.hasKey("fileCache") ? options.getBoolean("fileCache") : false;
28+
this.fileCache = options.hasKey("fileCache") && options.getBoolean("fileCache");
2929
this.path = options.hasKey("path") ? options.getString("path") : null;
3030
this.appendExt = options.hasKey("appendExt") ? options.getString("appendExt") : "";
31-
this.trusty = options.hasKey("trusty") ? options.getBoolean("trusty") : false;
32-
this.wifiOnly = options.hasKey("wifiOnly") ? options.getBoolean("wifiOnly") : false;
31+
this.trusty = options.hasKey("trusty") && options.getBoolean("trusty");
32+
this.wifiOnly = options.hasKey("wifiOnly") && options.getBoolean("wifiOnly");
3333
if (options.hasKey("addAndroidDownloads")) {
3434
this.addAndroidDownloads = options.getMap("addAndroidDownloads");
3535
}
@@ -45,8 +45,8 @@ class ReactNativeBlobUtilConfig {
4545
}
4646
this.key = options.hasKey("key") ? options.getString("key") : null;
4747
this.mime = options.hasKey("contentType") ? options.getString("contentType") : null;
48-
this.increment = options.hasKey("increment") ? options.getBoolean("increment") : false;
49-
this.auto = options.hasKey("auto") ? options.getBoolean("auto") : false;
48+
this.increment = options.hasKey("increment") && options.getBoolean("increment");
49+
this.auto = options.hasKey("auto") && options.getBoolean("auto");
5050
if (options.hasKey("timeout")) {
5151
this.timeout = options.getInt("timeout");
5252
}

0 commit comments

Comments
 (0)