Bill Farmer

Random thoughts on random subjects

Resolving content uris in android

by Bill Farmer. Categories: Hacking .

If you write an android app that handles images or any other sort of file your app may be required to deal with ‘content’ uris (content://). There is a very useful utility which resolves these into ‘file’ uris (file:///) FileUtils.java. This contains one external reference to LocalStorageProvider, which can be resolved by removing the function isLocalStorageDocument() and references to it.

    // import com.ianhanniballake.localstorage.LocalStorageProvider;
    // ...
        /**
         * @param uri The Uri to check.
         * @return Whether the Uri authority is {@link LocalStorageProvider}.
         * @author paulburke
         */
        public static boolean isLocalStorageDocument(Uri uri) {
            return LocalStorageProvider.AUTHORITY.equals(uri.getAuthority());
        }

Having done that, you can then resolve ‘content’ uris

    public final static String CONTENT = "content";
    // ...
            if (uri.getScheme().equalsIgnoreCase(CONTENT))
                uri = resolveContent(uri);
    // ...
        // resolveContent
        private Uri resolveContent(Uri uri)
        {
            String path = FileUtils.getPath(this, uri);
            if (path != null)
            {
                File file = new File(path);
                if (file.canRead())
                    uri = Uri.fromFile(file);
            }
            return uri;
        }

This may not always work, but I haven’t been able to defeat it. Later versions of android have added a ‘Documents’ folder, which is encoded as ‘home’, so some additional code is required to resolve it.

    /**
     * Get a file path from a Uri. This will get the the path for
     * Storage Access Framework Documents, as well as the _data field
     * for the MediaStore and other file-based ContentProviders.<br>
     * <br>
     * Callers should check whether the path is local before assuming
     * it represents a local file.
     *
     * @param context The context.
     * @param uri The Uri to query.
     * @see #isLocal(String)
     * @see #getFile(Context, Uri)
     * @author paulburke
     */
    @TargetApi(19)
    public static String getPath(final Context context, final Uri uri)
    {
        // ...
        final boolean isKitKat =
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri))
        {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri))
            {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                // /
                if ("primary".equalsIgnoreCase(type))
                {
                    return Environment
                        .getExternalStorageDirectory() + "/" + split[1];
                }

                // /Documents
                else if ("home".equalsIgnoreCase(type))
                {
                    return Environment
                        .getExternalStorageDirectory() + "/Documents/" +
                        split[1];
                }
                // TODO handle non-primary volumes
            }
        // ...
        }
    // ...
    }


See Also