首页 > 系统 > Android > 正文

AndroidQ 沙箱适配多媒体文件(小结)

2020-07-28 14:02:20
字体:
来源:转载
供稿:网友

综述

所有内容的访问变化见下图:

外部媒体文件的扫描,读取和写入

最容易被踩坑的应该是,对外部媒体文件,照片,视频,图片的读取或写入。

扫描

首先是扫描。扫描依然是使用 query MediaStore 的方式。一句话介绍 MediaStore,MediaStore 就是Android系统中的一个多媒体数据库。代码如下图所示,以搜索本地视频为例子:

protected List<VideoInfo> doInBackground(Void... params) {  mContentResolver = context.getContentResolver();  String[] mediaColumns = { MediaStore.Video.Media._ID, MediaStore.Video.Media.DATA,      MediaStore.Video.Media.TITLE, MediaStore.Video.Media.MIME_TYPE,      MediaStore.Video.Media.DISPLAY_NAME, MediaStore.Video.Media.SIZE,      MediaStore.Video.Media.DATE_ADDED, MediaStore.Video.Media.DURATION,      MediaStore.Video.Media.WIDTH, MediaStore.Video.Media.HEIGHT };  Cursor mCursor = mContentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, mediaColumns,      null, null, MediaStore.Video.Media.DATE_ADDED);  if (mCursor == null) {    return null;  }  // 注意,DATA 数据在 Android Q 以前代表了文件的路径,但在 Android Q上该路径无法被访问,因此没有意义。  ixData = mCursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);  ixMime = mCursor.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE);  // ID 是在 Android Q 上读取文件的关键字段  ixId = mCursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);  ixSize = mCursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE);  ixTitle = mCursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE);  allImages = new ArrayList<VideoInfo>();  mTotalVideoCount = 0;  mCursor.moveToLast();    while (mCursor.moveToPrevious()) {    if (addVideo(mCursor) == 0) {      continue;    } else if (addVideo(mCursor) == 1) {      break;    }  }  mCursor.close();    return allImages;}

既然 data 不可用,就需要知晓 id 的使用方式,首先是使用 id 拼装出 content uri ,如下所示:

public getRealPath(String id) {  return MediaStore.Video.Media.EXTERNAL_CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).build().toString();}

Image 同理换成 MediaStore.Images。

读取和写入

其次,是读取 content uri。这里需要注意 File file = new File(contentUri); 是无法获取到文件的。file.exist() 为 false。

那么就产生两个问题:1. 如何确定 ContentUri 形式的文件存在 2. 如何读取或写入文件。

首先,对于 Content Uri 的读取,必须借助于 ContentResolver。

其次,对于 1,没有找到 Google 文档中提供比较容易的API,只能采用打开 FileDescriptor 是否成功的形式,代码如下所示:

public boolean isContentUriExists(Context context, Uri uri) {  if (null == context) {    return false;  }  ContentResolver cr = context.getContentResolver();  try {    AssetFileDescriptor afd = cr.openAssetFileDescriptor(uri, "r");    if (null == afd) {      iterator.remove();    } else {      try {        afd.close();      } catch (IOException e) {      }    }  } catch (FileNotFoundException e) {    return false;  }  return true;}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表