Android笔记:AlbumSaver图片视频保存工具类

Posted MichaelX_Blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android笔记:AlbumSaver图片视频保存工具类相关的知识,希望对你有一定的参考价值。

背景

android中,有时需要操作生成一些图片或者视频,但不是你生成保存了就可以的,如何让生成的图片或者视频文件让其他app应用或者自身及时检索到,也是需要考虑的一个问题,下面这段代码是摘自某sdk demo的源码,刷新媒体数据库的方式让其他app可以方便的读取到刚生成的图片或者视频文件,兼容各个Android版本。

代码块AlbumSaver

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 用于将视频保存到本地相册
 */
public class AlbumSaver 

    private static final String TAG = "AlbumSaver";
    public static final String VOLUME_EXTERNAL_PRIMARY = "external_primary";
    private static final String IS_PENDING = "is_pending";
    private static AlbumSaver sInstance;
    private final ContentResolver mContentResolver;
    private final Context mContext;
    private String mVideoOutputPath;
    private long mVideoDuration;
    private String mCoverImagePath;

    public static AlbumSaver getInstance(@NonNull Context context) 
        if (sInstance == null) 
            sInstance = new AlbumSaver(context);
        
        return sInstance;
    

    private AlbumSaver(@NonNull Context context) 
        mContext = context.getApplicationContext();
        mContentResolver = context.getApplicationContext().getContentResolver();
    

    /**
     * 设置保存视频的信息
     *
     * @param videoPath 视频路径
     * @param duration  视频时长
     * @param coverPath 封面路径
     */
    public void setOutputProfile(String videoPath, long duration, String coverPath) 
        mVideoOutputPath = videoPath;
        mVideoDuration = duration;
        mCoverImagePath = coverPath;
    

    /**
     * 插入到本地相册
     */
    public void saveVideoToDCIM() 
        if (Build.VERSION.SDK_INT >= 29) 
            saveVideoToDCIMOnAndroid10();
         else 
            saveVideoToDCIMBelowAndroid10();
        
    

    private void saveVideoToDCIMBelowAndroid10() 
        File file = new File(mVideoOutputPath);
        if (file.exists()) 
            try 
                ContentValues values = initCommonContentValues(file);
                values.put(MediaStore.Video.VideoColumns.DATE_TAKEN, System.currentTimeMillis());
                values.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");
                values.put(MediaStore.Video.VideoColumns.DURATION, mVideoDuration);
                mContext.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);

                if (mCoverImagePath != null) 
                    insertVideoThumb(file.getPath(), mCoverImagePath);
                
                ToastUtil.toastShortMessage("视频已保存到手机相册");
             catch (Exception e) 
                e.printStackTrace();
            
         else 
            Log.d(TAG, "file :" + mVideoOutputPath + " is not exists");
        
    

    /**
     * Android 10(Q) 保存视频文件到本地的方法
     */
    private void saveVideoToDCIMOnAndroid10() 
        File file = new File(mVideoOutputPath);
        if (file.exists()) 
            ContentValues values = new ContentValues();
            long currentTimeInSeconds = System.currentTimeMillis();
            values.put(MediaStore.MediaColumns.TITLE, file.getName());
            values.put(MediaStore.MediaColumns.DISPLAY_NAME, file.getName());
            values.put(MediaStore.MediaColumns.DATE_MODIFIED, currentTimeInSeconds);
            values.put(MediaStore.MediaColumns.DATE_ADDED, currentTimeInSeconds);
            values.put(MediaStore.MediaColumns.SIZE, file.length());
            values.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");
            // 时长
            values.put(MediaStore.Video.VideoColumns.DURATION, mVideoDuration);
            values.put(MediaStore.Video.VideoColumns.DATE_TAKEN, System.currentTimeMillis());
            // Android 10 插入到图库标志位
            values.put(IS_PENDING, 1);

            Uri collection = MediaStore.Video.Media.getContentUri(VOLUME_EXTERNAL_PRIMARY);
            Uri item = mContext.getContentResolver().insert(collection, values);
            ParcelFileDescriptor pfd = null;
            FileOutputStream fos = null;
            FileInputStream fis = null;
            try 
                pfd = mContext.getContentResolver().openFileDescriptor(item, "w");
                // Write data into the pending image.
                fos = new FileOutputStream(pfd.getFileDescriptor());
                fis = new FileInputStream(file);
                byte[] data = new byte[1024];
                int length = -1;
                while ((length = fis.read(data)) != -1) 
                    fos.write(data, 0, length);
                
                fos.flush();
             catch (IOException e) 
                e.printStackTrace();
             finally 
                if (pfd != null) 
                    try 
                        pfd.close();
                     catch (IOException e) 
                        e.printStackTrace();
                    
                
                if (fos != null) 
                    try 
                        fos.close();
                     catch (IOException e) 
                        e.printStackTrace();
                    
                
                if (fis != null) 
                    try 
                        fos.close();
                     catch (IOException e) 
                        e.printStackTrace();
                    
                
            
            // 插入成功后,更新状态,让其他 app 可以看到新的视频
            values.clear();
            values.put(IS_PENDING, 0);
            mContext.getContentResolver().update(item, values, null, null);

            ToastUtil.toastShortMessage("视频已保存到手机相册");
         else 
            Log.d(TAG, "file :" + mVideoOutputPath + " is not exists");
        
    

    @NonNull
    private ContentValues initCommonContentValues(@NonNull File saveFile) 
        ContentValues values = new ContentValues();
        long currentTimeInSeconds = System.currentTimeMillis();
        values.put(MediaStore.MediaColumns.TITLE, saveFile.getName());
        values.put(MediaStore.MediaColumns.DISPLAY_NAME, saveFile.getName());
        values.put(MediaStore.MediaColumns.DATE_MODIFIED, currentTimeInSeconds);
        values.put(MediaStore.MediaColumns.DATE_ADDED, currentTimeInSeconds);
        values.put(MediaStore.MediaColumns.DATA, saveFile.getAbsolutePath());
        values.put(MediaStore.MediaColumns.SIZE, saveFile.length());
        return values;
    

    /**
     * 插入视频缩略图
     *
     * @param videoPath
     * @param coverPath
     */
    private void insertVideoThumb(String videoPath, String coverPath) 
        //以下是查询上面插入的数据库Video的id(用于绑定缩略图)
        //根据路径查询
        Cursor cursor = mContentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
                new String[]MediaStore.Video.Thumbnails._ID,//返回id列表
                String.format("%s = ?", MediaStore.Video.Thumbnails.DATA), //根据路径查询数据库
                new String[]videoPath, null);
        if (cursor != null) 
            if (cursor.moveToFirst()) 
                String videoId = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Thumbnails._ID));
                //查询到了Video的id
                ContentValues thumbValues = new ContentValues();
                thumbValues.put(MediaStore.Video.Thumbnails.DATA, coverPath);//缩略图路径
                thumbValues.put(MediaStore.Video.Thumbnails.VIDEO_ID, videoId);//video的id 用于绑定
                //Video的kind一般为1
                thumbValues.put(MediaStore.Video.Thumbnails.KIND, MediaStore.Video.Thumbnails.MINI_KIND);
                //只返回图片大小信息,不返回图片具体内容
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                Bitmap bitmap = BitmapFactory.decodeFile(coverPath, options);
                if (bitmap != null) 
                    thumbValues.put(MediaStore.Video.Thumbnails.WIDTH, bitmap.getWidth());//缩略图宽度
                    thumbValues.put(MediaStore.Video.Thumbnails.HEIGHT, bitmap.getHeight());//缩略图高度
                    if (!bitmap.isRecycled()) 
                        bitmap.recycle();
                    
                
                mContentResolver.insert(MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI, thumbValues);//缩略图数据库
            
            cursor.close();
        
    

结语

以上就是保存视频图片后刷新Android媒体数据的代码了,代码摘自腾讯某sdk demo,AlbumSaver工具类可以方便其他app及时读取到最新保存的图片视频。本来准备存gist的,网络挂了,供大家参考吧。

以上是关于Android笔记:AlbumSaver图片视频保存工具类的主要内容,如果未能解决你的问题,请参考以下文章

Android学习笔记进阶20之得到图片的缩略图

Android学习笔记进阶20 之得到图片的缩略图

【基础笔记】Android Studio拍照、选择相册(第三方框架)

android ndk之opencv+MediaCodec硬编解码来处理视频动态时间水印

android ndk之opencv+MediaCodec硬编解码来处理视频动态时间水印

【Android笔记】Android 9.0 SD卡读写权限问题