-
-
Save jaisoni/4d4e20409849dd3cfa12ee15895124a6 to your computer and use it in GitHub Desktop.
A complete class for getting file path from URI.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class FileUtils { | |
public static final String DOCUMENTS_DIR = "documents"; | |
/*** | |
* get actual path from provided file uri | |
* | |
* @param context application context | |
* @param uri file uri | |
*/ | |
public static String getPath(Context context, Uri uri) { | |
//TODO write espresso test cases | |
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; | |
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { | |
Logger.e("File Utility", uri+""); | |
if(isVirtualFile(context, uri) ){ | |
Logger.e("File Utility", "isVirtualFile"); | |
return getVirtualFile(context, uri); | |
}else if (isLocalStorageDocument(uri)) { | |
// LocalStorageProvider | |
return DocumentsContract.getDocumentId(uri); | |
} else if (isExternalStorageDocument(uri)) { | |
// ExternalStorageProvider | |
return getPathFromExternalStorage(context, uri); | |
} else if (isDownloadsDocument(uri)) { | |
// DownloadsProvider | |
return getPathFromDownloads(context, uri); | |
} else if (isMediaDocument(uri)) { | |
// MediaProvider | |
return getPathFromMedia(context, uri); | |
} else if ("content".equalsIgnoreCase(uri.getScheme())) { | |
//uriStringIntent { dat=content://com.android.providers.downloads.documents/document/2975 flg=0x43 } | |
if(uri.getHost().equalsIgnoreCase("com.android.providers")) | |
return getDataColumn(context, uri, null, null); | |
else | |
return getVirtualFile(context, uri); | |
} else if ("file".equalsIgnoreCase(uri.getScheme())) { | |
return uri.getPath(); | |
} | |
} | |
return null; | |
} | |
private static boolean isVirtualFile(Context context,Uri uri) { | |
if (!DocumentsContract.isDocumentUri(context, uri)) { | |
return false; | |
} | |
Cursor cursor = context.getContentResolver().query( | |
uri, | |
new String[] { DocumentsContract.Document.COLUMN_FLAGS }, | |
null, null, null); | |
int flags = 0; | |
if (cursor.moveToFirst()) { | |
flags = cursor.getInt(0); | |
} | |
cursor.close(); | |
return (flags & DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT) != 0; | |
} | |
/** | |
* @param uri The Uri to check. | |
* @return Whether the Uri authority is | |
*/ | |
public static boolean isLocalStorageDocument(Uri uri) { | |
return uri.getAuthority().equals(<your uri Authority>); | |
} | |
/** | |
* @param uri The Uri to check. | |
* @return Whether the Uri authority is ExternalStorageProvider. | |
*/ | |
public static boolean isExternalStorageDocument(Uri uri) { | |
return "com.android.externalstorage.documents".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.documents".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.documents".equals(uri.getAuthority()); | |
} | |
private static String getVirtualFile(Context context, Uri uri){ | |
String fileName = getFileName(context, uri); | |
File cacheDir = getDocumentCacheDir(context); | |
File file = generateFileName(fileName, cacheDir); | |
InputStream is = null; | |
BufferedOutputStream bos = null; | |
ContentResolver resolver = context.getContentResolver(); | |
String[] openableMimeTypes = resolver.getStreamTypes(uri, | |
MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileName.substring(fileName.indexOf(".")+1))); | |
if (openableMimeTypes == null || | |
openableMimeTypes.length < 1) { | |
Logger.e("File Utils", "Cannot open file"); | |
return null; | |
} | |
try { | |
is = resolver | |
.openTypedAssetFileDescriptor(uri, openableMimeTypes[0], null) | |
.createInputStream(); | |
bos = new BufferedOutputStream(new FileOutputStream(file, false)); | |
byte[] buf = new byte[1024]; | |
is.read(buf); | |
do { | |
bos.write(buf); | |
} while (is.read(buf) != -1); | |
}catch (Exception e){ | |
e.printStackTrace(); | |
}finally { | |
try { | |
if (is != null) is.close(); | |
if (bos != null) bos.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
return file.getAbsolutePath(); | |
} | |
/** | |
* get file path external storage | |
* | |
* @param context application context | |
* @param uri file uri | |
**/ | |
public static String getPathFromExternalStorage(Context context, Uri 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]; | |
} else { | |
String filePath = ""; | |
if (Build.VERSION.SDK_INT > 20) { | |
//getExternalMediaDirs() added in API 21 | |
File external[] = context.getExternalMediaDirs(); | |
if (external.length > 1) { | |
filePath = external[1].getAbsolutePath(); | |
filePath = filePath.substring(0, filePath.indexOf("Android")) + split[1]; | |
} | |
} else { | |
filePath = "/storage/" + type + "/" + split[1]; | |
} | |
return filePath; | |
} | |
} | |
/** | |
* get file path in download database | |
* | |
* @param context application context | |
* @param uri file uri | |
**/ | |
public static String getPathFromDownloads(Context context, Uri uri) { | |
final String id = DocumentsContract.getDocumentId(uri); | |
if (id != null && id.startsWith("raw:")) { | |
return id.substring(4); | |
} | |
String[] contentUriPrefixesToTry = new String[]{ | |
"content://downloads/public_downloads", | |
"content://downloads/my_downloads", | |
"content://downloads/all_downloads" | |
}; | |
for (String contentUriPrefix : contentUriPrefixesToTry) { | |
Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id)); | |
try { | |
String path = getDataColumn(context, contentUri, null, null); | |
if (path != null) { | |
return path; | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
String fileName = getFileName(context, uri); | |
File cacheDir = getDocumentCacheDir(context); | |
File file = generateFileName(fileName, cacheDir); | |
String destinationPath = null; | |
if (file != null) { | |
destinationPath = file.getAbsolutePath(); | |
saveFileFromUri(context, uri, destinationPath); | |
} | |
return destinationPath; | |
} | |
public static String getFileName(@NonNull Context context, Uri uri) { | |
String mimeType = context.getContentResolver().getType(uri); | |
String filename = null; | |
if (mimeType == null && context != null) { | |
String path = getPath(context, uri); | |
if (path == null) { | |
filename = getName(uri.toString()); | |
} else { | |
File file = new File(path); | |
filename = file.getName(); | |
} | |
} else { | |
Cursor returnCursor = context.getContentResolver().query(uri, null, | |
null, null, null); | |
if (returnCursor != null) { | |
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); | |
returnCursor.moveToFirst(); | |
filename = returnCursor.getString(nameIndex); | |
returnCursor.close(); | |
} | |
} | |
return filename; | |
} | |
public static String getName(String filename) { | |
if (filename == null) { | |
return null; | |
} | |
int index = filename.lastIndexOf('/'); | |
return filename.substring(index + 1); | |
} | |
private static void saveFileFromUri(Context context, Uri uri, String destinationPath) { | |
InputStream is = null; | |
BufferedOutputStream bos = null; | |
try { | |
is = context.getContentResolver().openInputStream(uri); | |
bos = new BufferedOutputStream(new FileOutputStream(destinationPath, false)); | |
byte[] buf = new byte[1024]; | |
is.read(buf); | |
do { | |
bos.write(buf); | |
} while (is.read(buf) != -1); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} finally { | |
try { | |
if (is != null) is.close(); | |
if (bos != null) bos.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
@Nullable | |
public static File generateFileName(@Nullable String name, File directory) { | |
if (name == null) { | |
return null; | |
} | |
File file = new File(directory, name); | |
if (file.exists()) { | |
String fileName = name; | |
String extension = ""; | |
int dotIndex = name.lastIndexOf('.'); | |
if (dotIndex > 0) { | |
fileName = name.substring(0, dotIndex); | |
extension = name.substring(dotIndex); | |
} | |
int index = 0; | |
while (file.exists()) { | |
index++; | |
name = fileName + '(' + index + ')' + extension; | |
file = new File(directory, name); | |
} | |
} | |
try { | |
if (!file.createNewFile()) { | |
return null; | |
} | |
} catch (IOException e) { | |
Logger.w("FileUtils", e.getMessage()); | |
return null; | |
} | |
//logDir(directory); | |
return file; | |
} | |
public static File getDocumentCacheDir(@NonNull Context context) { | |
File dir = new File(context.getCacheDir(), DOCUMENTS_DIR); | |
if (!dir.exists()) { | |
dir.mkdirs(); | |
} | |
return dir; | |
} | |
/** | |
* get file path in media database | |
* | |
* @param context application context | |
* @param uri file uri | |
**/ | |
public static String getPathFromMedia(Context context, Uri uri) { | |
final String docId = DocumentsContract.getDocumentId(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); | |
} | |
/** | |
* Get the value of the data column 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 getDataColumn(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; | |
} | |
} |
Turskyi
commented
Nov 8, 2020
- in getDataColumn cursor never moveToFirst()
- in isVirtualFile code only for SDK_INT >= android.os.Build.VERSION_CODES.N
- in getPathFromExternalStorage , Environment.getExternalStorageDirectory and getExternalMediaDirs deprecated
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment