Getexternalstoragepublicdirectory Deprecated in Android Q

getExternalStoragePublicDirectory deprecated in Android Q

Based on the docs, use DCIM/... for the RELATIVE_PATH, where ... is whatever your custom subdirectory would be. So, you would wind up with something like this:

      val resolver = context.contentResolver
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "CuteKitten001")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/PerracoLabs")
}

val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)

resolver.openOutputStream(uri).use {
// TODO something with the stream
}

Note that since RELATIVE_PATH is new to API Level 29, you would need to use this approach on newer devices and use getExternalStoragePublicDirectory() on older ones.

Environment.getExternalStorageDirectory() deprecated in API level 29 java

Use getExternalFilesDir(), getExternalCacheDir(), or getExternalMediaDirs() (methods on Context) instead of Environment.getExternalStorageDirectory().

Or, modify mPhotoEditor to be able to work with a Uri, then:

  • Use ACTION_CREATE_DOCUMENT to get a Uri to a location of the user's choosing, or

  • Use MediaStore, ContentResolver, and insert() to get a Uri for a particular type of media (e.g., an image) — see this sample app that demonstrates doing this for downloading MP4 videos from a Web site

Also, note that your Uri.fromFile with ACTION_MEDIA_SCANNER_SCAN_FILE should be crashing on Android 7.0+ with a FileUriExposedException. On Android Q, only the MediaStore/insert() option will get your content indexed by the MediaStore quickly.

Note that you can opt out of these "scoped storage" changes on Android 10 and 11, if your targetSdkVersion is below 30, using android:requestLegacyExternalStorage="true" in the <application> element of the manifest. This is not a long-term solution, as your targetSdkVersion will need to be 30 or higher sometime in 2021 if you are distributing your app through the Play Store (and perhaps elsewhere).

How to read or write file as getExternalStorageDirectory is deprecated in API 29?

From the docs you can see:

getExternalStoragePublicDirectory(String type)

This method was deprecated in API level 29. To improve user privacy, direct access to shared/external storage devices is deprecated. When
an app targets Build.VERSION_CODES.Q, the path returned from this
method is no longer directly accessible to apps. Apps can continue to
access content stored on shared/external storage by migrating to
alternatives such as Context#getExternalFilesDir(String),
MediaStore, or Intent#ACTION_OPEN_DOCUMENT.

Pass nothing as parameter to this function to get your directory as a File object :

context.getExternalFilesDir();

Here "Context" is an object which is obtained by this.getContext();

this is the current object of the Activity. Do check the scope carefully while using it.

Important

To access the Internal storage, Manifest.permission.WRITE_EXTERNAL_STORAGE and/or Manifest.permission.READ_EXTERNAL_STORAGE are required in the file AndroidManifest.xml.

Optional information:

  1. Usually the internal storage has the path
    /sdcard/ on Android devices. It's not a real path but a symlink.

  2. It's confusing but "external sdcard" in Android acutally means the Internal device storage and not the external ejectable out-of-the-device memory card storage.
    Also note that the real external sdcard cannot be fully access

  3. Activity class extends the Context class That's why we can get the context from it.



Related Topics



Leave a reply



Submit