Android development
MediaStore API
URI handling
file path retrieval
programming tutorial

Get filename and path from URI from mediastore

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

In modern Android application development, working with media files often requires accessing files stored in shared storage. MediaStore is an integral component of the Android framework, providing a content provider for accessing common media files such as audio, video, and images. This article explores how to efficiently retrieve the filename and path from a URI using MediaStore, with technical explanations, examples, and a summary table highlighting the main points.

Understanding URI in MediaStore

In Android, a URI (Uniform Resource Identifier) is a string used to identify a resource. Media files in shared storage are identified by URIs, allowing your application to interact with these files without needing direct file paths. MediaStore URIs typically follow this format:

 
content://media/external/images/media/[id]

Here, content:// denotes the content provider scheme, while media/external/images/media/ specifies the external storage and image directory within MediaStore.

Retrieving File Information from a URI

Step 1: Permissions

Before accessing files, ensure you have the necessary permissions defined in your AndroidManifest.xml:

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

Additionally, for Android 6.0 (API level 23) and above, request runtime permissions.

Step 2: Querying MediaStore

To extract the filename and path from a URI, you'll typically make use of the ContentResolver to query MediaStore. Use a projection to specify the columns you need, such as _display_name for the filename and _data for the file path (if applicable).

Here's a Kotlin example:

kotlin
1private fun getFileNameAndPathFromUri(context: Context, uri: Uri): Pair<String?, String?> {
2    val projection = arrayOf(MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.DATA)
3    var name: String? = null
4    var path: String? = null
5
6    context.contentResolver.query(uri, projection, null, null, null)?.use { cursor ->
7        if (cursor.moveToFirst()) {
8            val nameIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)
9            val pathIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
10            name = cursor.getString(nameIndex)
11            path = cursor.getString(pathIndex) // May be null in some cases
12        }
13    }
14
15    return Pair(name, path)
16}

Note on _data Column

Be cautious as the _data column may return null, especially for scoped storage on Android 10 and above.

Handling Scoped Storage

Starting with Android 10 (API level 29), scoped storage changes restrict direct access to file paths, favoring the usage of URI and Streams for increased security and privacy. If you target these API levels, you might want to use ContentResolver.openInputStream(uri) to access the file content rather than relying on the file path.

Example:

kotlin
1val inputStream = context.contentResolver.openInputStream(uri)
2inputStream?.use {
3    // Process the input stream
4}

Alternative Method: Retrieving File Path from InputStream

While direct file path access is limited, converting a URI into a usable file path can still be achieved by writing the contents of the URI to a temporary file:

kotlin
1fun writeToTempFile(context: Context, uri: Uri): File {
2    val tempFile = File.createTempFile("prefix", "suffix", context.cacheDir)
3    context.contentResolver.openInputStream(uri).use { inputStream ->
4        FileOutputStream(tempFile).use { outputStream ->
5            val buffer = ByteArray(8 * 1024)
6            var bytesRead: Int
7            while (inputStream?.read(buffer).also { bytesRead = it ?: -1 } != -1) {
8                outputStream.write(buffer, 0, bytesRead)
9            }
10        }
11    }
12    return tempFile
13}

Conclusion

The transition towards scoped storage in Android requires developers to adapt their methods for accessing file metadata and content. By leveraging MediaStore's content provider, we can efficiently retrieve file details such as names and access data via URIs. This approach not only aligns with modern security practices but also ensures future compatibility across Android versions.

Summary Table

Below is a table summarizing the key points covered in this article:

FeatureDetails
URI Formatcontent://media/external/images/media/[id]
Necessary PermissionsREAD_EXTERNAL_STORAGE
Important Columns_display_name, _data
Scoped Storage ImpactDirect file path access is restricted Use URI and Streams instead
Data RetrievalUse ContentResolver to query MediaStore
File Path WorkaroundSave URI data to a temp file for access

By embracing these techniques, you ensure that your application remains robust and compliant with Android's evolving ecosystem.


Course illustration
Course illustration

All Rights Reserved.