Android 与 JS 交互数据上限(Base64图片传输问题)

webview.loadUrl

在 Android 给 JS 传 Base64 格式的图片时

报错 Refusing to load URL as it exceeds 2097152 characters
在这里插入图片描述2097152 字节 / 1024 / 1024 = 2 兆,这说明调用 loadUrl,最多只能传 2M 的内容

Base64是将原文按照每 3 个字节一组分开,这个 3 字节组中的每一组将被按照位分解成 4 个部分,每个部分 6 个位,在这 4 个部分的每个部分高位加上 2 个 0构成一个新的 4 字节组,新的字节组中,每个字节只有 6 位,能表示 64 个值。

如果原文不是三字节的倍数,可能多出一个字节和两个字节,分别会被转为 2 字节和 3 字节的 BASE64 编码,这时编码系统应该在形成的 BASE64 编码最后添加上填充符”=”,保证 BASE64 编码长度是4的倍数。所以在 BASE64 编码后添加的填充符 ”=” 可能为 0-2 个。

2兆 / 4 * 3 = 1.5 兆 = 1536 字节,所以传给 JS 的图片最多不能超过 1.5 兆

webview.evaluateJavascript

通过下面代码进行打印,可以发现 evaluateJavascript 加载大于 5兆 的图片均正常

new Thread(() -> {
	//String data = BitmapUtil.toBase64(activity, uri);

	StringBuilder sb = new StringBuilder();
	for(int i=0;i<5 * 1048576;i++) {
		sb.append("1");
	}
	String data = sb.toString();

	webView.post(() -> {
		//webView.loadUrl("javascript:console.log('" + data + ".length')");
		//webView.evaluateJavascript("javascript:console.log('" + data + ".length')", value -> { });
	});
}).start();

但是,当我将写死的 “字符串常量” 替换成 “Base64” 的图片数据时,却报错了
在这里插入图片描述
我就想,会不会是由于Base64的转换过程中,有某些特殊字符,导致 evaluateJavascript 无法解析

下面是图片转 Base64 的方法,FLAGS 用的是默认的 Base64.DEFAULT

private static final int BASE64_FLAGS = Base64.DEFAULT;

/**
 * 从指定路径获取图片并转为Base64
 */
public static String toBase64(Context context, Uri uri) {
    Bitmap bitmap = fromUri(context, uri);
    if (bitmap != null) {
        return toBase64(bitmap);
    }
    return null;
}

/**
 * 将图片转为Base64
 */
public static String toBase64(Bitmap bitmap) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    Bitmap.CompressFormat format = Bitmap.CompressFormat.PNG;
    String mimeType = "image/png";
    if(bitmap.getConfig() == Bitmap.Config.RGB_565) {
        format = Bitmap.CompressFormat.JPEG;
        mimeType = "image/jpeg";
    }
    bitmap.compress(format, 100, baos);
    byte[] buffer = baos.toByteArray();
    return toBase64(buffer, mimeType);
}

/**
 * 将图片转为Base64
 */
public static String toBase64(byte[] buffer, String mimeType) {
    String str = Base64.encodeToString(buffer, BASE64_FLAGS);
    str = "data:" + mimeType + ";base64," + str;
    return str;
}

将 Base64 的前10位 和 后10位 进行拼接,同样用 console.log 打印出来,发现正常。

再看一下打印,突然发现打印出来的 Base64 有换行符
在这里插入图片描述
这是因为 Base64.DEFAULT,当字符串长度超过76会自动添加换行符,将 Base64 的 FLAGS 改成 Base64.NO_WRAP,再跑一遍,可以了 ~ ~

3.5 兆多的图片,可以被前端正常获取并显示了。

但是注意,传大图给前端要花很长的时间!!!

因为它需要将图片数据按字节做一次转换,然后前端获取之后设置到属性里,显示的时候需要再转一次(混合开发内耗严重),加载一张图片,要让用户等很久,体验很差。

因此建议的做法是,图片压缩之后传给前端,然后要上传时,直接调用 android 接口,从本地上传

发布了471 篇原创文章 · 获赞 565 · 访问量 188万+

猜你喜欢

转载自blog.csdn.net/chy555chy/article/details/102979014
今日推荐