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.

Leave a Reply

Your email address will not be published. Required fields are marked *