77
77
import java .io .OutputStream ;
78
78
import java .io .IOException ;
79
79
80
+ import android .os .Build ;
81
+ import android .os .Environment ;
82
+ import android .Manifest ;
83
+ import android .content .Context ;
84
+ import android .content .Intent ;
85
+ import android .content .pm .PackageInfo ;
86
+ import android .content .pm .PackageManager ;
87
+ import android .net .Uri ;
88
+ import android .provider .Settings ;
89
+
90
+ import androidx .core .content .ContextCompat ;
91
+
92
+
80
93
81
94
public class System extends CordovaPlugin {
82
95
@@ -240,6 +253,65 @@ public void run() {
240
253
241
254
callbackContext .success (arch );
242
255
return true ;
256
+
257
+ case "requestStorageManager" :
258
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .R ) {
259
+ try {
260
+ Intent intent = new Intent (Settings .ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION );
261
+ intent .setData (Uri .parse ("package:" + context .getPackageName ()));
262
+ intent .addFlags (Intent .FLAG_ACTIVITY_NEW_TASK );
263
+ context .startActivity (intent );
264
+ callbackContext .success ("true" );
265
+ } catch (Exception e ) {
266
+ // Fallback to general settings if specific one fails
267
+ Intent intent = new Intent (Settings .ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION );
268
+ intent .addFlags (Intent .FLAG_ACTIVITY_NEW_TASK );
269
+ context .startActivity (intent );
270
+ callbackContext .success ("true" );
271
+ }
272
+ } else {
273
+ callbackContext .success ("false" ); // Not needed on Android < 11
274
+ }
275
+ return true ;
276
+
277
+
278
+ case "hasGrantedStorageManager" :
279
+ boolean granted ;
280
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .R ) {
281
+ granted = Environment .isExternalStorageManager ();
282
+ } else {
283
+ // Fallback for Android 10 and below
284
+ granted = ContextCompat .checkSelfPermission (
285
+ context ,
286
+ Manifest .permission .READ_EXTERNAL_STORAGE
287
+ ) == PackageManager .PERMISSION_GRANTED ;
288
+ }
289
+ callbackContext .success (String .valueOf (granted ));
290
+ return true ;
291
+
292
+ case "isManageExternalStorageDeclared" :
293
+ PackageManager pm = context .getPackageManager ();
294
+ try {
295
+ PackageInfo info = pm .getPackageInfo (context .getPackageName (), PackageManager .GET_PERMISSIONS );
296
+ String [] permissions = info .requestedPermissions ;
297
+ String isDeclared = "false" ;
298
+
299
+ if (permissions != null ) {
300
+ for (String perm : permissions ) {
301
+ if (perm .equals ("android.permission.MANAGE_EXTERNAL_STORAGE" )) {
302
+ isDeclared = "true" ;
303
+ break ;
304
+ }
305
+ }
306
+ }
307
+ callbackContext .success (isDeclared );
308
+
309
+ } catch (PackageManager .NameNotFoundException e ) {
310
+ e .printStackTrace ();
311
+ callbackContext .error (e .toString ());
312
+ }
313
+
314
+ return true ;
243
315
case "mkdirs" :
244
316
File file = new File (args .getString (0 ));
245
317
if (file .mkdirs ()) {
@@ -260,106 +332,104 @@ public void run() {
260
332
public void run () {
261
333
switch (action ) {
262
334
case "copyToUri" :
263
- try {
264
- //srcUri is a file
265
- Uri srcUri = Uri .parse (args .getString (0 ));
266
-
267
- //destUri is a directory
268
- Uri destUri = Uri .parse (args .getString (1 ));
269
-
270
- //create a file named this into the dest Directory and copy the srcUri into it
271
- String fileName = args .getString (2 );
272
-
273
- InputStream in = null ;
274
- OutputStream out = null ;
275
- try {
276
- // Open input stream from the source URI
277
- if ("file" .equalsIgnoreCase (srcUri .getScheme ())) {
278
- File file = new File (srcUri .getPath ());
279
- in = new FileInputStream (file );
280
- } else {
281
- in = context .getContentResolver ().openInputStream (srcUri );
282
- }
283
-
284
- // Create the destination file using DocumentFile for better URI handling
285
- DocumentFile destFile = null ;
286
-
287
- if ("file" .equalsIgnoreCase (destUri .getScheme ())) {
288
- // Handle file:// scheme using DocumentFile
289
- File destDir = new File (destUri .getPath ());
290
- if (!destDir .exists ()) {
291
- destDir .mkdirs (); // Create directory if it doesn't exist
292
- }
293
- DocumentFile destDocDir = DocumentFile .fromFile (destDir );
294
-
295
- // Check if file already exists and delete it
296
- DocumentFile existingFile = destDocDir .findFile (fileName );
297
- if (existingFile != null && existingFile .exists ()) {
298
- existingFile .delete ();
299
- }
300
-
301
- // Create new file
302
- String mimeType = getMimeTypeFromExtension (fileName );
303
- destFile = destDocDir .createFile (mimeType , fileName );
304
- } else {
305
- // Handle content:// scheme using DocumentFile
306
- DocumentFile destDocDir = DocumentFile .fromTreeUri (context , destUri );
307
-
308
- if (destDocDir == null || !destDocDir .exists () || !destDocDir .isDirectory ()) {
309
- callbackContext .error ("Destination directory does not exist or is not accessible" );
310
- return ;
311
- }
312
-
313
- // Check if file already exists and delete it
314
- DocumentFile existingFile = destDocDir .findFile (fileName );
315
- if (existingFile != null && existingFile .exists ()) {
316
- existingFile .delete ();
317
- }
318
-
319
- // Create new file
320
- String mimeType = getMimeTypeFromExtension (fileName );
321
- destFile = destDocDir .createFile (mimeType , fileName );
322
- }
323
-
324
- if (destFile == null || !destFile .exists ()) {
325
- callbackContext .error ("Failed to create destination file" );
326
- return ;
327
- }
328
-
329
- // Open output stream to the created file
330
- out = context .getContentResolver ().openOutputStream (destFile .getUri ());
331
-
332
- if (in == null || out == null ) {
333
- callbackContext .error ("uri streams are null" );
334
- return ;
335
- }
336
-
337
- // Copy stream
338
- byte [] buffer = new byte [8192 ];
339
- int len ;
340
- while ((len = in .read (buffer )) > 0 ) {
341
- out .write (buffer , 0 , len );
342
- }
343
-
344
- out .flush ();
345
- callbackContext .success ();
346
- } catch (IOException e ) {
347
- e .printStackTrace ();
348
- callbackContext .error (e .toString ());
349
- } finally {
350
- try {
351
- if (in != null ) in .close ();
352
- if (out != null ) out .close ();
353
- } catch (IOException e ) {
354
- e .printStackTrace ();
355
- callbackContext .error (e .toString ());
356
- }
357
- }
358
- } catch (Exception e ) {
359
- e .printStackTrace ();
360
- callbackContext .error (e .toString ());
361
- }
362
- break ;
335
+ try {
336
+ //srcUri is a file
337
+ Uri srcUri = Uri .parse (args .getString (0 ));
338
+
339
+ //destUri is a directory
340
+ Uri destUri = Uri .parse (args .getString (1 ));
341
+
342
+ //create a file named this into the dest Directory and copy the srcUri into it
343
+ String fileName = args .getString (2 );
344
+
345
+ InputStream in = null ;
346
+ OutputStream out = null ;
347
+ try {
348
+ // Open input stream from the source URI
349
+ if ("file" .equalsIgnoreCase (srcUri .getScheme ())) {
350
+ File file = new File (srcUri .getPath ()); in = new FileInputStream (file );
351
+ } else { in = context .getContentResolver ().openInputStream (srcUri );
352
+ }
353
+
354
+ // Create the destination file using DocumentFile for better URI handling
355
+ DocumentFile destFile = null ;
356
+
357
+ if ("file" .equalsIgnoreCase (destUri .getScheme ())) {
358
+ // Handle file:// scheme using DocumentFile
359
+ File destDir = new File (destUri .getPath ());
360
+ if (!destDir .exists ()) {
361
+ destDir .mkdirs (); // Create directory if it doesn't exist
362
+ }
363
+ DocumentFile destDocDir = DocumentFile .fromFile (destDir );
364
+
365
+ // Check if file already exists and delete it
366
+ DocumentFile existingFile = destDocDir .findFile (fileName );
367
+ if (existingFile != null && existingFile .exists ()) {
368
+ existingFile .delete ();
369
+ }
370
+
371
+ // Create new file
372
+ String mimeType = getMimeTypeFromExtension (fileName );
373
+ destFile = destDocDir .createFile (mimeType , fileName );
374
+ } else {
375
+ // Handle content:// scheme using DocumentFile
376
+ DocumentFile destDocDir = DocumentFile .fromTreeUri (context , destUri );
377
+
378
+ if (destDocDir == null || !destDocDir .exists () || !destDocDir .isDirectory ()) {
379
+ callbackContext .error ("Destination directory does not exist or is not accessible" );
380
+ return ;
381
+ }
382
+
383
+ // Check if file already exists and delete it
384
+ DocumentFile existingFile = destDocDir .findFile (fileName );
385
+ if (existingFile != null && existingFile .exists ()) {
386
+ existingFile .delete ();
387
+ }
388
+
389
+ // Create new file
390
+ String mimeType = getMimeTypeFromExtension (fileName );
391
+ destFile = destDocDir .createFile (mimeType , fileName );
392
+ }
393
+
394
+ if (destFile == null || !destFile .exists ()) {
395
+ callbackContext .error ("Failed to create destination file" );
396
+ return ;
397
+ }
398
+
399
+ // Open output stream to the created file
400
+ out = context .getContentResolver ().openOutputStream (destFile .getUri ());
401
+
402
+ if ( in == null || out == null ) {
403
+ callbackContext .error ("uri streams are null" );
404
+ return ;
405
+ }
406
+
407
+ // Copy stream
408
+ byte [] buffer = new byte [8192 ];
409
+ int len ;
410
+ while ((len = in .read (buffer )) > 0 ) {
411
+ out .write (buffer , 0 , len );
412
+ }
413
+
414
+ out .flush ();
415
+ callbackContext .success ();
416
+ } catch (IOException e ) {
417
+ e .printStackTrace ();
418
+ callbackContext .error (e .toString ());
419
+ } finally {
420
+ try {
421
+ if ( in != null ) in .close ();
422
+ if (out != null ) out .close ();
423
+ } catch (IOException e ) {
424
+ e .printStackTrace ();
425
+ callbackContext .error (e .toString ());
426
+ }
427
+ }
428
+ } catch (Exception e ) {
429
+ e .printStackTrace ();
430
+ callbackContext .error (e .toString ());
431
+ }
432
+ break ;
363
433
case "get-webkit-info" :
364
434
getWebkitInfo (callbackContext );
365
435
break ;
@@ -445,16 +515,16 @@ public void run() {
445
515
}
446
516
447
517
// Helper method to determine MIME type using Android's built-in MimeTypeMap
448
- private String getMimeTypeFromExtension (String fileName ) {
449
- String extension = "" ;
450
- int lastDotIndex = fileName .lastIndexOf ('.' );
451
- if (lastDotIndex > 0 && lastDotIndex < fileName .length () - 1 ) {
452
- extension = fileName .substring (lastDotIndex + 1 ).toLowerCase ();
518
+ private String getMimeTypeFromExtension (String fileName ) {
519
+ String extension = "" ;
520
+ int lastDotIndex = fileName .lastIndexOf ('.' );
521
+ if (lastDotIndex > 0 && lastDotIndex < fileName .length () - 1 ) {
522
+ extension = fileName .substring (lastDotIndex + 1 ).toLowerCase ();
523
+ }
524
+
525
+ String mimeType = MimeTypeMap .getSingleton ().getMimeTypeFromExtension (extension );
526
+ return mimeType != null ? mimeType : "application/octet-stream" ;
453
527
}
454
-
455
- String mimeType = MimeTypeMap .getSingleton ().getMimeTypeFromExtension (extension );
456
- return mimeType != null ? mimeType : "application/octet-stream" ;
457
- }
458
528
459
529
private void getConfiguration (CallbackContext callback ) {
460
530
try {
0 commit comments