保存照片和视频到相册显示

照片和视频保存到本地的方法大致都是通过流的方式写入文件里面就可以达到保存到文件夹的目的,但是你保存到文件夹的资源却不一定能够在相册显示出来,只能翻看文件管理。

怎么能够将保存到本地的照片视频显示在系统相册中,最常用的方式是发送广播扫描的方式来通知系统扫描文件夹,但是这种方式经常不起作用,根本原因在于,向系统发送广播时系统只会去扫描系统资源的相册,如果你保存的文件夹是自己建立的,那么你发广播时系统是不会扫描到的。

解决这个问题,想要显示在相册需要将数据插入到ContentProvider中,因此对于非系统能够扫描到的相册我们使用手动插入的方式。

2. 保存到系统资源相册

系统相册指的的是CameraDCIM等等这些目录对应的相册,可能还有其他系统会自动扫描的相册,但是暂时没有去整理这些。

对于系统相册来说,只需要发送广播进行扫描即可,数据会自动添加到ContentProvider中,当然如果不发送广播,在手机重启或者过一段时间之后,扫描操作仍会开启,因此绝对绝对不可以自己去进行插入操作,否则相册中会出现两张相同的照片。

/**
 * 针对系统文夹只需要扫描,不用插入内容提供者,不然会重复
 *
 * @param context  上下文
 * @param filePath 文件路径
 */
