ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【Android】从共享存储访问媒体文件

2021-03-13 23:33:33  阅读:299  来源: 互联网

标签:存储 String Media 媒体文件 共享 cursor Video Android MediaStore


Android为了提供更丰富的用户体验,许多应用允许用户贡献和访问外部存储卷上可用的媒体。 媒体存储(media store) 框架为媒体集合提供了一个优化的索引,它允许更容易地检索和更新这些媒体文件。即使应用程序被卸载了,这些文件仍然保留在用户的设备上。
该系统自动扫描外部存储卷,并将媒体文件添加到以下明确定义的集合中:

  • 图片,包括照片和截图,存储在MediaStore.Images
  • 视频,存储在MediaStore.Video
  • 音频文件,存储在MediaStore.Audio
  • 下载的文件,存储在MediaStore.Downloads。 只在运行Android 10(API 级别29)及以上的设备上可用。

媒体存储还包括一个名为MediaStore.Files的集合。它的内容取决于应用是否使用分区存储。

  • 如果启用了分区存储,该集合将只显示应用创建的照片、视频和音频文件。
  • 如果分区存储不可用或未使用,则集合将显示所有类型的媒体文件。

1. 请求必要的权限

1.1. 存储权限

访问应用的媒体文件的权限模型取决于应用是否使用分区存储。如果应用想要访问MediaStore.Downloads集合中的并非自己创建文件,则必须使用存储访问框架。

1.2. 媒体位置权限

如果应用使用分区存储,为了让应用从照片中检索未编辑的Exif元数据,需要在应用的清单中声明ACCESS_MEDIA_LOCATION权限,然后在运行时请求这个权限。

2. 查询媒体集合

要查找满足一组特定条件(如持续时间为5分钟或更长)的媒体,请使用类似于SQL的选择语句,如下面的代码片段所示:

// Container for information about each video.
class Video {
    private final Uri uri;
    private final String name;
    private final int duration;
    private final int size;

    public Video(Uri uri, String name, int duration, int size) {
        this.uri = uri;
        this.name = name;
        this.duration = duration;
        this.size = size;
    }
}
List<Video> videoList = new ArrayList<Video>();

String[] projection = new String[] {
    MediaStore.Video.Media._ID,
    MediaStore.Video.Media.DISPLAY_NAME,
    MediaStore.Video.Media.DURATION,
    MediaStore.Video.Media.SIZE
};
String selection = MediaStore.Video.Media.DURATION +
        " >= ?";
String[] selectionArgs = new String[] {
    String.valueOf(TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES));
};
String sortOrder = MediaStore.Video.Media.DISPLAY_NAME + " ASC";

try (Cursor cursor = getApplicationContext().getContentResolver().query(
    MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
    projection,
    selection,
    selectionArgs,
    sortOrder
)) {
    // Cache column indices.
    int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
    int nameColumn =
            cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);
    int durationColumn =
            cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION);
    int sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE);

    while (cursor.moveToNext()) {
        // Get values of columns for a given video.
        long id = cursor.getLong(idColumn);
        String name = cursor.getString(nameColumn);
        int duration = cursor.getInt(durationColumn);
        int size = cursor.getInt(sizeColumn);

        Uri contentUri = ContentUris.withAppendedId(
                MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);

        // Stores column values and the contentUri in a local object
        // that represents the media file.
        videoList.add(new Video(contentUri, name, duration, size));
    }
}

在应用中执行这样的查询时,需记住以下几点:

  • 在工作线程中调用query()方法。
  • 缓存列索引,这样就不需要每次处理查询结果中的一行时调用getColumnIndexOrThrow()
  • 将ID附加到内容URI,如代码片段所示。
  • 运行Android 10及更高版本的设备需使用在MediaStoreAPI中定义的列名。 如果应用中的依赖库需要API中未定义的列名(例如“MimeType”),使用CursorWrapper在应用进程中动态转换列名。

3. 加载文件缩略图

要加载给定媒体文件的缩略图,使用loadThumbnail()并传递想要加载的缩略图大小,如下面的代码片段所示:

// Load thumbnail of a specific media item.
Bitmap thumbnail =
        getApplicationContext().getContentResolver().loadThumbnail(
        content-uri, new Size(640, 480), null);

4. 打开一个媒体文件

用于打开媒体文件的特定逻辑取决于媒体内容最好表示为文件描述符还是文件流:

4.1. 文件描述符

// Open a specific media item using ParcelFileDescriptor.
ContentResolver resolver = getApplicationContext()
        .getContentResolver();

// "rw" for read-and-write;
// "rwt" for truncating or overwriting existing file contents.
String readOnlyMode = "r";
try (ParcelFileDescriptor pfd =
        resolver.openFileDescriptor(content-uri, readOnlyMode)) {
    // Perform operations on "pfd".
} catch (IOException e) {
    e.printStackTrace();
}

4.2. 文件流

// Open a specific media item using InputStream.
ContentResolver resolver = getApplicationContext()
        .getContentResolver();
try (InputStream stream = resolver.openInputStream(content-uri)) {
    // Perform operations on "stream".
}

5. (待续……)

标签:存储,String,Media,媒体文件,共享,cursor,Video,Android,MediaStore
来源: https://blog.csdn.net/Alen_Sun/article/details/104478965

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有