Can not access OTG USB Key after just after Granting ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION

66 Views Asked by At

My phone is a Samsung A32 5G ( SM-A326B/DS). Android 12, native ROM, SDK 31.

I need to read files from OTG USB dongle from 2 apps :

  • My app which is an installer. It install some APK and restore some data external SD card or OTG USB Device.
  • Termux app, dowloaded from github and modified to request the right.

The manifest includes :

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

To request in java code I tried 2 methods :

First method :

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
          if (!Environment.isExternalStorageManager()) {
CTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION");
                Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
                String name = getPackageName();
                Uri uri = Uri.fromParts("package", name, null);
                intent.setData(uri);
                startActivity(intent);
            }
        }

Second method :

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    if (!getPackageManager().canRequestPackageInstalls()) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Uri.parse("package:" + BuildConfig.APPLICATION_ID));
        startActivityForResult(intent, 501);
    }
}

In two apps, the problem is that it the authorization does not take effect inside the Activity which asked the authorization. Even if I end my Activity with finish() and start again my App, I have not the access. But if I kill my app with task manager and start the app, the I get the right. But when I kill my app with the task manage and start it again, then I access the USB dongle.

In both app, to access the ISB Key I use linux commands.

  • With mount command I check that the USB Dongle is seen by Android.
  • With USBPATH=$(grep -E "^[^ ]+ /mnt/media_rw/[A-Z0-9]{4}-[A-Z0-9]{4} " /proc/mounts | cut -d' ' -f2) I get the path of the dongle
  • With ls $USBPATH I see that I have not the right, even after MANAGE_EXTERNAL_STORAGE has been granted, because ls returns "permission denied".
3

There are 3 best solutions below

3
blackapps On

You have no read access to /mnt/media_rw.

All files access has no effect on it.

2
Coilhac On

I found a solution. It is probably a dirty solution, but it works. The problem was to terminate my Activity just after the user manually grant the right MANAGE_EXTERNAL_STORAGE, knowing that :

  • even after the user grant the permission, my Activity did not have the right (1)
  • more over, if I end my Activity by finish() and start the app again, the new activity have not the right. I do not find explanation for that , It look like the new activity keep some context of the previous one.

My solution is to kill my pid. I had implemented in my app the ability to launch bash commands. So I kill the pid of my Activity after launching new activity:

static String HaraKiri = "sleep 2;PID=$(ps -ef | grep     'eu.eduphone.install' | grep -v  'grep' | grep  -v 'eu.eduphone.install.' |awk '{ print $2 }');echo \"PID=$PID\";kill -15 \"$PID\"";
    ...
private void Restart() {
    Intent intent = new Intent();
    String name=getActivity().getPackageName();
    Log.d("Thierry", "Restartn Name = "+name);
    intent.setComponent(new ComponentName(name, name+".MainActivity"));
    startActivity(intent);
    ShellExec(HaraKiri);
}

That works, the new activity can read the USB Dongle.

(1) About the reason what we must restart Activity to get the right after the user grant it :

In another discussion, https://github.com/termux/termux-app/issues/71#issuecomment-1869222653 , https://github.com/agnostic-apollo says that :

  • Unreliable/Removable volumes like USB OTG devices that are only available on the /mnt/media_rw paths with their own filesystem (vfat/exfat) are assigned the root (0) owner and external_storage (1077) group.
  • If an app has been granted the MANAGE_EXTERNAL_STORAGE permission, then the external_storage (1077) group is added to list of groups that are assigned to the app process when its forked from zygote, allowing it to access unreliable/removable volumes with the
    external_storage (1077) group.

My running activity is not in the group 1077 because it has been forked before this group was assigned to the app.

4
Martin Zeitler On

It's not required to kill the app, when waiting until the user pressed the back button.

@RequiresApi(api = Build.VERSION_CODES.R)
public void gotoExternalStorageSettings() {
    Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
    intent.setData(Uri.fromParts("package", requireContext().getPackageName(), null));
    this.startActivityAndWait.launch(intent);
}

ActivityResultLauncher<Intent> startActivityAndWait = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(), (ActivityResult result) -> {
            if (Environment.isExternalStorageManager()) {
                // permission was granted
                // continue in here ...
            }
        });

The culprit otherwise is indeed, that the app does not know when.
There isn't any result returned, but one does not need any result ...