手头一个项目中需要使用微信 SDK 分享图片,但遇到了有些图片分享没问题有些却无反应的问题,实际抓取日志发现微信 SDK 有打印错误信息,即
checkArgs fail, thumbData is invalid
因为其他图片可以正常分享,那么这句错误的大致意思就是缩略图的大小超出限制所以无效,网上给出的各种方案基本都是尽量压缩图像以适合微信 SDK 的 32k 字节数(实际上是32768)的分享限制,然而基本都是一棒子打死,我在其基础上进行了修改,改为了根据图像逐级减少清晰度直到适合微信 32k 字节数限制后,分享即可正常进行,具体修改后的算法如下:
private static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) {
byte[] data = bmpToByteArray(bmp, 100);
if (DEBUGMODE) Log.d(">>>", "zipBitmap: quality=100" + " size=" + data.length);
int i = 100;
while (data.length > '耀') { //请勿问我为啥用 '耀' 这个字,这问题问微信 SDK 开发者去,他就是这么判断的
if (i > 10) {
i = i - 10;
} else {
i = i - 1;
}
if (i <= 0) {
if (DEBUGMODE)
Log.e(">>>", "zipBitmap: 失败,很无奈清晰度已经降为0,但压缩的图像依然不符合微信的要求,最后size=" + data.length);
break;
}
data = bmpToByteArray(bmp, i);
if (DEBUGMODE) Log.d(">>>", "zipBitmap: quality=" + i + " size=" + data.length);
}
if (needRecycle)
bmp.recycle();
return data;
}
public static byte[] bmpToByteArray(final Bitmap bmp, int quality) {
int i;
int j;
if (bmp.getHeight() > bmp.getWidth()) {
i = bmp.getWidth();
j = bmp.getWidth();
} else {
i = bmp.getHeight();
j = bmp.getHeight();
}
Bitmap localBitmap = Bitmap.createBitmap(i, j, Bitmap.Config.RGB_565);
Canvas localCanvas = new Canvas(localBitmap);
while (true) {
localCanvas.drawBitmap(bmp, new Rect(0, 0, i, j), new Rect(0, 0, i, j), null);
ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream();
localBitmap.compress(Bitmap.CompressFormat.JPEG, quality,
localByteArrayOutputStream
);
localBitmap.recycle();
byte[] arrayOfByte = localByteArrayOutputStream.toByteArray();
try {
localByteArrayOutputStream.close();
return arrayOfByte;
} catch (Exception e) {
//F.out(e);
}
i = bmp.getHeight();
j = bmp.getHeight();
}
}
主要过程是从 100% 原图开始逐级向下减少清晰度尝试压缩图像至 32k 字节范围内,如果下降到原图 10% 清晰度时依然不满足小于 32k 字节的条件,则以逐级 1% 递减清晰度直至 0% 无法压缩为止。基本满足了大部分图片压缩情况的需要,而且不会对原本就符合要求的图像进行“一棒子打死”式的压缩。
小彩蛋是微信 SDK 中判断 32k 的条件是通过一个字来实现的,即 '耀',这我也与其保持一致。
如果不想这么麻烦直接一步搞定,可以使用我开源的库 # WechatHelper
一并提供了 微信登录、支付、分享的封装,帮你排坑,更轻松的完成微信功能的开发。
网友评论