Android使用系统文件管理器选择文件,并将Uri转换为File
文章目录
- 0.README
- 1.利用系统文件管理器选择文件得到Uri码
- 2.Uri转化成File能读取的路径
- 参考文献
0.README
本文的android代码测试机型为:小米4。首先用系统文件管理器选择文件,获得文件Uri,然后解析Uri得到文件真实路径。
1.利用系统文件管理器选择文件得到Uri码
这里借鉴的是CSDN博客里别的大佬的回答(见参考文献[1],记得申请运行时权限 READ_EXTERNAL_STORAGE
):
//**********************************File Choose Depart****************************************private static final String TAG1 = "FileChoose";// 调用系统文件管理器private void chooseFile() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE); try { startActivityForResult(Intent.createChooser(intent, "Choose File"), CHOOSE_FILE_CODE); } catch (ActivityNotFoundException e) { Toast.makeText(this, "亲,木有文件管理器啊-_-!!", Toast.LENGTH_SHORT).show(); }}private static final int CHOOSE_FILE_CODE = 0;@Override// 文件选择完之后,自动调用此函数protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK) { if (requestCode == CHOOSE_FILE_CODE) { Uri uri = data.getData(); } } else { Log.e(TAG1, "onActivityResult() error, resultCode: " + resultCode); } super.onActivityResult(requestCode, resultCode, data);}
2.Uri转化成File能读取的路径
Uri.toString()
的值为
content://com.android.fileexplorer.myprovider/external_files/AFolder/tiaojiaoqi.stl
Uri.getPath()
的值为
external_files/AFolder/tiaojiaoqi.stl
文件的实际外部存储路径为
/storage/emulated/0/AFolder/tiaojiaoqi.stl
这里采用了StackOverflow上大神Paul Burke的代码(见参考文献[2]),在小米4 Android 8.0.0 API 26
上的测试是成功的:
Uri uri = data.getData();String sPath1 = null;sPath1 = getPath(this, uri); // Paul Burke写的函数,根据Uri获得文件路径
/** * 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. * * @param context The context. * @param uri The Uri to query. * @author paulburke */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]; } // TODO handle non-primary volumes } // DownloadsProvider else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri 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.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); } } // 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 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;}/** * @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());}
最后根据路径打开文件,可以自由处理了。
Demo代码在这里。
参考文献
[1] 安卓[android] 通过Uri获取File文件. https://blog.csdn.net/Gen_Ye/article/details/53537139
[2] Get real path from URI, Android KitKat new storage access framework [duplicate].
https://stackoverflow.com/questions/20067508/get-real-path-from-uri-android-kitkat-new-storage-access-framework/20559175#20559175
更多相关文章
- 一款常用的 Squid 日志分析工具
- GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
- RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
- Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
- android存放本地数据
- android 网络下载PDF文件并打开PDF文件内容
- Android多分辨率适配巧妙方法
- Android(安卓)SD卡 路径问题
- Android周学习Step By Step(3)--应用工程文件组成