Android 4.4 kitkat and above, and the following method to obtain the path based on uri
Please indicate the source for reprinting. Thank you ~
Today, when I was doing video editing, I encountered this problem. It took me one hour to find and solve it, because I always thought it was my mistake and later found that, P6 uses the Android4.4 system, and then I am surprised...
First of all, let's talk about what I am doing. After I finish shooting a video, I want to edit a video stuff. This stuff is actually not difficult. The source code contains it. Do you dare not believe it ?! In the android source code android. media. videoeditor has the videoeditor class. This is actually the video editing stuff written by Google. He calls several lib libraries written in C ++ at the underlying layer, and Google has written these libraries, let's call him. When I edit the video, I want to add a ringtone. When I get the path based on the uri I wrote, I always return null, which is strange, finally, we found that the 4.4 system was used by P6... The following code is not too long.
Here we will first look at the uri format before 4.4:
Uri : content://media/extenral/images/media/17766
Are you familiar with this?
Let's look at the Uri format of 4.4 and later:
content://com.android.providers.media.documents/document/image%2706
I printed it out, and it was so bad. What is this ?! Looking at P6's system, it's really 4.4.
So let's just talk about it. After turning over the API, we found that the Uri after 4.4 is not unique, and it is not a uniform format. So we just need a general method.
4.4 obtain the path from Uri before:
Data is uri, filename is a String, used to save the path.
If (data. getScheme (). toString (). compareTo ("content") = 0) {cursor = getContentResolver (). query (data, new String [] {Audio. media. DATA}, null); if (cursor. moveToFirst () {filename = cursor. getString (0) ;}} else if (data. getScheme (). toString (). compareTo ("file") = 0) // file: // uri {filename = data. toString (); filename = data. toString (). replace ("file: //", ""); // replace file: // if (! Filename. startsWith ("/mnt") {// Add "/mnt" header filename + = "/mnt ";}}
4.4 and later get the path based on the Uri:
Public class GetPathFromUri4kitkat {/*** it is designed for Android4.4 to obtain the absolute path of the file from the Uri. The previous method is hard to make */@ SuppressLint ("NewApi ") 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. getentid (uri); final String [] split = docId. split (":"); final String type = split [0]; if ("primary ". inclusignorecase (type) {return Environment. getExternalStorageDirectory () + "/" + split [1];} // TODO handle non-primary volumes} // DownloadsProvider else if (isDownloadsDocument (uri )) {final String id = DocumentsContract. getentid (uri); final Ur I contentUri = ContentUris. withAppendedId (Uri. parse ("content: // downloads/public_downloads"), Long. valueOf (id); return getDataColumn (context, contentUri, null, null);} // MediaProvider else if (isMediaDocument (uri) {final String docId = DocumentsContract. getentid (uri); final String [] split = docId. split (":"); final String type = split [0]; Uri contentUri = null; if ("image ". equals (type )){ ContentUri = MediaStore. images. media. EXTERNAL_CONTENT_URI;} else if ("video ". equals (type) {contentUri = MediaStore. video. media. EXTERNAL_CONTENT_URI;} else if ("audio ". equals (type) {contentUri = MediaStore. audio. media. EXTERNAL_CONTENT_URI;} final String selection = "_ id =? "; Final String [] selectionArgs = new String [] {split [1]}; return getDataColumn (context, contentUri, selection, selectionArgs); }}// MediaStore (and general) else if ("content ". equalsIgnoreCase (uri. getScheme () {return getDataColumn (context, uri, null, null);} // File else if ("file ". equalsIgnoreCase (uri. getScheme () {return uri. getPath ();} return null;}/*** Get the value of the data c Olumn for this Uri. this is useful for * MediaStore Uris, and other file-based ContentProviders. ** @ param context * The context. * @ param uri * The Uri to query. * @ param selection * (Optional) Filter used in the query. * @ param selectionArgs * (Optional) Selection arguments used in the query. * @ return The value of the _ data column, which is typically a file path. */public static String getDat AColumn (Context context, Uri uri, String selection, String [] selectionArgs) {Cursor cursor = null; final String column = "_ data "; final String [] projection = {column}; try {cursor = context. getContentResolver (). query (uri, projection, selection, selectionArgs, null); if (cursor! = Null & cursor. moveToFirst () {final int column_index = cursor. getColumnIndexOrThrow (column); return cursor. getString (column_index) ;}} finally {if (cursor! = Null) cursor. close ();} return null;}/*** @ param uri * The Uri to check. * @ return Whether the Uri authority is ExternalStorageProvider. */public static boolean isExternalStorageDocument (Uri uri) {return "com.android.externalstorage.doc uments ". equals (uri. getAuthority ();}/*** @ param uri * The Uri to check. * @ return Whether the Uri authority is DownloadsProvider. */public static boolean isDownloadsDocument (Uri uri) {return "com.android.providers.downloads.doc uments ". equals (uri. getAuthority ();}/*** @ param uri * The Uri to check. * @ return Whether the Uri authority is MediaProvider. */public static boolean isMediaDocument (Uri uri) {return "com.android.providers.media.doc uments ". equals (uri. getAuthority ());}}
This part of the Code draws some examples from the Internet and is available for test. copy is welcome.