androidjava-native-interfacemediastorescoped-storage

How to WRITE to a file from native side (C/C++) on Android 13 Device


I have a complex image processing application that records images/videos using native code from C++ side, and would like to write to DCIM folder.

I've made this work with Scoped Storage on Android 10 and 11 with the code below:

1.Insert an entry in media store

Uri placeholderUri = null;
ContentResolver contentResolver = context.getContentResolver();
ContentValues contentValues = new ContentValues();        
contentValues.put(MediaStore.Video.Media.DISPLAY_NAME, "TEST_VIDEO");
contentValues.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
contentValues.put(MediaStore.Video.Media.RELATIVE_PATH, "DCIM/" + "APP_NAME");
try {
   placeholderUri = contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);
} catch (RuntimeException e) {
   e.printStackTrace();
}

2.Create ParcelFileDescriptor from the content

ParcelFileDescriptor fd = null;
try {
   fd = context.getContentResolver().openFileDescriptor(placeholderUri, "rw");
   Log.d(TAG, "new fd: " + fd.getFd());
} catch (FileNotFoundException e) {
   throw new RuntimeException(e);
}

3. Get the full path from open resources the app should have access to by concatenating the fd to "/proc/self/fd/"

return "/proc/self/fd/" + fd.getFd();

This approach now does not work on Android 13 devices, as I don't seem to have write access to "/proc/self/fd" I could not find any information as to why this wouldn't work on Android 13 but it would for Android 10 or 11.

Is there any way to make this work with MediaStore without using StorageAccessFramework? Idea of relying on users to select the correct folders would be the last option for my clientele, so I would like to rely on MediaStore as much as possible.

Thank you!


Solution

  • DCIM seems to be one of few places we have read/write access granted the file is attributed to the app.The initial code I provided in my question is a way to create a file attributed to the app so we can do a write access from the native side.

    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + "/" + albumName + "/" + fileName + ".mp4"
    

    Above code works to get the absolute path which the app will have rw access to.