2

the app i'm working on uses a File as a target for photo capturing. this is executed externally by user selecting a camera-app using Intent(ACTION_IMAGE_CAPTURE). since upgrading build and target-sdk to 29, there have been a series of issues starting with the restriction on freely accessing files on external storage. the first change was to use one of either the application's private-cache directory, eg:

File.createTempFile("tempImage", ".jpg", context.cacheDir)

or the applications private external-storage directory:

File.createTempFile("tempImage", ".jpg", context.getExternalFilesDir(Environment.DIRECTORY_PICTURES))

in combination with FileProvider access in file_paths.xml, eg:

<paths>
    <external-path name="images" path="Pictures/" /><!-- prior to SDK-29, use public external storage -->
    <external-files-path name="externalImages" path="Pictures/" />
    <files-path name="internalImages" path="internalImages/"/>
    <cache-path name="cache" path="/" />
</paths>

these work well now after being properly configured, however implementing "Save to Gallery" functionality, eg: notifying other apps of new images is no longer working on devices running Android-10

// use FileProvider to make this new photo publicly accessible 
val shareableUri = FileProvider.getUriForFile(context, FILE_PROVIDER_AUTHORITY, newImage)
context.sendBroadcast(
  Intent(ACTION_MEDIA_SCANNER_SCAN_FILE).apply { data = uris.externalUri }
)

this approach should work but doesn't, regardless of where the original image is saved (private-app-dir, cache-dir, external-private)

MediaScannerConnection.scanFile(context, arrayOf(newImage.absolutePath), arrayOf("image/jpeg")) { path: String, uri: Uri? ->
  if (uri == null) {
    throw IllegalStateException("media scan failed...")
  } else {
    // successful
  }
}

Are there are new restrictions in Android's SDK-29 which necessitate a change in MediaScanning, specifically related to the way in which a (potentially) private image file is scanned? I noticed that MediaScanner methods mostly expect a String path instead of a URI, so this leads me to think that the new restrictions won't apply to it since its a system component.

xst
  • 2,536
  • 5
  • 29
  • 41
  • I'm wondering what you ended up doing because I'm working to support the new scoped storage and yeah I have tried this and I can confirm that the MediaScanning is not working as before. – Hossam Hassan Apr 22 '20 at 07:28

1 Answers1

2

Apps targeting Android 10 (API level 29) and higher are given scoped access into an external storage device, or scoped storage, by default.

so you need to make it compatible with scopedStorage but you can use this temporary approach for now mentioned in Google Android Developers guide.

Before your app is fully compatible with scoped storage, you can temporarily opt out based on your app's target SDK level or the requestLegacyExternalStorage manifest attribute:

<manifest ... >
  <!-- This attribute is "false" by default on apps targeting
       Android 10 or higher. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

visit this link for more info: https://developer.android.com/training/data-storage/files/external-scoped

Maryam Mirzaie
  • 536
  • 6
  • 24
  • 1
    i didn't see any direct mention of Media-Scanning in any scoped-storage or Android-10 docs. that's the main problem now, the other i was able to resolve using `FileProvider` and so i didn't need to use `android:requestLegacyExternalStorage="true"` – xst Sep 17 '19 at 17:46
  • Be aware that `requestLegacyExternalStorage` will have impact when publishing an app on the store and will need to be justified on Google Play Store. @xst can you post your solution as an answer to this questio? – Hugo Gresse Apr 19 '21 at 13:16