No Description

RNFetchBlob.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. package com.RNFetchBlob;
  2. import android.app.Activity;
  3. import android.app.DownloadManager;
  4. import android.content.Intent;
  5. import android.content.pm.PackageManager;
  6. import android.net.Uri;
  7. import android.os.Build;
  8. import androidx.core.content.FileProvider;
  9. import android.util.SparseArray;
  10. import com.facebook.react.bridge.ActivityEventListener;
  11. import com.facebook.react.bridge.Callback;
  12. import com.facebook.react.bridge.LifecycleEventListener;
  13. import com.facebook.react.bridge.Promise;
  14. import com.facebook.react.bridge.ReactApplicationContext;
  15. import com.facebook.react.bridge.ReactContextBaseJavaModule;
  16. import com.facebook.react.bridge.ReactMethod;
  17. import com.facebook.react.bridge.ReadableArray;
  18. import com.facebook.react.bridge.ReadableMap;
  19. // Cookies
  20. import com.facebook.react.bridge.WritableMap;
  21. import com.facebook.react.modules.network.ForwardingCookieHandler;
  22. import com.facebook.react.modules.network.CookieJarContainer;
  23. import com.facebook.react.modules.network.OkHttpClientProvider;
  24. import okhttp3.OkHttpClient;
  25. import okhttp3.JavaNetCookieJar;
  26. import java.io.File;
  27. import java.util.Map;
  28. import java.util.concurrent.LinkedBlockingQueue;
  29. import java.util.concurrent.ThreadPoolExecutor;
  30. import java.util.concurrent.TimeUnit;
  31. import static android.app.Activity.RESULT_OK;
  32. import static com.RNFetchBlob.RNFetchBlobConst.GET_CONTENT_INTENT;
  33. public class RNFetchBlob extends ReactContextBaseJavaModule {
  34. private final OkHttpClient mClient;
  35. static ReactApplicationContext RCTContext;
  36. private static LinkedBlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();
  37. private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 5000, TimeUnit.MILLISECONDS, taskQueue);
  38. static LinkedBlockingQueue<Runnable> fsTaskQueue = new LinkedBlockingQueue<>();
  39. private static ThreadPoolExecutor fsThreadPool = new ThreadPoolExecutor(2, 10, 5000, TimeUnit.MILLISECONDS, taskQueue);
  40. private static boolean ActionViewVisible = false;
  41. private static SparseArray<Promise> promiseTable = new SparseArray<>();
  42. public RNFetchBlob(ReactApplicationContext reactContext) {
  43. super(reactContext);
  44. mClient = OkHttpClientProvider.getOkHttpClient();
  45. ForwardingCookieHandler mCookieHandler = new ForwardingCookieHandler(reactContext);
  46. CookieJarContainer mCookieJarContainer = (CookieJarContainer) mClient.cookieJar();
  47. mCookieJarContainer.setCookieJar(new JavaNetCookieJar(mCookieHandler));
  48. RCTContext = reactContext;
  49. reactContext.addActivityEventListener(new ActivityEventListener() {
  50. @Override
  51. public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
  52. if(requestCode == GET_CONTENT_INTENT && resultCode == RESULT_OK) {
  53. Uri d = data.getData();
  54. promiseTable.get(GET_CONTENT_INTENT).resolve(d.toString());
  55. promiseTable.remove(GET_CONTENT_INTENT);
  56. }
  57. }
  58. @Override
  59. public void onNewIntent(Intent intent) {
  60. }
  61. });
  62. }
  63. @Override
  64. public String getName() {
  65. return "RNFetchBlob";
  66. }
  67. @Override
  68. public Map<String, Object> getConstants() {
  69. return RNFetchBlobFS.getSystemfolders(this.getReactApplicationContext());
  70. }
  71. @ReactMethod
  72. public void createFile(final String path, final String content, final String encode, final Promise promise) {
  73. threadPool.execute(new Runnable() {
  74. @Override
  75. public void run() {
  76. RNFetchBlobFS.createFile(path, content, encode, promise);
  77. }
  78. });
  79. }
  80. @ReactMethod
  81. public void createFileASCII(final String path, final ReadableArray dataArray, final Promise promise) {
  82. threadPool.execute(new Runnable() {
  83. @Override
  84. public void run() {
  85. RNFetchBlobFS.createFileASCII(path, dataArray, promise);
  86. }
  87. });
  88. }
  89. @ReactMethod
  90. public void actionViewIntent(String path, String mime, final Promise promise) {
  91. try {
  92. Uri uriForFile = FileProvider.getUriForFile(getCurrentActivity(),
  93. this.getReactApplicationContext().getPackageName() + ".provider", new File(path));
  94. if (Build.VERSION.SDK_INT >= 24) {
  95. // Create the intent with data and type
  96. Intent intent = new Intent(Intent.ACTION_VIEW)
  97. .setDataAndType(uriForFile, mime);
  98. // Set flag to give temporary permission to external app to use FileProvider
  99. intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  100. // All the activity to be opened outside of an activity
  101. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  102. // Validate that the device can open the file
  103. PackageManager pm = getCurrentActivity().getPackageManager();
  104. if (intent.resolveActivity(pm) != null) {
  105. this.getReactApplicationContext().startActivity(intent);
  106. }
  107. } else {
  108. Intent intent = new Intent(Intent.ACTION_VIEW)
  109. .setDataAndType(Uri.parse("file://" + path), mime).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  110. this.getReactApplicationContext().startActivity(intent);
  111. }
  112. ActionViewVisible = true;
  113. final LifecycleEventListener listener = new LifecycleEventListener() {
  114. @Override
  115. public void onHostResume() {
  116. if(ActionViewVisible)
  117. promise.resolve(null);
  118. RCTContext.removeLifecycleEventListener(this);
  119. }
  120. @Override
  121. public void onHostPause() {
  122. }
  123. @Override
  124. public void onHostDestroy() {
  125. }
  126. };
  127. RCTContext.addLifecycleEventListener(listener);
  128. } catch(Exception ex) {
  129. promise.reject("EUNSPECIFIED", ex.getLocalizedMessage());
  130. }
  131. }
  132. @ReactMethod
  133. public void writeArrayChunk(final String streamId, final ReadableArray dataArray, final Callback callback) {
  134. RNFetchBlobFS.writeArrayChunk(streamId, dataArray, callback);
  135. }
  136. @ReactMethod
  137. public void unlink(String path, Callback callback) {
  138. RNFetchBlobFS.unlink(path, callback);
  139. }
  140. @ReactMethod
  141. public void mkdir(String path, Promise promise) {
  142. RNFetchBlobFS.mkdir(path, promise);
  143. }
  144. @ReactMethod
  145. public void exists(String path, Callback callback) {
  146. RNFetchBlobFS.exists(path, callback);
  147. }
  148. @ReactMethod
  149. public void cp(final String path, final String dest, final Callback callback) {
  150. threadPool.execute(new Runnable() {
  151. @Override
  152. public void run() {
  153. RNFetchBlobFS.cp(path, dest, callback);
  154. }
  155. });
  156. }
  157. @ReactMethod
  158. public void mv(String path, String dest, Callback callback) {
  159. RNFetchBlobFS.mv(path, dest, callback);
  160. }
  161. @ReactMethod
  162. public void ls(String path, Promise promise) {
  163. RNFetchBlobFS.ls(path, promise);
  164. }
  165. @ReactMethod
  166. public void writeStream(String path, String encode, boolean append, Callback callback) {
  167. new RNFetchBlobFS(this.getReactApplicationContext()).writeStream(path, encode, append, callback);
  168. }
  169. @ReactMethod
  170. public void writeChunk(String streamId, String data, Callback callback) {
  171. RNFetchBlobFS.writeChunk(streamId, data, callback);
  172. }
  173. @ReactMethod
  174. public void closeStream(String streamId, Callback callback) {
  175. RNFetchBlobFS.closeStream(streamId, callback);
  176. }
  177. @ReactMethod
  178. public void removeSession(ReadableArray paths, Callback callback) {
  179. RNFetchBlobFS.removeSession(paths, callback);
  180. }
  181. @ReactMethod
  182. public void readFile(final String path, final String encoding, final Promise promise) {
  183. threadPool.execute(new Runnable() {
  184. @Override
  185. public void run() {
  186. RNFetchBlobFS.readFile(path, encoding, promise);
  187. }
  188. });
  189. }
  190. @ReactMethod
  191. public void writeFileArray(final String path, final ReadableArray data, final boolean append, final Promise promise) {
  192. threadPool.execute(new Runnable() {
  193. @Override
  194. public void run() {
  195. RNFetchBlobFS.writeFile(path, data, append, promise);
  196. }
  197. });
  198. }
  199. @ReactMethod
  200. public void writeFile(final String path, final String encoding, final String data, final boolean append, final Promise promise) {
  201. threadPool.execute(new Runnable() {
  202. @Override
  203. public void run() {
  204. RNFetchBlobFS.writeFile(path, encoding, data, append, promise);
  205. }
  206. });
  207. }
  208. @ReactMethod
  209. public void lstat(String path, Callback callback) {
  210. RNFetchBlobFS.lstat(path, callback);
  211. }
  212. @ReactMethod
  213. public void stat(String path, Callback callback) {
  214. RNFetchBlobFS.stat(path, callback);
  215. }
  216. @ReactMethod
  217. public void scanFile(final ReadableArray pairs, final Callback callback) {
  218. final ReactApplicationContext ctx = this.getReactApplicationContext();
  219. threadPool.execute(new Runnable() {
  220. @Override
  221. public void run() {
  222. int size = pairs.size();
  223. String [] p = new String[size];
  224. String [] m = new String[size];
  225. for(int i=0;i<size;i++) {
  226. ReadableMap pair = pairs.getMap(i);
  227. if(pair.hasKey("path")) {
  228. p[i] = pair.getString("path");
  229. if(pair.hasKey("mime"))
  230. m[i] = pair.getString("mime");
  231. else
  232. m[i] = null;
  233. }
  234. }
  235. new RNFetchBlobFS(ctx).scanFile(p, m, callback);
  236. }
  237. });
  238. }
  239. @ReactMethod
  240. public void hash(final String path, final String algorithm, final Promise promise) {
  241. threadPool.execute(new Runnable() {
  242. @Override
  243. public void run() {
  244. RNFetchBlobFS.hash(path, algorithm, promise);
  245. }
  246. });
  247. }
  248. /**
  249. * @param path Stream file path
  250. * @param encoding Stream encoding, should be one of `base64`, `ascii`, and `utf8`
  251. * @param bufferSize Stream buffer size, default to 4096 or 4095(base64).
  252. */
  253. @ReactMethod
  254. public void readStream(final String path, final String encoding, final int bufferSize, final int tick, final String streamId) {
  255. final ReactApplicationContext ctx = this.getReactApplicationContext();
  256. fsThreadPool.execute(new Runnable() {
  257. @Override
  258. public void run() {
  259. RNFetchBlobFS fs = new RNFetchBlobFS(ctx);
  260. fs.readStream(path, encoding, bufferSize, tick, streamId);
  261. }
  262. });
  263. }
  264. @ReactMethod
  265. public void cancelRequest(String taskId, Callback callback) {
  266. try {
  267. RNFetchBlobReq.cancelTask(taskId);
  268. callback.invoke(null, taskId);
  269. } catch (Exception ex) {
  270. callback.invoke(ex.getLocalizedMessage(), null);
  271. }
  272. }
  273. @ReactMethod
  274. public void slice(String src, String dest, int start, int end, Promise promise) {
  275. RNFetchBlobFS.slice(src, dest, start, end, "", promise);
  276. }
  277. @ReactMethod
  278. public void enableProgressReport(String taskId, int interval, int count) {
  279. RNFetchBlobProgressConfig config = new RNFetchBlobProgressConfig(true, interval, count, RNFetchBlobProgressConfig.ReportType.Download);
  280. RNFetchBlobReq.progressReport.put(taskId, config);
  281. }
  282. @ReactMethod
  283. public void df(final Callback callback) {
  284. fsThreadPool.execute(new Runnable() {
  285. @Override
  286. public void run() {
  287. RNFetchBlobFS.df(callback);
  288. }
  289. });
  290. }
  291. @ReactMethod
  292. public void enableUploadProgressReport(String taskId, int interval, int count) {
  293. RNFetchBlobProgressConfig config = new RNFetchBlobProgressConfig(true, interval, count, RNFetchBlobProgressConfig.ReportType.Upload);
  294. RNFetchBlobReq.uploadProgressReport.put(taskId, config);
  295. }
  296. @ReactMethod
  297. public void fetchBlob(ReadableMap options, String taskId, String method, String url, ReadableMap headers, String body, final Callback callback) {
  298. new RNFetchBlobReq(options, taskId, method, url, headers, body, null, mClient, callback).run();
  299. }
  300. @ReactMethod
  301. public void fetchBlobForm(ReadableMap options, String taskId, String method, String url, ReadableMap headers, ReadableArray body, final Callback callback) {
  302. new RNFetchBlobReq(options, taskId, method, url, headers, null, body, mClient, callback).run();
  303. }
  304. @ReactMethod
  305. public void getContentIntent(String mime, Promise promise) {
  306. Intent i = new Intent(Intent.ACTION_GET_CONTENT);
  307. if(mime != null)
  308. i.setType(mime);
  309. else
  310. i.setType("*/*");
  311. promiseTable.put(GET_CONTENT_INTENT, promise);
  312. this.getReactApplicationContext().startActivityForResult(i, GET_CONTENT_INTENT, null);
  313. }
  314. @ReactMethod
  315. public void addCompleteDownload (ReadableMap config, Promise promise) {
  316. DownloadManager dm = (DownloadManager) RCTContext.getSystemService(RCTContext.DOWNLOAD_SERVICE);
  317. if (config == null || !config.hasKey("path"))
  318. {
  319. promise.reject("EINVAL", "RNFetchblob.addCompleteDownload config or path missing.");
  320. return;
  321. }
  322. String path = RNFetchBlobFS.normalizePath(config.getString("path"));
  323. if(path == null) {
  324. promise.reject("EINVAL", "RNFetchblob.addCompleteDownload can not resolve URI:" + config.getString("path"));
  325. return;
  326. }
  327. try {
  328. WritableMap stat = RNFetchBlobFS.statFile(path);
  329. dm.addCompletedDownload(
  330. config.hasKey("title") ? config.getString("title") : "",
  331. config.hasKey("description") ? config.getString("description") : "",
  332. true,
  333. config.hasKey("mime") ? config.getString("mime") : null,
  334. path,
  335. Long.valueOf(stat.getString("size")),
  336. config.hasKey("showNotification") && config.getBoolean("showNotification")
  337. );
  338. promise.resolve(null);
  339. }
  340. catch(Exception ex) {
  341. promise.reject("EUNSPECIFIED", ex.getLocalizedMessage());
  342. }
  343. }
  344. @ReactMethod
  345. public void getSDCardDir(Promise promise) {
  346. RNFetchBlobFS.getSDCardDir(promise);
  347. }
  348. @ReactMethod
  349. public void getSDCardApplicationDir(Promise promise) {
  350. RNFetchBlobFS.getSDCardApplicationDir(this.getReactApplicationContext(), promise);
  351. }
  352. }