全网查过都漏了一种情况,isMediaDocument的判断里面都少了else,这里补充了大家看看,还有没别的适配问题,可以一起完善下
private static boolean isLocalStorageDocument(Context cxt, Uri uri) {
return getFileProvider(cxt).equals(uri.getAuthority());
}
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
* 获取FileProvider path
*/
private static String getFilePathByFileProviderUri(Context context, Uri uri) {
try {
List<PackageInfo> packs = context.getPackageManager().getInstalledPackages(PackageManager.GET_PROVIDERS);
String fileProviderClassName = FileProvider.class.getName();
for (PackageInfo pack : packs) {
ProviderInfo[] providers = pack.providers;
if (providers != null) {
for (ProviderInfo provider : providers) {
if (Objects.equals(uri.getAuthority(), provider.authority)) {
if (provider.name.equalsIgnoreCase(fileProviderClassName)) {
Class<FileProvider> fileProviderClass = FileProvider.class;
try {
Method getPathStrategy = fileProviderClass.getDeclaredMethod("getPathStrategy", Context.class, String.class);
getPathStrategy.setAccessible(true);
Object invoke = getPathStrategy.invoke(null, context, uri.getAuthority());
if (invoke != null) {
String PathStrategyStringClass = FileProvider.class.getName() + "$PathStrategy";
Class<?> PathStrategy = Class.forName(PathStrategyStringClass);
Method getFileForUri = PathStrategy.getDeclaredMethod("getFileForUri", Uri.class);
getFileForUri.setAccessible(true);
Object invoke1 = getFileForUri.invoke(invoke, uri);
if (invoke1 instanceof File) {
return ((File) invoke1).getAbsolutePath();
}
}
} catch (Exception e) {
e.printStackTrace();
}
break;
}
break;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
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.
*/
private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
String column = "_data";
String[] projection = {column};
try (Cursor cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null)) {
if (cursor != null && cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// endregion
//由Uri读取路径
public static String getFilePathByUri(Context context, Uri uri) {
if (context == null || uri == null) return null;
// 先直接查一遍该uri,能拿到路径就不用做后续那些复杂的判断了
String filePath = getDataColumn(context, uri, null, null);
if (!TextUtils.isEmpty(filePath))
return filePath;
try {
if (isLocalStorageDocument(context, uri)) {
// The path is the id
filePath = getFilePathByFileProviderUri(context, uri);
} else if (DocumentsContract.isDocumentUri(context, uri)) { // DocumentProvider
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
String docId = DocumentsContract.getDocumentId(uri);
String[] split = docId.split(":");
String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
filePath = Environment.getExternalStorageDirectory() + "/" + split[1];
} else if ("home".equalsIgnoreCase(type)) {
filePath = Environment.getExternalStorageDirectory() + "/" + split[1];
}
} else if (isDownloadsDocument(uri)) { // DownloadsProvider
String id = DocumentsContract.getDocumentId(uri);
if (id.startsWith("raw:")) {
filePath = id.replaceFirst("raw:", "");
} else {
String[] split = id.split(":");
if (split.length == 2)
id = split[1];
Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.parseLong(id));
filePath = getDataColumn(context, contentUri, null, null);
}
} else if (isMediaDocument(uri)) { // MediaProvider
String docId = DocumentsContract.getDocumentId(uri);
String[] split = docId.split(":");
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;
} else {
try {
// content://com.android.providers.media.documents/document/document%3A1000002873
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
contentUri = MediaStore.getMediaUri(context, uri);
filePath = getDataColumn(context, contentUri, null, null);
}
} catch (Exception ignored) {
}
try {
// 这个先写着适配,目前还没发现会走到这里的uri
if (TextUtils.isEmpty(filePath) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
contentUri = MediaStore.getDocumentUri(context, uri);
filePath = getDataColumn(context, contentUri, null, null);
}
} catch (Exception ignored) {
}
if (TextUtils.isEmpty(filePath))
contentUri = MediaStore.Files.getContentUri("external");
}
if (TextUtils.isEmpty(filePath)) {
String selection = "_id=?";
String[] selectionArgs = new String[]{split[1]};
filePath = getDataColumn(context, contentUri, selection, selectionArgs);
}
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) { // MediaStore (and general)
filePath = getDataColumn(context, uri, null, null);
} else if ("file".equalsIgnoreCase(uri.getScheme())) { // File
filePath = uri.getPath();
}
} catch (Exception ignored) {
}
if (TextUtils.isEmpty(filePath) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
filePath = uriToFileApiQ(context, uri);
if (!TextUtils.isEmpty(filePath)) {
String dirPath = filePath;
if (filePath.contains("/")) {
dirPath = filePath.substring(0, filePath.lastIndexOf("/"));
}
// 创建文件夹
new File(dirPath).mkdirs();
}
return filePath;
}
/**
* Android 10 以上适配 :
* 通过正常方式读取不到path,则先拷贝到私有目录,之后返回路径
*/
@RequiresApi(api = Build.VERSION_CODES.Q)
private static String uriToFileApiQ(Context context, Uri uri) {
if (uri.getScheme() == null) return null;
File file = null;
//android10以上转换
if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
if (uri.getPath() == null)
return null;
file = new File(uri.getPath());
} else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
//把文件复制到沙盒目录
ContentResolver contentResolver = context.getContentResolver();
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
@SuppressLint("Range") String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
try {
InputStream is = contentResolver.openInputStream(uri);
if (is != null) {
File cache = new File(getAppCachePath(context, "select_file"), displayName);
if (cache.exists())
cache.delete();
FileOutputStream fos = new FileOutputStream(cache);
android.os.FileUtils.copy(is, fos);
file = cache;
fos.close();
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
cursor.close();
}
}
if (file == null)
return null;
else
return file.getAbsolutePath();
}
public static String getFileProvider(Context context) {
String provider = context.getPackageName() + ".fileprovider";
L.i(provider);
return provider;
}
// 获取缓存路径
public static String getAppCachePath(Context context, String directory) {
String filePath;
if (TextUtils.isEmpty(directory))
filePath = context.getCacheDir().getPath() + File.separator;
else
filePath = context.getCacheDir().getPath() + File.separator + directory + File.separator;
createSelfDirIfNotExist(filePath);
return filePath;
}
// 判断私有目录是否存在,不存在则进行创建
private static void createSelfDirIfNotExist(String path) {
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
}
微信搜索“A查佣利小助手”,获取支付宝红包、TB/JD/PDD返利最新优惠资讯!