Android 12 - Storage Access Framework / Scoped Storage not working anymore

Viewed 2698

Android 12 recently released on some phones and some users started to complain about storage access: they can't grant access to a specific folder anymore to the app (for example, the "Download" folder).

The message indicates: "Can't use this folder. To protect your privacy, choose another folder".

The issue is easy to reproduce and I spent some time looking for a fix, but I could not find an easy one.

Image of the issue

It seems that the only workarounds are to ask for full storage access (but it's not what I want to do, it's bad) or to ask the user to create a new folder, which would be an UX absolute pain.

What I don't understand is: did Google just - without any documentation - deprecated SAF on Android 12? Is that a bug or a feature? I'm really puzzled there. Android 11 was already such a pain to migrate on, and now I'm afraid that 12 will become even more painful.

Here is the code, but nothing fancy:

    /*
    * Requests Scoped Storage access authorization
    */
    @RequiresApi(Build.VERSION_CODES.Q)
    @JvmStatic
    fun requestScopedStorageAccess(activity: Activity, requestCode: Int) {
        val storageManager = activity.getSystemService(Context.STORAGE_SERVICE) as StorageManager
        val intent = storageManager.primaryStorageVolume.createOpenDocumentTreeIntent()
        activity.startActivityForResult(intent, requestCode)
    }

I think that it's worth noting that everything works perfectly on Android 10 & 11, so the issue really is about Android 12.

1 Answers
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
            StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);

            Intent intent = sm.getPrimaryStorageVolume().createOpenDocumentTreeIntent();

            String startSubDir = "Android%2Fdata";

            Uri uri = intent.getParcelableExtra("android.provider.extra.INITIAL_URI");

            String scheme = uri.toString();

            Log.d(TAG, "INITIAL_URI scheme: " + scheme);

            scheme = scheme.replace("/root/", "/document/");

            scheme += "%3A" + startSubDir;
            Log.d(TAG, "INITIAL_URI scheme: " + scheme);

            uri = Uri.parse(scheme);

            intent.putExtra("android.provider.extra.INITIAL_URI", uri);

            Log.d(TAG, "uri: " + uri.toString());

            ((Activity) getActivity()).startActivityForResult(intent, REQUEST_ACTION_OPEN_DOCUMENT_TREE);

            return;
        }
Related