哈喽,大家好,好久不见了,很久没有更新 Android 方面的技术文章了,最近在忙公司的 AR 类的新产品,其中涉及到本地图片和视频的选择和上传功能。至于为什么不用系统提供的图片和视频选择器,原因你懂的,系统提供的选择器只能通过 Intent 方式去获取,这意味着需要离开当前页面前往系统的媒体库,选择完毕后在onActivityResult 方法中拿到结果。这显然存在很多弊端:
- UI的定制化很差
- 需要离开当前页面,体验不好
- 不同机型可能会出现各种问题
- 系统选择器并不支持多选功能
其实,我们最希望的是拿到手机中的图片和视频数据,至于UI的绘制和交互细节都由我们自己来定制。你说你想用 ListView 或者 RecyclerView 来展示所有图片和视频,ok,当然可以,那是你的自由!让我们先来看一下最终实现的效果图吧:
不要直接一看效果图以为还是前往的另一个页面,那和其他图片选择器有什么分别?客官先别急,这里的效果图只是为了美观而已,反正数据给你了,想怎么安排UI就看你们设计喵了?~,比如可以这样:
看到这你可能会以为很复杂,其实不然,代码量很少,而且涉及到的核心知识点如:获取系统图片和视频数据、单选和多选功能,相信大家一看就明了。好了,喝口茶,且听我慢慢道来。
获取手机所有图片和视频数据
一般地,获取手机内部图片和视频数据有两种方式:通过遍历文件夹获取图片和视频资源,或者通过ContentResolver来获取。虽然第一种方式拿到的图片比较齐全,但文件遍历操作过于耗时,这里我推荐采用第二种方式。ContentResolver即内容解析器,可以对ContentProvider中的数据库进行增删改查操作,其中主要包含联系人、短信、相册、视频、音频等一系列数据。我们来看看具体获取系统图片数据实现代码吧:
/**
* <pre>
* @author moosphon (about me: <a>https://github.com/Moosphan<a/>)
* @date 2018/09/16
* @desc get all pictures of the phone.
* <pre/>
*/
fun getLocalPictures(mContext: Context?): List<ImageMediaEntity>? {
val images = ArrayList<ImageMediaEntity>()
val resolver = mContext?.contentResolver
var cursor: Cursor? = null
queryImageThumbnails(resolver!!, arrayOf(MediaStore.Images.Thumbnails.IMAGE_ID, MediaStore.Images.Thumbnails.DATA))
try {
cursor = resolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
arrayOf(MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.SIZE,
MediaStore.Images.ImageColumns.MIME_TYPE),
null, null, null)
return if (cursor == null || !cursor.moveToFirst()) {
null
} else {
do {
val picPath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA))
val id = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))
val size = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.SIZE))
val mimeType = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE))
val image = ImageMediaEntity.Builder(id, picPath)
.setMimeType(mimeType)
.setSize(size)
.setThumbnailPath(mThumbnailMap?.get(id))
.build()
images.add(image)
mThumbnailMap = null
}while (cursor.moveToNext())
return images
}
} finally {
if (cursor !