一. 系统相册的数源其实来自系统媒体库, 即android.provider.MediaStore
. 既然如此, 只需要将图片数据插入到系统媒体库就行啦 !
二. 系统图库相关API
MediaStore.Images.Media.insertImage() //将图信息片插入到系统相册中
MediaStore.Images.Media.query() //查询系统相册
MediaStore.Images.Media.getBitmap() //从系统相册中获取图片
利用MediaStore.Images.Media.insertImage()
方法把图片数据插入到系统相册中, 上代码:
下载网络图片, 并保存到系统相册中 AlbumManager.java
public class AlbumManager {
/**
* 下载图片
* @param imageUrl
* @param downloadCallback
*/
public static void download(final String imageUrl, final DownloadCallback downloadCallback) {
Flowable.create(new FlowableOnSubscribe() {
@Override
public void subscribe(FlowableEmitter e) throws Exception {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(imageUrl).build();
Call call = client.newCall(request);
Response response = call.execute();
if(response != null && response.body() != null) {
BufferedSink sink = null;
try {
sink = Okio.buffer(Okio.sink(FileUtils.createFileFrom(imageUrl)));
sink.write(response.body().bytes());
e.onNext(true);
} catch (Exception exception) {
Log.e("_stone_", "AlbumManager-download-subscribe(): " + exception.getMessage());
e.onNext(false);
} finally {
if(sink != null) sink.close();
}
} else {
e.onNext(false);
}
}
}, BackpressureStrategy.BUFFER)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer() {
@Override
public void accept(@NonNull Boolean result) throws Exception {
//将下载的图片插入到系统相册, 并同步刷新系统相册(更新UI)
if(result) insertSystemAlbumAndRefresh(imageUrl);
//回调更新UI
if(downloadCallback != null) downloadCallback.onDownloadCompleted(result);
}
}, new Consumer() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
Log.d("_stone_", "AlbumManager-download-OnError-accept: " + throwable.getMessage());
if(downloadCallback != null) downloadCallback.onDownloadCompleted(false);
}
});
}
/**
* 插入到系统相册, 并刷新系统相册
* @param imageUrl
*/
private static void insertSystemAlbumAndRefresh(final String imageUrl) {
Flowable.create(new FlowableOnSubscribe
调用MediaStore.Images.Media.insertImage()
方法保持图片信息到系统相册后, 打开系统相册APP就可以看到刚才保存的图片了; 为了保险起见, 可以同步一下系统相册, 即下面这段代码:
private static void syncAlbum(String imageUrl) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
final Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
final Uri contentUri = Uri.fromFile(FileUtils.createFileFrom(imageUrl).getAbsoluteFile());
scanIntent.setData(contentUri);
ApplicationProvider.IMPL.getApp().sendBroadcast(scanIntent);
} else {
//4.4开始不允许发送"Intent.ACTION_MEDIA_MOUNTED"广播, 否则会出现: Permission Denial: not allowed to send broadcast android.intent.action.MEDIA_MOUNTED from pid=15410, uid=10135
final Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()));
ApplicationProvider.IMPL.getApp().sendBroadcast(intent);
}
}
}
代码已经上传到GitHub SaveImage2SystemAlbum, 如有不妥之处, 欢迎指正 !
@@@@@@@@@@@@@@@@@@@@@@@@@
更新(2017-04-07)
如果你调用系统相机拍摄视频, 而不把视频加入到媒体库中, 视频同样也是不会在系统相册中展示的. 因此拍摄完视频后需要将拍摄的视频加入到系统媒体库中.
调用系统相机拍摄视频 并 将拍摄的视频加入到系统媒体库中 (这样就可以在系统相册中看到你拍摄的视频啦):
//调用系统相机拍摄视频
private void captureVideo() {
// 激活系统的照相机进行录像
Intent intent = new Intent();
intent.setAction("android.media.action.VIDEO_CAPTURE");
intent.addCategory("android.intent.category.DEFAULT");
// 保存录像到指定的路径
videoFile = new File(videoFileName + ".3gp");
if (Build.VERSION.SDK_INT >= 24) { //判断版本是否在7.0以上
mUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", videoFile);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
mUri = Uri.fromFile(videoFile);
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, mUri);
startActivityForResult(intent, REQUEST_CAMERA);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CAMERA && resultCode == RESULT_OK) {
addVideo2MediaStore(videoFile);
}
}
//将视频加入到系统媒体库中
private void addVideo2MediaStore(File videoFile) {
//此处需要rxjava2的支持
Flowable.create(new FlowableOnSubscribe() {
@Override
public void subscribe(FlowableEmitter e) throws Exception {
try {
// 将视频加入到媒体库
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Video.Media.DATA, videoFile.getAbsolutePath());
contentValues.put(MediaStore.Video.Media.TITLE, videoFile.getName());
contentValues.put(MediaStore.Video.Media.DISPLAY_NAME, videoFile.getName());
Uri uri = getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);
DevUtil.dd("video uri: " + uri.toString());
e.onNext(true);
e.onComplete();
} catch(Exception exception) {
e.onNext(false);
e.onComplete();
}
}
}, BackpressureStrategy.BUFFER)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer() {
@Override
public void accept(Boolean result) throws Exception {
DevUtil.dd("addVideo2MediaStore() : " + (result ? "插入成功!" : "插入失败!") );
}
}, new Consumer() {
@Override
public void accept(Throwable throwable) throws Exception {
DevUtil.dd("addVideo2MediaStore() : " + "插入失败!");
}
});
}