private static void scanFile(Context context, String filePath) {
    if (!checkFile(filePath))
        return;
    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    intent.setData(Uri.fromFile(new File(filePath)));
    context.sendBroadcast(intent);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3. 保存到非系统资源相册

保存到非系统资源相册中时,我们就需要进行ContentProvider的插入更新,来达到可以在相册显示的目的。

3.1 初始化ContentValues公共字段

照片和视频是有一些公共字段,写一个初始化公共字段的方法,简化MediaStore字段的写入操作。

/**
 * 插入时初始化公共字段
 *
 * @param filePath 文件
 * @param time     ms
 * @return ContentValues
 */
private static ContentValues initCommonContentValues(String filePath, long time) {
    ContentValues values = new ContentValues();
    File saveFile = new File(filePath);
    long timeMillis = getTimeWrap(time);
    values.put(MediaStore.MediaColumns.TITLE, saveFile.getName());
    values.put(MediaStore.MediaColumns.DISPLAY_NAME, saveFile.getName());
    values.put(MediaStore.MediaColumns.DATE_MODIFIED, timeMillis);
    values.put(MediaStore.MediaColumns.DATE_ADDED, timeMillis);
    values.put(MediaStore.MediaColumns.DATA, saveFile.getAbsolutePath());
    values.put(MediaStore.MediaColumns.SIZE, saveFile.length());
    return values;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

3.2 插入照片资源

保存照片到本地,并通知相册显示,需要注意的时间的单位必须是ms

/**
 * 保存到照片到本地,并插入MediaStore以保证相册可以查看到
 * 这是更优化的方法,防止读取的照片获取不到宽高
 *
 * @param context    上下文
 * @param filePath   文件路径
 * @param createTime 创建时间 <=0时为当前时间 ms
 * @param width      宽度
 * @param height     高度
 */
public static void insertImageToMediaStore(Context context, String filePath,
                                           long createTime, int width, int height) {
    if (!checkFile(filePath))
        return;
    createTime = getTimeWrap(createTime);
    ContentValues values = initCommonContentValues(filePath, createTime);
    values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, createTime);
    values.put(MediaStore.Images.ImageColumns.ORIENTATION, 0);
    values.put(MediaStore.Images.ImageColumns.ORIENTATION, 0);
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
        if (width > 0) values.put(MediaStore.Images.ImageColumns.WIDTH, 0);
        if (height > 0) values.put(MediaStore.Images.ImageColumns.HEIGHT, 0);
    }
    values.put(MediaStore.MediaColumns.MIME_TYPE, getPhotoMimeType(filePath));
    context.getApplicationContext().getContentResolver()
            .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

3.3 插入视频资源

保存视频到本地,并通知相册显示,需要注意的时间的单位必须是ms

/**
 * 保存到视频到本地,并插入MediaStore以保证相册可以查看到
 * 这是更优化的方法,防止读取的视频获取不到宽高
 *
 * @param context    上下文
 * @param filePath   文件路径
 * @param createTime 创建时间 <=0时为当前时间 ms
 * @param duration   视频长度 ms
 * @param width      宽度
 * @param height     高度
 */
public static void insertVideoToMediaStore(Context context, String filePath, long createTime,
                                           int width, int height, long duration) {
    if (!checkFile(filePath))
        return;
    createTime = getTimeWrap(createTime);
    ContentValues values = initCommonContentValues(filePath, createTime);
    values.put(MediaStore.Video.VideoColumns.DATE_TAKEN, createTime);
    if (duration > 0)
        values.put(MediaStore.Video.VideoColumns.DURATION, duration);
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
        if (width > 0) values.put(MediaStore.Video.VideoColumns.WIDTH, width);
        if (height > 0) values.put(MediaStore.Video.VideoColumns.HEIGHT, height);
    }
    values.put(MediaStore.MediaColumns.MIME_TYPE, getVideoMimeType(filePath));
    context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

4. 注意

在应用过程中发现,vivo手机和魅族手机部分机型只支持在文件管理中查看视频,使用本文描述的方法添加后没有效果,用微信保存视频试了一下同样不能在相册中将视频显示出来,应该是手机的原因,特此声明。

5.源码

贴一下工具类源代码,多了一些辅助方法,比如获取mime_type的参数等方法。

/**
 * CreateAt : 2017/5/24
 * Describe : 相册更新通知帮助类
 * 创建时间单位ms
 * 视频时长单位ms
 *
 * @author chendong
 */
public class AlbumNotifyHelper {

    public static final String TAG = AlbumNotifyHelper.class.getSimpleName();

    ///////////////////////////////////////////////////////////////////////////
    // 下面是对外公开的重载的方法
    ///////////////////////////////////////////////////////////////////////////

    public static void notifyScanDcim(Context context, String filePath) {
        scanFile(context, filePath);
    }

    public static void insertVideoToMediaStore(Context context, String filePath, long dateTaken, long duration) {
        insertVideoToMediaStore(context, filePath, dateTaken, 0, 0, duration);
    }

    public static void insertVideoToMediaStore(Context context, VideoUtil.VideoInfo videoInfo) {
        insertVideoToMediaStore(context, videoInfo.originalVideoFilePath, videoInfo.dateTaken, videoInfo.width, videoInfo.height, videoInfo.duringTime);
    }

    public static void insertImageToMediaStore(Context context, String filePath, long createTime) {
        insertImageToMediaStore(context, filePath, createTime, 0, 0);
    }

    ///////////////////////////////////////////////////////////////////////////
    // 扫描系统相册核心方法
    ///////////////////////////////////////////////////////////////////////////

    /**
     * 针对系统文夹只需要扫描,不用插入内容提供者,不然会重复
     *
     * @param context  上下文
     * @param filePath 文件路径
     */
    public static void scanFile(Context context, String filePath) {
        if (!checkFile(filePath))
            return;
        Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        intent.setData(Uri.fromFile(new File(filePath)));
        context.sendBroadcast(intent);
    }

    ///////////////////////////////////////////////////////////////////////////
    // 非系统相册像MediaContent中插入数据,核心方法
    ///////////////////////////////////////////////////////////////////////////

    /**
     * 针对非系统文件夹下的文件,使用该方法
     * 插入时初始化公共字段
     *
     * @param filePath 文件
     * @param time     ms
     * @return ContentValues
     */
    private static ContentValues initCommonContentValues(String filePath, long time) {
        ContentValues values = new ContentValues();
        File saveFile = new File(filePath);
        long timeMillis = getTimeWrap(time);
        values.put(MediaStore.MediaColumns.TITLE, saveFile.getName());
        values.put(MediaStore.MediaColumns.DISPLAY_NAME, saveFile.getName());
        values.put(MediaStore.MediaColumns.DATE_MODIFIED, timeMillis);
        values.put(MediaStore.MediaColumns.DATE_ADDED, timeMillis);
        values.put(MediaStore.MediaColumns.DATA, saveFile.getAbsolutePath());
        values.put(MediaStore.MediaColumns.SIZE, saveFile.length());
        return values;
    }

    /**
     * 保存到照片到本地,并插入MediaStore以保证相册可以查看到,这是更优化的方法,防止读取的照片获取不到宽高
     *
     * @param context    上下文
     * @param filePath   文件路径
     * @param createTime 创建时间 <=0时为当前时间 ms
     * @param width      宽度
     * @param height     高度
     */
    public static void insertImageToMediaStore(Context context, String filePath, long createTime, int width, int height) {
        if (!checkFile(filePath))
            return;
        createTime = getTimeWrap(createTime);
        ContentValues values = initCommonContentValues(filePath, createTime);
        values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, createTime);
        values.put(MediaStore.Images.ImageColumns.ORIENTATION, 0);
        values.put(MediaStore.Images.ImageColumns.ORIENTATION, 0);
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
            if (width > 0) values.put(MediaStore.Images.ImageColumns.WIDTH, 0);
            if (height > 0) values.put(MediaStore.Images.ImageColumns.HEIGHT, 0);
        }
        values.put(MediaStore.MediaColumns.MIME_TYPE, getPhotoMimeType(filePath));
        context.getApplicationContext().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    }

    /**
     * 保存到视频到本地,并插入MediaStore以保证相册可以查看到,这是更优化的方法,防止读取的视频获取不到宽高
     *
     * @param context    上下文
     * @param filePath   文件路径
     * @param createTime 创建时间 <=0时为当前时间 ms
     * @param duration   视频长度 ms
     * @param width      宽度
     * @param height     高度
     */
    public static void insertVideoToMediaStore(Context context, String filePath, long createTime, int width, int height, long duration) {
        if (!checkFile(filePath))
            return;
        createTime = getTimeWrap(createTime);
        ContentValues values = initCommonContentValues(filePath, createTime);
        values.put(MediaStore.Video.VideoColumns.DATE_TAKEN, createTime);
        if (duration > 0)
            values.put(MediaStore.Video.VideoColumns.DURATION, duration);
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
            if (width > 0) values.put(MediaStore.Video.VideoColumns.WIDTH, width);
            if (height > 0) values.put(MediaStore.Video.VideoColumns.HEIGHT, height);
        }
        values.put(MediaStore.MediaColumns.MIME_TYPE, getVideoMimeType(filePath));
        context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
    }

    // 是不是系统相册
    private static boolean isSystemDcim(String path) {
        return path.toLowerCase().contains("dcim") || path.toLowerCase().contains("camera");
    }

    // 获取照片的mine_type
    private static String getPhotoMimeType(String path) {
        String lowerPath = path.toLowerCase();
        if (lowerPath.endsWith("jpg") || lowerPath.endsWith("jpeg")) {
            return "image/jpeg";
        } else if (lowerPath.endsWith("png")) {
            return "image/png";
        } else if (lowerPath.endsWith("gif")) {
            return "image/gif";
        }
        return "image/jpeg";
    }

    // 获取video的mine_type,暂时只支持mp4,3gp
    private static String getVideoMimeType(String path) {
        String lowerPath = path.toLowerCase();
        if (lowerPath.endsWith("mp4") || lowerPath.endsWith("mpeg4")) {
            return "video/mp4";
        } else if (lowerPath.endsWith("3gp")) {
            return "video/3gp";
        }
        return "video/mp4";
    }

    // 获得转化后的时间
    private static long getTimeWrap(long time) {
        if (time <= 0) {
            return System.currentTimeMillis();
        }
        return time;
    }

    // 检测文件存在
    private static boolean checkFile(String filePath) {
        boolean result = FileUtil.fileIsExist(filePath);
        Log.e(TAG, "文件不存在 path = " + filePath);
        return result;
    }
}
时间: 2024-12-28 01:34:07

