Getting File Path from URI on Android 10
Android 10 (API level 29) introduced significant changes to how file access is handled, focusing on user privacy and security. One of the major impacts is on retrieving file paths from URIs. This article explains the challenges and solutions for getting file paths from URIs on Android 10 and beyond.
The Challenge: Legacy File Access Restrictions
In previous Android versions, getting the file path from a URI was relatively straightforward using Uri.getPath()
. However, Android 10 restricts access to file paths for security reasons. Accessing files directly through file paths can expose sensitive data, and Android 10 aims to protect user privacy.
Solutions for Getting File Path in Android 10
Android 10 provides several mechanisms for accessing files while respecting user privacy. Here are some solutions:
1. Using ContentResolver and OpenableColumns
For files accessed through content providers (like images from the gallery), you can use the ContentResolver
and the OpenableColumns
class.
import android.content.ContentResolver;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.widget.Toast;
// ... Inside your activity or fragment
public void getFileDetails(Uri uri) {
if (uri != null) {
if (uri.getScheme() != null && uri.getScheme().equals("content")) {
ContentResolver resolver = getContentResolver();
try {
Cursor cursor = resolver.query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
String fileName = cursor.getString(nameIndex);
// Get the file path, but it may be in the form of content://...
String filePath = uri.getPath();
Toast.makeText(this, "File Name: " + fileName + "\nFile Path: " + filePath, Toast.LENGTH_LONG).show();
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
}
}
2. Using Storage Access Framework (SAF)
The Storage Access Framework (SAF) provides a standardized way to access files, allowing users to choose files from different storage providers (like Google Drive, local storage, etc.).
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.widget.Toast;
// ... Inside your activity
public void openFileFromSAF() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*"); // Set the desired file type
startActivityForResult(intent, REQUEST_CODE_OPEN_FILE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_OPEN_FILE && resultCode == Activity.RESULT_OK) {
Uri uri = data.getData();
if (uri != null) {
// Get file details using ContentResolver and OpenableColumns
// ... (see previous example)
}
}
}
3. Using FileProvider
If you need to access files from your app’s private storage, use FileProvider
to grant temporary access to external apps. This ensures that you don’t directly expose the file path.
// ... Inside your AndroidManifest.xml (application tag)
// ... Create file_paths.xml in your res/xml directory
// ... Inside your activity or fragment
public void getFileUriFromPrivateStorage(File file) {
// Create URI using FileProvider
Uri uri = FileProvider.getUriForFile(this, "${applicationId}.fileprovider", file);
// Use the URI for accessing the file (e.g., share, send via intent)
// ...
}
Comparing Solutions
Solution | Description | Suitable for |
---|---|---|
ContentResolver and OpenableColumns | Retrieve file details and paths from content providers. | Accessing files from the gallery, documents, etc. |
Storage Access Framework (SAF) | Allows users to select files from different storage providers. | Choosing files from multiple sources, granting limited access to external apps. |
FileProvider | Grants temporary access to files in your app’s private storage. | Sharing or accessing files from your app’s internal storage with other apps. |
Conclusion
Getting file paths from URIs on Android 10 and above requires a shift in how you handle file access. By utilizing the appropriate methods like ContentResolver, Storage Access Framework, and FileProvider, you can ensure that your app complies with security and privacy guidelines while still accessing the files you need.