序
此文承接上一篇文章,主要把后续传输图片的部分介绍一下。
其实传输图片除了直接注入 js 还有一个方案是通过 拦截 url 实现。
但是这既不灵活也不优雅,具体怎么实现在此就不多赘述了。
惯例,我不太喜欢写 java 代码,还是继续 kt 把,反正语法就一丢丢差别
安卓端代码
权限
由于 安卓 q 的权限变更,如果你是老老实实使用正常的权限的话,理论上不需要额外申请相册的写入权限,此外相册的写入权限只是为了方便图片是否写入成功,写 cache 目录是同理的。
相册保存
首先先非常简单的把写相册功能实现一下:
// 这里不使用复杂的方案了,直接 replace ,理论上是需要通过正则提取的
val buffer = Base64.decode(base64.replace("data:image/png;base64", ""), Base64.DEFAULT)
val bitmap = BitmapFactory.decodeByteArray(buffer, 0, buffer.size)
// 构建 query
val contentValue = ContentValues().apply {
// 这里可以改名字的,我就用时间代替了
put(MediaStore.MediaColumns.DISPLAY_NAME, System.currentTimeMillis().toString())
put(MediaStore.MediaColumns.MIME_TYPE, "image/png")
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
}
val resolver = this.contentResolver
val contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
// 这两是为了出错的时候会正常关闭流
var stream: OutputStream? = null
var uri: Uri? = null
try {
uri = resolver.insert(contentUri, contentValue)
?: throw IOException("fail to create record")
stream = resolver.openOutputStream(uri) ?: throw IOException("fail to get output stream");
if (!bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)) {
throw IOException("fail to save bitmap image");
}
} catch (e: IOException) {
// 如果 uri 生成了记得一定要删除
if (uri != null) {
resolver.delete(uri, null, null);
}
throw e;
} finally {
// 如果 stream 存在一定要记得关闭流
stream?.close()
}
从js端获取 base64 代码
然后没什么难度的传递参数:
this@MainActivity.saveFileIntoStorage(base64)
val alertDialog = AlertDialog.Builder(this@MainActivity)
alertDialog.setTitle("系统提示")
.setMessage("js传图成功")
.create()
alertDialog.show()
web 端
我们把代码整体修改一下,如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button id="btn">click</button>
<script>
function download(url) {
// 这里用了 fetch api 其他的可能需要做一个转换
// 也很简单通过 xhr 获取后 设置 xhr.responseType = "blob" 即可
// content 直接是 blob 的
// 如果实在不行可以用 canvas toBlob 解决,都不难
return fetch(url).then(function (response) {
return response.blob();
});
}
document.getElementById("btn").addEventListener("click", () => {
let url = "./test.png";
download(url)
.then(
(blob) =>
new Promise( (resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
// 转换成 base64
reader.readAsDataURL(blob);
})
)
.then( (base64) => {
window.webviewTest.onJsCallback(base64);
});
});
</script>
</body>
</html>
效果
然后看一下效果, 也 ok ,没啥问题。
本文标题:通过 webview 传输图片给 android
永久链接:https://iceprosurface.com/2020/05/05/2020/pass-image-to-android/
作者授权:本文由 icepro 原创编译并授权刊载发布。
版权声明:本文使用「署名-非商业性使用-相同方式共享 4.0 国际」创作共享协议,转载或使用请遵守署名协议。