0

I'm currently working on an app where u can edit some metatags of an image. The app is build using flutter. To edit the metadata I'm using Kotlin. Currently I can read metadata from a given image path like /storage/emulated/0/Download/05-03.jpg and path trough the data to my flutter application using a MethodChannel. But the problem is with the writing of the metadata. When I'm trying it then I get this error: E/DartMessenger( 3532): java.io.FileNotFoundException: /storage/emulated/0/Download/05-03.jpg: open failed: EACCES (Permission denied).

My targeted SDK version is 32.

My Manifest has the following permissions:

<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

This is the code for asking for permission in the flutter app:

Future<void> requestPermission() async {
    final storageStatus = await Permission.storage.request();

    if (storageStatus == PermissionStatus.granted) {
      setState(() {
        _permissionsGranted = true;
      });
      _loadAlbums();
    } else {
      print('Permission to access photos or storage not granted');
    }
  }

And this is the code which should write the metadata with Kotlin:

val arguments = call.arguments() as Map<String, Any>?
val path = arguments?.get("imagePath") as String
val xmpstring = arguments?.get("XMPString") as String

val exif = ExifInterface(path)
exif.setAttribute(ExifInterface.TAG_XMP, xmpstring)
exif.saveAttributes()
result.success(null)

Here is the full error response:

[ +685 ms] E/DartMessenger( 3532): Uncaught exception in binary message listener
[   +1 ms] E/DartMessenger( 3532): java.io.FileNotFoundException: /storage/emulated/0/Download/05-03.jpg: open failed: EACCES (Permission
denied)
[   +2 ms] E/DartMessenger( 3532):      at libcore.io.IoBridge.open(IoBridge.java:574)
[   +1 ms] E/DartMessenger( 3532):      at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
[   +1 ms] E/DartMessenger( 3532):      at java.io.FileOutputStream.<init>(FileOutputStream.java:125)
[   +1 ms] E/DartMessenger( 3532):      at android.media.ExifInterface.saveAttributes(ExifInterface.java:2163)
[   +1 ms] E/DartMessenger( 3532):      at
com.example.gallery_organiser_flutter.MainActivity.configureFlutterEngine$lambda-0(MainActivity.kt:57)
[   +1 ms] E/DartMessenger( 3532):      at com.example.gallery_organiser_flutter.MainActivity.$r8$lambda$1bRFzOsVd3GTISkOzpe0jh_X5RA(Unknown
Source:0)
[   +1 ms] E/DartMessenger( 3532):      at com.example.gallery_organiser_flutter.MainActivity$$ExternalSyntheticLambda0.onMethodCall(Unknown
Source:2)
[   +1 ms] E/DartMessenger( 3532):      at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:258)
[   +2 ms] E/DartMessenger( 3532):      at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
[   +3 ms] E/DartMessenger( 3532):      at
io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMesseng
er.java:322)
[   +2 ms] E/DartMessenger( 3532):      at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
[   +1 ms] E/DartMessenger( 3532):      at android.os.Handler.handleCallback(Handler.java:942)
[   +1 ms] E/DartMessenger( 3532):      at android.os.Handler.dispatchMessage(Handler.java:99)
[   +1 ms] E/DartMessenger( 3532):      at android.os.Looper.loopOnce(Looper.java:201)
[   +1 ms] E/DartMessenger( 3532):      at android.os.Looper.loop(Looper.java:288)
[   +1 ms] E/DartMessenger( 3532):      at android.app.ActivityThread.main(ActivityThread.java:7898)
[   +1 ms] E/DartMessenger( 3532):      at java.lang.reflect.Method.invoke(Native Method)
[   +1 ms] E/DartMessenger( 3532):      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
[   +1 ms] E/DartMessenger( 3532):      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
[   +1 ms] E/DartMessenger( 3532): Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
[   +1 ms] E/DartMessenger( 3532):      at libcore.io.Linux.open(Native Method)
[   +2 ms] E/DartMessenger( 3532):      at libcore.io.ForwardingOs.open(ForwardingOs.java:563)
[   +1 ms] E/DartMessenger( 3532):      at libcore.io.BlockGuardOs.open(BlockGuardOs.java:274)
[   +1 ms] E/DartMessenger( 3532):      at libcore.io.ForwardingOs.open(ForwardingOs.java:563)
[   +1 ms] E/DartMessenger( 3532):      at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7784)
[   +1 ms] E/DartMessenger( 3532):      at libcore.io.IoBridge.open(IoBridge.java:560)
[   +1 ms] E/DartMessenger( 3532):      ... 18 more
[ +185 ms] E/flutter ( 3532): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No
implementation found for method setRatingXMP on channel com.broump.gallery_organiser_flutter/exif_interface)
[   +1 ms] E/flutter ( 3532): #0      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:313:7)
[   +1 ms] E/flutter ( 3532): <asynchronous suspension>
[   +2 ms] E/flutter ( 3532): #1      ExifInterfaceChannel.setRating
(package:gallery_organiser_flutter/providers/exif_provider.dart:54:7)
[   +1 ms] E/flutter ( 3532): <asynchronous suspension>
[   +1 ms] E/flutter ( 3532): #2      _RatingDialogState._writeRating
(package:gallery_organiser_flutter/components/rating_modal.dart:31:5)
[   +1 ms] E/flutter ( 3532): <asynchronous suspension>
[   +1 ms] E/flutter ( 3532): 

So how could I solve this error?

Broump
  • 303
  • 3
  • 9

1 Answers1

0

To access the Downloads folder after Android 10+ you need the permission READ_EXTERNAL_STORAGE. Here is a snippet or extracting all downloads files for both before and after Android 10 devices:

@RequiresApi(Build.VERSION_CODES.R)
fun hasAllFilesPermission() = Environment.isExternalStorageManager()

fun getDownloadsFiles(context: Context): Array<String> {
            if (Build.VERSION.SDK_INT >= 30) {
                if (hasAllFilesPermission()) {
                    return File(downloadsPath).list() ?: emptyArray()
                } else {
                    requestFilePermission(context)

                    val filesArray = File(downloadsPath).list()
                    if (filesArray != null) {
                        return filesArray
                    } else {
                        getDownloadsFiles(context)
                    }
                }
            } else {
                return File(downloadsPath).list() ?: emptyArray()
            }
            return emptyArray()
}
@RequiresApi(Build.VERSION_CODES.R)
fun requestFilePermission(context: Context) {
            context.startActivity(
                Intent(
                    Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION,
                )
            )
}
MercifulSory
  • 337
  • 1
  • 14
  • Excuse my negligent use of Tabs and spaces.. :) – MercifulSory Mar 05 '23 at 18:24
  • When I Log `Log.i("Permission", "Permission granted: ${ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED}") Log.i("Permission", "Permission granted: ${ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED}")` i'll get his response: `[ +15 ms] I/Permission( 6639): Permission granted: true [ ] I/Permission( 6639): Permission granted: true`. So I think i have the right permission, but it still wont work. – Broump Mar 11 '23 at 13:59