保存照片和视频到相册显示的相关文章

iOS开发&gt;学无止境 - 保存照片到自己创建的相簿

在刚刚在线上一篇文章iOS开发之保存照片到系统相册(Photo Album),我们讲到了如何保持照片系统相册.还有其他保存的方法吗? 保存照片还可以用ALAssetsLibrary,ALAssetsLibrary提供了我们对iOS设备中的相片.视频的访问,是连接应用程序和相册之间访问的一个桥梁. 接下来,我们来详细讲解一下关于系统相册权限获取.保存照片.创建自己的相簿等等功能. 创建自己的相簿 这也是一种比较创建的作法,创建自己的相簿,然后把照片或者视频保存到自己的相簿中.相关代码如下: ALA

iOS开发之保存照片到系统相册(Photo Album)

iOS开发之保存照片到系统相册(Photo Album) 保存照片到系统相册这个功能很多社交类的APP都有的,今天我们简单讲解一下,如何将图片保存到系统相册(Photo Album). 创建UIImageView 创建UIImageView是为了将照片展示出来,我们是要把UIImage保存到系统相册(Photo Album): #define SCREEN [UIScreen mainScreen].bounds.size self.image = [UIImage imageNamed:@"i

iOS开发&gt;学无止境 - 保存照片到系统相册(Photo Album)

