使用方法
保存当前view到相册 MediaStoreUtils.saveBitmap(activity,ConvertUtils.view2Bitmap(view"需要保存的图片"));
保存drawable资源图片到相册
Bitmap bitmap=BitmapFactory.decodeResource(resources,R.drawable.t1) MediaStoreUtils.saveBitmap(activity,bitmap);
1. MediaStore工具类
public class MediaStoreUtils {
//读取
public static void queryImages(@NotNull Activity activity) {
String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
//检查权限
if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{permission}, 10086);
return;
}
}
queryAllImages(activity);
}
private static ArrayList queryAllImages(Context context) {
Uri externalContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection;
Uri.Builder appendId = new Uri.Builder();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
projection = new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.RELATIVE_PATH};
} else {
projection = new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.DATA};
}
Cursor cursor = context.getContentResolver().query(externalContentUri, projection, null, null, null);
ArrayList<Uri> uris = new ArrayList<Uri>();
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
appendId = ContentUris.appendId(externalContentUri.buildUpon(), cursor.getLong(0));
if (appendId != null) {
uris.add(appendId.build());
Log.d("SMG", appendId.build().toString());
}
String string1 = cursor.getString(1);
Log.d("SMG", string1);
String string2 = cursor.getString(2);
Log.d("SMG", string2);
} while (cursor.moveToNext());
}
cursor.close();
}
return uris;
}
//保存
public static void saveImages(@NotNull Activity activity, @NotNull final Bitmap bitmap) {
String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
//检查权限
if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{permission}, 10086);
return;
}
}
try {
saveMedia(activity, bitmap, Environment.DIRECTORY_PICTURES, "ASUKA", "xxx.jpg", "image/JPEG", "");
} catch (IOException e) {
e.printStackTrace();
}
}
//type:Environment.DIRECTORY_PICTURES
private static void saveMedia(Context context, Bitmap bitmap, String dirType, String relativeDir, String filename, String mimeType, String description) throws IOException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
//首先保存
File saveDir = Environment.getExternalStoragePublicDirectory(dirType);
saveDir = new File(saveDir, relativeDir);
if (!saveDir.exists() && !saveDir.mkdirs()) {
try {
throw new Exception("create directory fail!");
} catch (Exception e) {
e.printStackTrace();
}
}
Log.d("SMG", saveDir.getAbsolutePath());
File outputFile = new File(saveDir, filename);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(outputFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
BufferedOutputStream bos = new BufferedOutputStream(fos);
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos);
bos.flush();
bos.close();
//把文件插入到系统图库(直接插入到Picture文件夹下)
// MediaStore.Images.Media.insertImage(
// context.contentResolver, outputFile.absolutePath, outputFile.name, ""
// )
//最后通知图库更新
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(outputFile)));
} else {
String path = EmptyUtils.isNotEmpty(relativeDir) ? Environment.DIRECTORY_PICTURES + File.separator + relativeDir : Environment.DIRECTORY_PICTURES;
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, filename);
contentValues.put(MediaStore.Images.Media.DESCRIPTION, description);
contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, path);
contentValues.put(MediaStore.Images.Media.MIME_TYPE, mimeType);
//contentValues.put(MediaStore.Images.Media.IS_PENDING,1)
Uri external = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Uri insertUri = context.getContentResolver().insert(external, contentValues);
OutputStream fos = (OutputStream) null;
if (insertUri != null) {
try {
fos = context.getContentResolver().openOutputStream(insertUri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
if (fos != null) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.flush();
fos.close();
}
}
}
/**
* Android Q以下版本,删除文件需要申请WRITE_EXTERNAL_STORAGE权限。通过MediaStore的DATA字段获得媒体文件的绝对路径,然后使用File相关API删除
* <p>
* Android Q以上版本,应用删除自己创建的媒体文件不需要用户授权。删除其他应用创建的媒体文件需要申请READ_EXTERNAL_STORAGE权限。
* 删除其他应用创建的媒体文件,还会抛出RecoverableSecurityException异常,在操作或删除公共目录的文件时,需要Catch该异常,由MediaProvider弹出弹框给用户选择是否允许应用修改或删除图片/视频/音频文件
*/
public static void deletePicture(@NotNull Activity activity, @NotNull Uri imageUri) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
String[] projection = new String[]{MediaStore.Images.Media.DATA};
Cursor cursor = activity.getContentResolver().query(imageUri, projection,
null, null, null);
if (cursor != null) {
int columnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
if (columnIndex > -1) {
File file = new File(cursor.getString(columnIndex));
file.delete();
}
}
if (cursor != null) {
cursor.close();
}
} else {
try {
activity.getContentResolver().delete(imageUri, null, null);
} catch (RecoverableSecurityException e1) {
//捕获 RecoverableSecurityException异常,发起请求
try {
ActivityCompat.startIntentSenderForResult(activity, e1.getUserAction().getActionIntent().getIntentSender(),
10086, null, 0, 0, 0, null);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
}
}
}
2. view2Bitmap 跟bitmap2Bytes转换工具类
public final class ConvertUtils {
/**
* 毫秒时间戳转合适时间长度
*
* @param millis 毫秒时间戳
* <p>小于等于0,返回null</p>
* @param precision 精度
* <ul>
* <li>precision = 0,返回null</li>
* <li>precision = 1,返回天</li>
* <li>precision = 2,返回天和小时</li>
* <li>precision = 3,返回天、小时和分钟</li>
* <li>precision = 4,返回天、小时、分钟和秒</li>
* <li>precision >= 5,返回天、小时、分钟、秒和毫秒</li>
* </ul>
* @return 合适时间长度
*/
@SuppressLint("DefaultLocale")
public static String millis2FitTimeSpan(long millis, int precision) {
if (millis <= 0 || precision <= 0) {
return null;
}
StringBuilder sb = new StringBuilder();
String[] units = {"天", "小时", "分钟", "秒", "毫秒"};
int[] unitLen = {86400000, 3600000, 60000, 1000, 1};
precision = Math.min(precision, 5);
for (int i = 0; i < precision; i++) {
if (millis >= unitLen[i]) {
long mode = millis / unitLen[i];
millis -= mode * unitLen[i];
sb.append(mode).append(units[i]);
}
}
return sb.toString();
}
/**
* bitmap转byteArr
*
* @param bitmap bitmap对象
* @param format 格式
* @return 字节数组
*/
public static byte[] bitmap2Bytes(final Bitmap bitmap, final Bitmap.CompressFormat format) {
if (bitmap == null) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
/**
* Bitmap.CompressFormat format 图像的压缩格式;
* int quality 图像压缩率,0-100。 0 压缩100%,100意味着不压缩;
* OutputStream stream 写入压缩数据的输出流;
*/
bitmap.compress(format, 100, baos);
return baos.toByteArray();
}
/**
* byteArr转bitmap
*
* @param bytes 字节数组
* @return bitmap
*/
public static Bitmap bytes2Bitmap(final byte[] bytes) {
return (bytes == null || bytes.length == 0) ? null : BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
/**
* drawable转bitmap
*
* @param drawable drawable对象
* @return bitmap
*/
public static Bitmap drawable2Bitmap(final Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if (bitmapDrawable.getBitmap() != null) {
return bitmapDrawable.getBitmap();
}
}
Bitmap bitmap;
if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
bitmap = Bitmap.createBitmap(1, 1,
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
/**
* bitmap转drawable
*
* @param bitmap bitmap对象
* @return drawable
*/
public static Drawable bitmap2Drawable(final Bitmap bitmap, Context context) {
return bitmap == null ? null : new BitmapDrawable(context.getResources(), bitmap);
}
/**
* drawable转byteArr
*
* @param drawable drawable对象
* @param format 格式
* @return 字节数组
*/
public static byte[] drawable2Bytes(final Drawable drawable, final Bitmap.CompressFormat format) {
return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable), format);
}
/**
* byteArr转drawable
*
* @param bytes 字节数组
* @return drawable
*/
public static Drawable bytes2Drawable(final byte[] bytes, Context context) {
return bytes == null ? null : bitmap2Drawable(bytes2Bitmap(bytes),context);
}
/**
* view转Bitmap
*
* @param view 视图
* @return bitmap
*/
public static Bitmap view2Bitmap(final View view) {
if (view == null) {
return null;
}
Bitmap bmp = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null) {
bgDrawable.draw(canvas);
} else {
canvas.drawColor(Color.WHITE);
}
view.draw(canvas);
// 缩小图片
Matrix matrix = new Matrix();
matrix.postScale(1.0f, 1.0f); //长和宽放大缩小的比例
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
return bmp;
}
public static Bitmap stringToBitmap(String string){
//将字符串转换成Bitmap类型
Bitmap bitmap=null;
try {
byte[]bitmapArray;
bitmapArray=Base64.decode(string, Base64.DEFAULT);
bitmap=BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
}