1.项目开发中需要用到选择文件的功能,本来一直没什么问题,但是最近用户却来反应再选择文件时出现了崩溃,后来通过市场发来的操作视频发现了,每次出错都是在进入系统文件管理页面后点击了下载内容该条目后选择里面的文件出现的,得知后复现了一下问题,证明该问题确实一直存在并且只存在于该目录下,这让我感到很是奇怪。
看代码是url错误了,但是方法应该是对的,最后上网找了下,基本都是在说6.0,7.0之后的权限问题,可是在代码里已经做过处理了明显不是这个原因。后来打了下log看了下路径到底是什么
if (isDownloadsDocument(uri)) { // 【DownloadsProvider】
String id = DocumentsContract.getDocumentId(uri);
LogUtil.d("路径","---------","sss*"+id);
Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
这时发现了问题返回的路径有问题。前面多了个raw的前缀,只要像这样
String id = DocumentsContract.getDocumentId(imageUri);
if (id.startsWith("raw:")
判断一下id是否包含截取掉在按正常的处理就行了,这个问题我在网上看了下好像这个问题并不是个简单的问题有很多的案例,具体什么原因也不是很清楚,大家如果知道原因欢迎告诉我
后来这个问题又出现了,上述方法不是很好用,为了解决这个问题翻了很多的博客最后找到了个相对可以解决的办法,办法如下:
将上述代码改为
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 = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
try {
String path = getDataColumn(context, contentUri, null, null);
if (path != null) {
return path;
}
} catch (Exception e) {}
}
// 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;
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);
}
public static File getDocumentCacheDir(@NonNull Context context) {
File dir = new File(context.getCacheDir(), DOCUMENTS_DIR);
if (!dir.exists()) {
dir.mkdirs();
}
// logDir(context.getCacheDir());
// logDir(dir);
return dir;
}
@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) {
//Log.w(TAG, e);
return null;
}
//logDir(directory);
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];
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();
}
}
}
其主要是把该文件复制了一份得到其路径,希望大家有更好的办法解决