AndroidQ 系统自带文件选择器
16lz
2021-01-26
Android Q 作用域规则
如果我们要读取SD卡上非图片、音频、视频类的文件,比如说先选择一个doc文件,这个时候就不能再使用MediaStore API了,而是要使用系统自带的文件选择器。直接上代码。
//选择文件private void performFileSearch() { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); //允许多选 长按多选 intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); //不限制选取类型 intent.setType("*/*"); startActivityForResult(intent, -1);}//接收返回值@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case -1: if (resultCode == Activity.RESULT_OK && data != null) { //当单选选了一个文件后返回 if (data.getData() != null) { handleSingleDocument(data); } else { //多选 ClipData clipData = data.getClipData(); if (clipData != null) { Uri[] uris = new Uri[clipData.getItemCount()]; for (int i = 0; i < clipData.getItemCount(); i++) { uris[i] = clipData.getItemAt(i).getUri(); } } } } break; }}//将uri转换为我们需要的path,多选类似private void handleSingleDocument(Intent data) { Uri uri = data.getData(); String filePath = FileUtils.getRealPath(this, uri);}
FileUtils.java文件 (根据Uri获取Path)
网上流传的很多Uri获取Path的方法虽然都适配到了Android 4.4,但是到了Android 8.0又不好使了,下面是在Android 10.0上测试通过的版本。
public class FileUtils { public static String getRealPath(Context context, Uri fileUri) { String realPath; // SDK < API11 if (Build.VERSION.SDK_INT < 11) { realPath = FileUtils.getRealPathFromURI_BelowAPI11(context, fileUri); } // SDK >= 11 && SDK < 19 else if (Build.VERSION.SDK_INT < 19) { realPath = FileUtils.getRealPathFromURI_API11to18(context, fileUri); } // SDK > 19 (Android 4.4) and up else { realPath = FileUtils.getRealPathFromURI_API19(context, fileUri); } return realPath; } @SuppressLint("NewApi") public static String getRealPathFromURI_API11to18(Context context, Uri contentUri) { String[] proj = {MediaStore.Images.Media.DATA}; String result = null; CursorLoader cursorLoader = new CursorLoader(context, contentUri, proj, null, null, null); Cursor cursor = cursorLoader.loadInBackground(); if (cursor != null) { int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); result = cursor.getString(column_index); cursor.close(); } return result; } public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) { String[] proj = {MediaStore.Images.Media.DATA}; Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null); int column_index = 0; String result = ""; if (cursor != null) { column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); result = cursor.getString(column_index); cursor.close(); return result; } return result; } @SuppressLint("NewApi") public static String getRealPathFromURI_API19(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]; // This is for checking Main Memory if ("primary".equalsIgnoreCase(type)) { if (split.length > 1) { return Environment.getExternalStorageDirectory() + "/" + split[1]; } else { return Environment.getExternalStorageDirectory() + "/"; } // This is for checking SD Card } else { return "storage" + "/" + docId.replace(":", "/"); } } // DownloadsProvider else if (isDownloadsDocument(uri)) { String fileName = getFilePath(context, uri); if (fileName != null) { return Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName; } String id = DocumentsContract.getDocumentId(uri); if (id.startsWith("raw:")) { id = id.replaceFirst("raw:", ""); File file = new File(id); if (file.exists()) return id; } 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 the remote address if (isGooglePhotosUri(uri)) return uri.getLastPathSegment(); return getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } 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 index = cursor.getColumnIndexOrThrow(column); return cursor.getString(index); } } finally { if (cursor != null) cursor.close(); } return null; } public static String getFilePath(Context context, Uri uri) { Cursor cursor = null; final String[] projection = { MediaStore.MediaColumns.DISPLAY_NAME }; try { cursor = context.getContentResolver().query(uri, projection, null, null, null); if (cursor != null && cursor.moveToFirst()) { final int index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME); return cursor.getString(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()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is Google Photos. */ public static boolean isGooglePhotosUri(Uri uri) { return "com.google.android.apps.photos.content".equals(uri.getAuthority()); }}
最后,如果想给选择器添加过滤的文件类型,只需要添加如下代码就可以了
String[] mimeTypes = {MimeType.DOC, MimeType.DOCX, MimeType.PDF, MimeType.PPT, MimeType.PPTX, MimeType.XLS, MimeType.XLSX};intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);//存放需要过滤的类型的类public class MimeType { public static final String DOC = "application/msword"; public static final String DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; public static final String XLS = "application/vnd.ms-excel"; public static final String XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; public static final String PPT = "application/vnd.ms-powerpoint"; public static final String PPTX = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; public static final String PDF = "application/pdf";}
更多相关文章
- Android(安卓)Lint
- Android(安卓)MediaScannerConnection,Android(安卓)MediaScanner
- Android(安卓)自定义Notification字体颜色适配
- 系统定义弹窗以及自定义弹窗
- Android之CheckBox(多选按钮)
- Mac OS 上配置Android(安卓)studio的真机调试环境
- Android(安卓)Fragment学习笔记(一)
- Android(安卓)boot.img 结构
- 解决Android(安卓)studio 2.3升级到Android(安卓)studio 3.0 后a