本文主要介绍保存图片到相册的几种方式。其本质上并没有把图片保存到相册中,实际上是保存在SD卡下自定义的文件夹中,目的只是让QQ
和微信
在选择照片的时候立刻显示,注:其实QQ
和微信
也是这样做的。
方式1-扫描文件通知相册更新
// 通知相册更新
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(file);
intent.setData(uri);
context.sendBroadcast(intent);
方式1-错误操作
MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), "name", "description");
// 通知相册更新
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(file);
intent.setData(uri);
context.sendBroadcast(intent);
对比 方式1 和 错误方式 ,我们可以发现其实就是多了一行insertImage
的代码,然后就不能被QQ
和微信
立刻识别了,好伤心~~
这里我稍微研究了一下,然而没有发现本质原因,不过做了以下猜测,有兴趣的可以自行研究源码。
因为在使用ACTION_MEDIA_SCANNER_SCAN_FILE
方式通知相册更新时,也需要执行类似insertImage
方法内部的某些操作,可能和ContentProvider
相关的数据库有关,所以如果你先执行了insertImage
方法,那么它在接收到这个ACTION_MEDIA_SCANNER_SCAN_FILE
广播的时候,做了如下判断:如果已经执行了insertImage
方法,那么return;
,所以不会执行再通知相册更新
了。
方式2-完整操作
// 插入file数据到相册
ContentValues values = new ContentValues(9);
values.put(MediaStore.Images.Media.TITLE, "Camera");
values.put(MediaStore.Images.Media.DISPLAY_NAME, filename);
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.ORIENTATION, 0);
values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
values.put(MediaStore.Images.Media.SIZE, file.length());
Uri uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
// 通知相册更新
context.sendBroadcast(new Intent("com.android.camera.NEW_PICTURE", uri));
方式2-简单操作
// 插入file数据到相册
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
Uri uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
// 通知相册更新
context.sendBroadcast(new Intent("com.android.camera.NEW_PICTURE", uri));
总结
对于Google
和百度
出来的Android保存图片到相册
表示无奈,90%以上都是一样的,这个时候如果我们还是依靠搜索
,消耗的成本是很大的,如果你能够从源码
入手,可能就会给你提供一些思路,例如:上述所说的方式2
就是从insertImage
方法中得出的,源码如下:
/**
* Insert an image and create a thumbnail for it.
*
* @param cr The content resolver to use
* @param source The stream to use for the image
* @param title The name of the image
* @param description The description of the image
* @return The URL to the newly created image, or <code>null</code> if the image failed to be stored
* for any reason.
*/
public static final String insertImage(ContentResolver cr, Bitmap source,
String title, String description) {
ContentValues values = new ContentValues();
values.put(Images.Media.TITLE, title);
values.put(Images.Media.DESCRIPTION, description);
values.put(Images.Media.MIME_TYPE, "image/jpeg");
Uri url = null;
String stringUrl = null; /* value to be returned */
try {
url = cr.insert(EXTERNAL_CONTENT_URI, values);
if (source != null) {
OutputStream imageOut = cr.openOutputStream(url);
try {
source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);
} finally {
imageOut.close();
}
long id = ContentUris.parseId(url);
// Wait until MINI_KIND thumbnail is generated.
Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id,
Images.Thumbnails.MINI_KIND, null);
// This is for backward compatibility.
Bitmap microThumb = StoreThumbnail(cr, miniThumb, id, 50F, 50F,
Images.Thumbnails.MICRO_KIND);
} else {
Log.e(TAG, "Failed to create thumbnail, removing original");
cr.delete(url, null, null);
url = null;
}
} catch (Exception e) {
Log.e(TAG, "Failed to insert image", e);
if (url != null) {
cr.delete(url, null, null);
url = null;
}
}
if (url != null) {
stringUrl = url.toString();
}
return stringUrl;
}