在android10以后在操作照片等文件上传的时候,需要做分区存储处理,不然无法读取到文件,分享一个照片读取处理的工具类
/**
* @Description: 从系统相册内选取 照片时,兼容androi 10
* @Author: gstory
* @CreateDate: 2021/4/19 11:46
**/
public class ImageFileUtil {
private static String imageCacheFile = "/image_cache";
/**
* 根据Uri获取图片的绝对路径
*
* @param context 上下文对象
* @param uri 图片的Uri
* @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
*/
@SuppressLint("ObsoleteSdkInt")
public static String getRealPathFromUri(Context context, Uri uri) {
//android 10+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
return getRealPathFromUriAboveApiAndroidQ(context, uri);
//android 4.4及以上
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
return getRealPathFromUriAboveApiAndroidK(context, uri);
// Android 4.4以下
} else {
return getRealPathFromUriBelowApiAndroidK(context, uri);
}
}
/**
* 适配 Android 10以上相册选取照片操作
*
* @param context 上下文
* @param uri 图片uri
* @return 图片地址
*/
private static String getRealPathFromUriAboveApiAndroidQ(Context context, Uri uri) {
Cursor cursor = null;
String path = getRealPathFromUriAboveApiAndroidK(context, uri);
try {
cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Images.Media._ID}, MediaStore.Images.Media.DATA + "=? ",
new String[]{path}, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
Uri baseUri = Uri.parse("content://media/external/images/media");
//这里也可以直接返回uri路径不做缓存读取操作
// return String.valueOf(Uri.withAppendedPath(baseUri, "" + id));
Uri uri2 = Uri.withAppendedPath(baseUri, "" + id);
int orientation = getOrientation(context, uri2);
return saveImagePath(context, getImageBit(context, uri2, orientation));
} else {
// 如果图片不在手机的共享图片数据库,就先把它插入。
if (new File(path).exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, path);
//这里也可以直接返回uri路径不做缓存读取操作
// return String.valueOf(context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values));
Uri uri2 = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
int orientation = getOrientation(context, uri2);
return saveImagePath(context, getImageBit(context, uri2, orientation));
} else {
return null;
}
}
} catch (Exception e) {
if (cursor != null)
cursor.close();
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* 适配Android 4.4以下(不包括api19),根据uri获取图片的绝对路径
*
* @param context 上下文对象
* @param uri 图片的Uri
* @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
*/
private static String getRealPathFromUriBelowApiAndroidK(Context context, Uri uri) {
return getDataColumn(context, uri, null, null);
}
/**
* 适配Android 4.4及以上,根据uri获取图片的绝对路径
*
* @param context 上下文对象
* @param uri 图片的Uri
* @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
*/
@SuppressLint("NewApi")
private static String getRealPathFromUriAboveApiAndroidK(Context context, Uri uri) {
String filePath = null;
if (DocumentsContract.isDocumentUri(context, uri)) {
// 如果是document类型的 uri, 则通过document id来进行处理
String documentId = DocumentsContract.getDocumentId(uri);
if (isMediaDocument(uri)) {
// 使用':'分割
String id = documentId.split(":")[1];
String selection = MediaStore.Images.Media._ID + "=?";
String[] selectionArgs = {id};
filePath = getDataColumn(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection, selectionArgs);
} else if (isDownloadsDocument(uri)) {
Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(documentId));
filePath = getDataColumn(context, contentUri, null, null);
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
// 如果是 content 类型的 Uri
filePath = getDataColumn(context, uri, null, null);
} else if ("file".equals(uri.getScheme())) {
// 如果是 file 类型的 Uri,直接获取图片对应的路径
filePath = uri.getPath();
}
return filePath;
}
/**
* 获取数据库表中的 _data 列,即返回Uri对应的文件路径
*/
private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
String path = null;
String[] projection = new String[]{MediaStore.Images.Media.DATA};
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndexOrThrow(projection[0]);
path = cursor.getString(columnIndex);
}
} catch (Exception e) {
if (cursor != null) {
cursor.close();
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return path;
}
/**
* @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());
}
/**
* @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 context
* @param photoUri
* @return
*/
public static int getOrientation(Context context, Uri photoUri) {
int orientation = 0;
Cursor cursor = context.getContentResolver().query(photoUri,
new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null);
if (cursor != null) {
if (cursor.getCount() != 1) {
return -1;
}
cursor.moveToFirst();
orientation = cursor.getInt(0);
cursor.close();
}
return orientation;
}
/**
* 根据bitmap获取uri
*
* @param context 上下文
* @param imageUri 图片uri
* @param orientation 图片方向
* @return
*/
public static Bitmap getImageBit(Context context, Uri imageUri, int orientation) {
//根据path获取url
// Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Long.parseLong(imagePath));
//获取bitmap
ParcelFileDescriptor parcelFileDescriptor = null;
Bitmap bitmap = null;
try {
parcelFileDescriptor = context.getContentResolver().openFileDescriptor(imageUri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
bitmap = changeBitmapOrientation(bitmap, orientation);
return bitmap;
}
/**
* 修改bitmap的方向 发现部分手机获取到的bitmap会旋转 所以改回原先图片的方法
*
* @param bitmap
* @param orientation
* @return
*/
private static Bitmap changeBitmapOrientation(Bitmap bitmap, int orientation) {
if (orientation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
return bitmap;
}
/**
* 保存bitmap到内部缓存目录
*
* @param context
* @param bitmap
* @return
*/
public static String saveImagePath(Context context, Bitmap bitmap) {
File file = new File(context.getExternalCacheDir() + imageCacheFile);
// 判断当前目录是否存在,不存在就创建
if (!file.exists()) {
file.mkdir();
}
File imageFile = new File(file.getPath() + "/" + System.currentTimeMillis() + ".jpg");
try {
OutputStream os = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
//释放缓存
os.flush();
os.close();
bitmap.recycle();
bitmap = null;
return imageFile.getAbsolutePath();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 删除缓存的图片
*
* @param context
* @return
*/
public static boolean cleanImageCache(Context context) {
File file = new File(context.getExternalCacheDir().getPath() + imageCacheFile);
if (file.exists()) {
return file.delete();
}
return true;
}
}
评论区