美文网首页
如何让图片在相册中展示 (将图片保存到系统相册中)

如何让图片在相册中展示 (将图片保存到系统相册中)

作者: 元亨利贞o | 来源:发表于2017-04-06 17:37 被阅读2423次

    一. 系统相册的数源其实来自系统媒体库, 即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<Boolean>() {
                @Override
                public void subscribe(FlowableEmitter<Boolean> 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<Boolean>() {
                        @Override
                        public void accept(@NonNull Boolean result) throws Exception {
                            //将下载的图片插入到系统相册, 并同步刷新系统相册(更新UI)
                            if(result) insertSystemAlbumAndRefresh(imageUrl);
    
                            //回调更新UI
                            if(downloadCallback != null) downloadCallback.onDownloadCompleted(result);
                        }
                    }, new Consumer<Throwable>() {
                        @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<Object>() {
                @Override
                public void subscribe(FlowableEmitter<Object> e) throws Exception {
                    File file = FileUtils.createFileFrom(imageUrl);
                    String imageUri = MediaStore.Images.Media.insertImage(ApplicationProvider.IMPL.getApp().getContentResolver(), file.getAbsolutePath(), file.getName(), "图片: " + file.getName());
                    Log.d("_stone_", "insertSystemAlbumAndRefresh-subscribe: imageUri=" + imageUri);
                    syncAlbum(imageUrl);
                }
            }, BackpressureStrategy.BUFFER)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe();
        }
    
        /**
         * 同步刷新系统相册
         * @param imageUrl
         */
        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);
            }
        }
    }
    

    调用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<Boolean>() {
            @Override
            public void subscribe(FlowableEmitter<Boolean> 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<Boolean>() {
            @Override
            public void accept(Boolean result) throws Exception {
                DevUtil.dd("addVideo2MediaStore() : " + (result ? "插入成功!" : "插入失败!") );
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                DevUtil.dd("addVideo2MediaStore() : " + "插入失败!");
            }
        });
    }
    

    相关文章

      网友评论

          本文标题:如何让图片在相册中展示 (将图片保存到系统相册中)

          本文链接:https://www.haomeiwen.com/subject/cfbxottx.html