保存照片到系统相册这个功能很多社交类的APP都有的,今天我们简单讲解一下,如何将图片保存到系统相册(Photo Album). 创建UIImageView 创建UIImageView是为了将照片展示出来,我们是要把UIImage保存到系统相册(Photo Album): #define SCREEN [UIScreen mainScreen].bounds.size self.image = [UIImage imageNamed:@"iOSDevTip"]; UIImageView

保存视频到相册的相关代码

@implementation ALAssetsLibrary (ZHExpand) /**  *  创建本地相册  *  *  @param name                        相册名称  *  @param enumerateGroupsFailureBlock 遍历相册分组失败回调  *  @param hasGroup                    本地已经存在该相册,请重新命名  *  @param createSuccessedBlock        创

Android:仿QQ照片选择器(按相册分类显示,多选添加)

本例的目的是实现类似于QQ的照片选择功能.选择照片之后,使用类似于新浪微博 发微博 页面进行展示. 先上效果图:     本例中使用的主要技术: 1.使用ContentProvider读取SD卡所有图片信息. 2.对1中获取的图片,以图片所属的父文件夹进行分类(类似于QQ). 3.选择照片页面 与 选择相册页面 相互切换并且不走onCreate(切换十分流畅),同时设置页面切换动画以提升用户体验. 4.加载SD卡图片时使用LruCache,并设置初始压缩比例,减少内存占用. 5."正方形布局&q

iOS开发之保存照片到自己创建的相簿

iOS开发之保存照片到系统相册(Photo Album), 保存照片还可以用ALAssetsLibrary,ALAssetsLibrary提供了我们对iOS设备中的相片.视频的访问,是连接应用程序和相册之间访问的一个桥梁. 接下来,我们来详细讲解一下关于系统相册权限获取.保存照片.创建自己的相簿等等功能. 创建自己的相簿 这也是一种比较创建的作法,创建自己的相簿,然后把照片或者视频保存到自己的相簿中.相关代码如下: ALAssetsLibrary *library = [[ALAssetsLib

Window 下 VFW 视频采集与显示

引言 经过几天的努力终于将VFW视频采集与显示功能完整实现了,不得不说网上对这方面完整的详细讲解文章是在太少了.所以就要本人来好好总结一下让后来者不再像我一样折腾好久.在本文中我将详细讲解VFW视频采集过程的实现,以及采集后视频的显示方法. VFW简介 虽然这是篇技术博文,但是我觉得用一个东西,那么关于它的概述还是不能少,所以特从百度上copy了下VFW的概念描述,如果读者不想看可以直接去观看正文部分. VFW(Video for Windows)是Microsoft推出的关于数字视频的一个软件

保险箱Pro-加密保护您的照片、视频、账号、联系人、日记

保险箱Pro-加密保护您的照片.视频.账号.联系人.日记 下载地址:https://itunes.apple.com/cn/app/id680159199?mt=8 ***如果您遇到闪退问题(请不要删除闪退app,因为数据都在里面),请立即联系:[email protected]或qq:673368731.官方技术支持qq群:331210536 史上最好用, 最强大的隐私保护App,为您加密存储照片.视频.账号.日记.联系人.!? 保险箱Pro是怎么运作的? 第一, 作为一款保密应用, 您最关心

通过python获取苹果手机备份文件中的照片,视频等信息采集

前言:苹果手机用户通常会将手机备份到电脑上,而备份文件通常不会自动删除.在我们电脑取证,或者***到一台电脑后可以通过python脚本获取到备份文件中的一些隐私信息,比如照片.视频.相关软件中的一些账号,联系信息等等.但是我们进入到备份文件目录,会发现文件都没有后缀名,而且很乱.似乎没有什么用.我们看到的如下:备份目录(win7):C:\Users\你的用户名\AppData\Roaming\Apple Computer\MobileSync\Backup\ 在备份文件的根目录下有个Manife