Android:聊聊我使用过的图片、视频访问方式

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 30 天,点击查看活动详情

Android中访问图片和视频的方式有很多种,其中各有优缺点,下面就来聊聊我曾经使用过的文件访问方式吧。

Intent访问

此方式是打开手机所有文件,可以根据文件类型选择显示内容,使用简单方便:

val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
val mimetypes = arrayOf("image/*", "video/*")
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes)
startActivityForResult(intent, 100)

image.png

Matisse访问

这是知乎开源的一套UI框架,整体风格看起来非常舒服,使用也比较简单

//引入依赖
dependencies {
    implementation 'com.zhihu.android:matisse:$latest_version'
}

在Activity中使用

Matisse.from(MainActivity.this)
        .choose(MimeType.allOf())//选择类型  图片和视频或者全部
        .countable(true)
        .maxSelectable(9)//配置最大勾选数量
        .addFilter(new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K))//条件筛选
        .gridExpectedSize(getResources().getDimensionPixelSize(R.dimen.grid_expected_size))//文字大小
        .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
        .thumbnailScale(0.85f)
        .imageEngine(new GlideEngine())
        .showPreview(false) // 是否预览 默认是
        .forResult(REQUEST_CODE_CHOOSE);
        
//获取文件
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == REQUEST_CODE_CHOOSE && resultCode == RESULT_OK) {
        val mSelected = Matisse.obtainResult(data)
    }
}        

image.png

PictureSelector访问

PictureSelector提供了非常多的辅助功能,不仅可以选择图片视频还可以压缩图片和裁剪图片,甚至你可以自定义相机

dependencies {
  // PictureSelector 基础 (必须)
  implementation 'io.github.lucksiege:pictureselector:v3.10.7'
  // 图片压缩 (按需引入)
  implementation 'io.github.lucksiege:compress:v3.10.7'
  // 图片裁剪 (按需引入)
  implementation 'io.github.lucksiege:ucrop:v3.10.7'
  // 自定义相机 (按需引入)
  implementation 'io.github.lucksiege:camerax:v3.10.7'
}

其实它内部就提供了很多方法可以涵盖到绝大部分UI和功能:

PictureSelector.create(this)
    .openGallery(SelectMimeType.ofImage())//选择类型
    .setSelectorUIStyle(PictureSelectorStyle().apply {
        windowAnimationStyle = PictureWindowAnimationStyle() //入场动画
        selectMainStyle = SelectMainStyle()//配置选中的色调
        bottomBarStyle = BottomNavBarStyle()//配置底部内容色调
    })
    .setImageEngine(GlideEngine.createGlideEngine())//glide加载引擎
    .setCompressEngine(ImageFileCompressEngine())//压缩引擎
    .setSandboxFileEngine(MeSandboxFileEngine())//自定义沙箱文件处理
    .setSelectionMode(SelectModeConfig.MULTIPLE)//多选
    .isOriginalControl(true)//是否原图
    .isDisplayTimeAxis(true)//时间轴
    .isDisplayCamera(true)//打开拍照按钮
    .isPreviewFullScreenMode(true)//预览全屏
    .isPreviewZoomEffect(true)//预览缩放
    .isPreviewImage(true)//预览
    .isPreviewVideo(true)
    .isPreviewAudio(true)
    .setMaxSelectNum(5)//选择最大数量
    .setMaxVideoSelectNum(2)
    .setRecyclerAnimationMode(AnimationType.DEFAULT_ANIMATION)
    .forResult(object : OnResultCallbackListener<LocalMedia> {
    override fun onResult(result: ArrayList<LocalMedia>?) {//返回的文件
    }
    override fun onCancel() {
    }
    })

唯一不足的是没有视频压缩功能,它仅提供了图片压缩功能。

image.png

如此优秀的库我们肯定不愿因为这个缺陷就放弃吧,在网上搜索了解了一番,比较稳定优秀的视频压缩需要用到FFmpeg,但仅为了压缩就去使用它不可取。最终选择了一款VideoCompress,根据压缩视频宽高分辨率达到目的,分为三个档次:高、中、低

static final int COMPRESS_QUALITY_HIGH = 1;
static final int COMPRESS_QUALITY_MEDIUM = 2;
static final int COMPRESS_QUALITY_LOW = 3;
//path为文件源路径,destPath为压缩后路径
VideoCompress.compressVideoLow( path, destPath, object : CompressListener {
        override fun onStart() {//压缩开始
        }
        override fun onSuccess() {//压缩成功,此时的destPath则是压缩文件路径     
        }
        override fun onFail() {//压缩失败
        }
        override fun onProgress(percent: Float) {//压缩进度
        }
    })

总结

Intent方式最简单,无需接入其他库,但局限性大,没有可定制性,功能也少,只能简单获取图片和视频文件,不推荐使用。

Matisse方式是早期的一个库,UI看起来比较舒服,支持图片视频访问和拍照,但不支持图片视频压缩,头部的标题栏也无法定制,标题只有黑白两种主图,已经停止维护,但不保证当前市面上机型的适配能力。如没有很高的要求可以使用,接入成本也还好。

PictureSelector方式是目前使用的最优秀的库,重点是至今仍在维护。不仅包含了Matisse的所有功能,还可定制UI,配置色调也非常简单。还可以预览音视频,框架有很多辅助功能,图片裁剪、图片压缩、自定义相机等,文件的返回也可直接在回调中获取。由于还在维护,所以当下市场手机的适配也是没后顾之忧的。唯一不足是没有视频等文件的压缩功能,但上文中我们已经补充了这块的辅助方案,所以值得推荐。

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 30 天,点击查看活动详情