Search code examples
javaandroidstorage-access-framework

Extracting Filenames from SAF content URIs


Hello my fellow stackoverflows,

I am writing an application where I implemented an Activity that handles share-intents. So far it works fine but during testing I have got a problem with Quickoffice (Android 4.4, KitKat), because it returns an URI from which I can´t get the filename from. I also tried sharing with other apps like Dropbox and it works there.

The exact URI I get from the Qickoffice app:

content://com.quickoffice.android.quickcommon.FileContentProvider/5cmeDeeatcdv8IFyu-bEr2w1jSHrvPmCzXGb_VvZulMBErE5Tmfd_5P5kckE68LaEYDVSp3q5r19%0A4sOkpYCEM_VqK6Y%3D%0A

This was the code I used first:

public String getRealPathFromURI(Uri contentUri) {
    Cursor cursor = null;
    try {
        String[] proj = {MediaStore.Images.Media.DATA}; // = "_data"
        ContentResolver cr = getContentResolver(); 
        cursor = cr.query(contentUri, proj, null, null, null); // <--EXCEPTION

        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    } catch (Exception exception) {
        Log.d("clixend", "Exception: " + exception);
        Toast.makeText(this, "Exception: " + exception, Toast.LENGTH_LONG).show();
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
    return null;
}

Where I received following error:

09-23 16:54:17.664  32331-32341/? E/DatabaseUtils﹕ Writing exception to parcel
java.lang.UnsupportedOperationException: Unsupported column: _data
        at com.google.android.apps.docs.quickoffice.FileContentProvider.query(FileContentProvider.java:78)
        at android.content.ContentProvider.query(ContentProvider.java:857)
        at android.content.ContentProvider$Transport.query(ContentProvider.java:200)
        at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:112)
        at android.os.Binder.execTransact(Binder.java:404)
        at dalvik.system.NativeStart.run(Native Method)

After some research I figured out that Android 4.4 Kitkat introduces SAF (Storage Access Framework) which manages data different, so I tried the following Code from https://developer.android.com/guide/topics/providers/document-provider.html to get the name:

public String getNameKitkat(Uri contentUri) {
Cursor cursor = getContentResolver()
            .query(contentUri, null, null, null, null, null); // <--EXCEPTION
    try {
        if (cursor != null && cursor.moveToFirst()) {
            String displayName = cursor.getString(
                    cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));

           return displayName;
        }
    } finally {
        cursor.close();
    }
    return null;
}

But I also receive an error code:

09-23 16:49:43.317  32331-32421/? E/DatabaseUtils﹕ Writing exception to parcel
java.lang.IllegalArgumentException: columnNames.length = 4, columnValues.size() = 2
        at android.database.MatrixCursor.addRow(MatrixCursor.java:157)
        at android.database.MatrixCursor.addRow(MatrixCursor.java:128)
        at com.google.android.apps.docs.quickoffice.FileContentProvider.query(FileContentProvider.java:95)
        at android.content.ContentProvider.query(ContentProvider.java:857)
        at android.content.ContentProvider$Transport.query(ContentProvider.java:200)
        at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:112)
        at android.os.Binder.execTransact(Binder.java:404)
        at dalvik.system.NativeStart.run(Native Method)

If somebody knows how to get the name out of the URI I get from Quickoffice I would be very thankful.


Solution

  • After I searched some more I found the answer to my question how to get the filename from the URI I get from Quickoffice.

    public String getNameFromURI(Uri contenturi){
    
        String[] proj = {
                OpenableColumns.DISPLAY_NAME,
                OpenableColumns.SIZE
        };
        String name = null;
        int size= 0;
        Cursor metadataCursor = getContentResolver().query(contenturi,  proj, null, null, null);
    
        if (metadataCursor != null) {
            try {
                if (metadataCursor.moveToFirst()) {
                    name = metadataCursor.getString(0);
                    size = metadataCursor.getInt(1);
                }
            } finally {
                metadataCursor.close();
            }
        }
    
        return name;
    }
    

    The problem was I didn´t use the proper Typ, I wanted to receive. After using:

    String[] proj = {
            OpenableColumns.DISPLAY_NAME,
            OpenableColumns.SIZE
    };
    

    it worked perfectly fine. Sorry for your waste of time.