Android图片选择,jsb调用图片选择及裁剪压缩(含demo)

前言

最近有人来跟我要android的图片选择demo,而且需要将选择结果回调给web.虽然这个功能在好久以前做过,但是在这次重写的时候,发现很多东西都不太一样了,例如以前使用的图片选择框架PhotoPicker现在没有维护的,推荐了一个知乎的图片选择Matisse.

先说说传给web的方案,demo中由于没有服务器交互,所以回将选择好的图片转换成base64字符串,通过jsb传给web,这种方案在一些小图选择的情况下非常常见,但也有一定的弊端,这个在最后就给出修改建议.

demo工程:https://github.com/lewis-v/ImageSelect

选择图片

manifest中添加

<activity
            android:name="com.yalantis.ucrop.UCropActivity"
            android:screenOrientation="portrait"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.lewis.imageselect"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths"/>
        </provider>

res目录中添加xml目录,创建文件filepaths.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path
            name="my_images"
            path="Pictures"/>
    </paths>
</resources>

activity中的初始化操作

private val imageViewModel by lazy {
    ViewModelProvider(
        this,
        ViewModelProvider.AndroidViewModelFactory.getInstance(application)
    ).get(ImageViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
    imageViewModel.imageErrorLiveData.observe(this, Observer {
        Toast.makeText(this, it, Toast.LENGTH_SHORT).show()
    })
    imageViewModel.imageSelectResultViewModel.observe(this, Observer {
        //图片选择结果
        Toast.makeText(this, "select success ${it.size}", Toast.LENGTH_SHORT).show()
    })
}

//权限处理
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (permissions.isNotEmpty()) {
        imageViewModel.selectImage(this)
    }
}
//选择回调
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    imageViewModel.onResult(this, requestCode, resultCode, data)
}

选择图片调用

if (PermissionUtil.checkAllPermission(this)) {
    //选择一张图片,不裁剪
    imageViewModel.selectImage(this, 1, null, ImageCompressionInfo())
}
if (PermissionUtil.checkAllPermission(this)) {
    //选择1张图片,裁剪
    imageViewModel.selectImage(this, 1, ImageCropInfo(), ImageCompressionInfo())
}

到此,图片选择的初始化和调用就完成的,具体的实现在ImageViewModel中.

回调给web

ImageJsbModul类中提供了jsb的方法调用
初始化

override fun onCreate(savedInstanceState: Bundle?) {
	imageJsbModul = ImageJsbModul(this, web)
	webView.addJavascriptInterface(imageJsbModul, "ImageSelect")//将jsb方法加入到js中
}

override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (permissions.isNotEmpty()) {
        imageJsbModul.onGetPermission()
    }
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    imageViewModel.onResult(this, requestCode, resultCode, data)
}

网页调用图片选择的方法,在asset的js_webView.html有示例

window.ImageSelect.selectImage(num, '{"ratio":{"x":16.0,"y":9.0}}',true,"callBack");
//其中第一个参数num为选择图片数量,
//第二个参数为裁剪的配置(支持裁剪比例和大小)
//第三个参数为是否压缩
//第四个参数是选择结果的回调方法

最后

图片选择到这里结束啦,其实也没什么复杂的,就只是将各种框架结合在一起封装一下就完事了(具体实现可见工程demo源码, 主要的实现在ImageJsbModul和ImageViewModel中),但是这里也有一些细节是没有考虑的,例如在不保留活动下,选择完图片回来是否有问题等

建议

jsb的回调方式是将图片转成base64的形式,这里最好不要这样做,因为文件转成base64之后会很大,这里会占用很多内存,当然如果只是一张小头像问题到不是很大,最好的做法是将选择好的图片上传到服务器,将图片链接传给web.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章