问题1:在DocumentProvider中我在调试的过程发现有些文件路径不是primary而是以home开头的路径
content://com.android.externalstorage.documents/document/home:A20220419194337xzspj_chenxiaobin.docx
这时候 百度中常用的 Environment.getExternalStorageDirectory() 再拼上文件路径无法获取到文件,实际文件路径得再加个documents
// 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];
}else{
return Environment.getExternalStorageDirectory()+ "/documents/" + split[1];
}
}
问题2:在DownloadsProvider中uri路径中返回的不是
content://com.android.providers.downloads.documents/document/158
这种常规类型的 地址而是返回的是
content://com.android.providers.downloads.documents/document/raw:/storage/emulated/0/Download/Browser/12345_1.0.apk
类似这种的地址
解决方案:
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
//DocumentsContract.getDocumentId(uri)返回String路径而不是Long类型数字
final String id = DocumentsContract.getDocumentId(uri);
if (!StringUtils.isEmpty(id)) {
if (id.startsWith("raw:")) {
return id.replaceFirst("raw:", "");
}
try {
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), ContentUris.parseId(uri));
return getDataColumn(context, contentUri, null, null);
} catch (NumberFormatException e) {
return null;
}
}
}
完整代码 FileChooseUtil 工具类
public class FileChooseUtil {
private static Context context;
private static FileChooseUtil util = null;
private FileChooseUtil(Context context) {
this.context = context;
}
public static FileChooseUtil getInstance(Context context) {
if (util == null) {
util = new FileChooseUtil(context);
}
return util;
}
/**
* 对外接口 获取uri对应的路径
*
* @param uri
* @return
*/
public String getChooseFileResultPath(Uri uri) {
String chooseFilePath = null;
if ("file".equalsIgnoreCase(uri.getScheme())) {//使用第三方应用打开
chooseFilePath = uri.getPath();
Toast.makeText(context, chooseFilePath, Toast.LENGTH_SHORT).show();
return chooseFilePath;
}
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {//4.4以后
chooseFilePath = getPath(context, uri);
} else {//4.4以下下系统调用方法
chooseFilePath = getRealPathFromURI(uri);
}
return chooseFilePath;
}
public static String getRealPathFromURI(Uri contentUri) {
String res = null;
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
if (null != cursor && cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
res = cursor.getString(column_index);
cursor.close();
}
return res;
}
public static String uriToPath(Context context, Uri uri) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {//4.4以后
return FileChooseUtil.getPath(context, uri);
} else {//4.4以下下系统调用方法
return FileChooseUtil.getRealPathFromURI(uri);
}
}
/**
* 专为Android4.4设计的从Uri获取文件绝对路径,以前的方法已不好使
*/
@SuppressLint("NewApi")
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];
}else{
return Environment.getExternalStorageDirectory()+ "/documents/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
//DocumentsContract.getDocumentId(uri)返回String路径而不是Long类型数字
final String id = DocumentsContract.getDocumentId(uri);
if (!StringUtils.isEmpty(id)) {
if (id.startsWith("raw:")) {
return id.replaceFirst("raw:", "");
}
try {
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), ContentUris.parseId(uri));
return getDataColumn(context, contentUri, null, null);
} catch (NumberFormatException e) {
return 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;
}else if ("document".equals(type)) {
contentUri = MediaStore.Files.getContentUri("external");
}
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())) {
uri.getPath();
}
return null;
}
private 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.
*/
private 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.
*/
private 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.
*/
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
}
activity启动使用
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");//设置类型,我这里是任意类型,任意后缀的可以这样写。
//intent.setType(“image/*”);//选择图片
//intent.setType(“audio/*”); //选择音频
//intent.setType(“video/*”); //选择视频 (mp4 3gp 是android支持的视频格式)
//intent.setType(“video/*;image/*”);//同时选择视频和图片
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, 1000);
activity回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if ("selectFile".equals(selectFileType)) {
if (resultCode == PTBaseActivity.RESULT_OK) {
if ( requestCode == 1000) {
Uri uri = data.getData();//得到uri,后面就是将uri转化成file的过程。
String absolutePath = FileChooseUtil.uriToPath(this, uri);
if (StringUtils.isEmpty(absolutePath)){
ToastUtils.showBad("该文件不存在");
}else{
File file = new File(absolutePath);
if (file.exists()) {
//文件存在 自己逻辑 上传 或是打开
} else {
ToastUtils.showBad("该文件不存在");
}
}
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
引用了
DocumentsContract.getDocumentId(uri)返回String路径而不是Long类型数字 - 简书