今天测试提了一个很奇怪的问题,说是在选择文件上传时失败,当时听到这个问题感觉到很奇怪,因为这块功能已经稳定运行很长事件了,等我拿来手机一看发现他选择的文件是个很奇怪地方的文件,这个是手机错误报告的文件,路径也很奇怪是这样的
content://com.android.shell.documents/documentgreport%3Abugreport-JKM-AL00b-HUAWEIJKM-AL00b-2022-01-20-10-29-01-dumpstate_log-22742.txt
我打了断点发现在转路径时发现怎么也匹配不上
if (isExternalStorageDocument(uri)) { // 【ExternalStorageProvider】
String docId = DocumentsContract.getDocumentId(uri);
String[] split = docId.split(":");
String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
} else {
String storagePath = getStoragePath(context);
if (!TextUtils.isEmpty(storagePath)) {
return storagePath + File.separator + split[1];
}
}
} else if (isDownloadsDocument(uri)) { // 【DownloadsProvider】
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"
};
for (String contentUriPrefix : contentUriPrefixesToTry) {
Uri contentUri = null;
if (id != null) {
//修复id有可能包含:冒号造成转id时失败
String index;
if (id.contains(":")) {
String[] split = id.split(":");
index = split[1];
} else {
index = id;
}
contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.parseLong(index));
}
try {
String path = getDataColumn(context, contentUri, null, null);
if (path != null) {
return path;
}
} catch (Exception e) {
e.printStackTrace();
}
}
// path could not be retrieved using ContentResolver, therefore copy file to accessible cache using streams
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;
} else if (isMediaDocument(uri)) {
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 if ("document".equals(type)) {
contentUri = MediaStore.Files.getContentUri("external");
}
String selection = "_id=?";
String[] selectionArgs = new String[] { split[1] };
return getDataColumn(context, contentUri, selection, selectionArgs);
}
这些都匹配不上,我查了很久也没又查到怎么去处理它,也许是我查找的方式不对吧!最后我想了一个怪招,就是把这个不能获取路径的文件复制一份
public static String getPath(Context context, Uri uri){
.......
//实在找不到就复制一份
if ("content".equalsIgnoreCase(uri.getScheme())) {
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;
}
}
private static String getFileName(@NonNull Context context, Uri uri) {
String mimeType = context.getContentResolver().getType(uri);
String filename = null;
if (mimeType == null) {
String path = getPath(context, uri);
if (path == null) {
filename = getFileName(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;
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private static File getDocumentCacheDir(@NonNull Context context) {
File dir = new File(context.getCacheDir(), DOCUMENTS_DIR);
if (!dir.exists()) {
dir.mkdirs();
}
return dir;
}
@Nullable
private static File generateFileName(@Nullable String name, File directory) {
if (name == null) {
return null;
}
File file = new File(directory, name);
if (file.exists()) {
file.delete();
}
try {
if (!file.createNewFile()) {
return null;
}
} catch (IOException e) {
return null;
}
return file;
}
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];
if (is != null) {
is.read(buf);
}
do {
bos.write(buf);
} while ((is != null ? is.read(buf) : 0) != -1);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
这样一来就能解决这个问题了,但是问题具体原因实在不清楚,如果有知道的兄弟,欢迎评论讲解下