場景
由於專案需要,要在預覽圖片介面新增圖片分享功能,需要對純圖片進行分享,所以照舊呼叫了微信分享的封裝方法(WxShareUtil.of().open(true, bitmap);
),第一個引數為是否分享到朋友圈,第二個引數為bitmap,因為預覽的圖片為url
,需要先將url
轉為bitmap
,但是,無法吊起微信,因為方法用在別的地方分享圖片是沒問題的,為什麼在這就無法吊起微信了。
原因
開啟log檢視並沒有明顯的報錯,但發現一條 checkArgs fail, thumbData is invalid
,在網上查了一下,說是縮圖太大,微信限制縮圖只能小於32k,打斷點檢視,確實是縮圖太大。
msg.thumbData = BitmapUtils.bitmap2Bytes(thumbBmp);
//壓縮縮圖到32kb
if (msg.thumbData != null && msg.thumbData.length > '耀') { //微信sdk裡面判斷的大小
msg.thumbData = BitmapUtils.compressBitmap(msg.thumbData, '耀');
}
複製程式碼
暫時解決,但是,因為圖片大多為使用者相機直接拍照的大圖,所以,好多相機直接拍攝的圖片仍舊無法吊起微信,提示錯誤為checkArgs fail, content is too large
,檢視原始碼發現是分享的圖片過大,所以這裡需要進行壓縮。
public void open(boolean isChat, Bitmap bmp) {
if (!iwxapi.isWXAppInstalled()) {
Toast.makeText(app, "您尚未安裝微信客戶端", Toast.LENGTH_SHORT).show();
}
new Thread(new Runnable() {
@Override
public void run() {
WXImageObject imgObj = new WXImageObject();
Bitmap bitmap = compressScale(bmp);
imgObj.imageData = bmpToByteArray(bitmap, true);
WXMediaMessage msg = new WXMediaMessage();
msg.mediaObject = imgObj;
Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, 120, 120, true);
msg.thumbData = BitmapUtils.bitmap2Bytes(thumbBmp);
//壓縮縮圖到32kb
if (msg.thumbData != null && msg.thumbData.length > '耀') { //微信sdk裡面判斷的大小
msg.thumbData = BitmapUtils.compressBitmap(msg.thumbData, '耀');
}
SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = buildTransaction("img");
req.message = msg;
req.scene = isChat ? SendMessageToWX.Req.WXSceneSession : SendMessageToWX.Req.WXSceneTimeline;
boolean sendReq = iwxapi.sendReq(req);
}
}).start();
}
複製程式碼
bmpToByteArray
public static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, output);
if (needRecycle) {
bmp.recycle();
}
byte[] result = output.toByteArray();
try {
output.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
複製程式碼
BitmapUtils.bitmap2Bytes()
/**
* Bitmap 轉 bytes
* @param bitmap
* @return
*/
public static byte[] bitmap2Bytes(Bitmap bitmap) {
ByteArrayOutputStream byteArrayOutputStream = null;
if(bitmap != null && !bitmap.isRecycled()) {
try {
byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
if(byteArrayOutputStream.toByteArray() == null) {
LogUtils.e("BitmapUtils", "bitmap2Bytes byteArrayOutputStream toByteArray=null");
}
return byteArrayOutputStream.toByteArray();
} catch (Exception e) {
LogUtils.e("BitmapUtils", e.toString());
} finally {
if(byteArrayOutputStream != null) {
try {
byteArrayOutputStream.close();
} catch (IOException var14) {
;
}
}
}
return null;
} else {
LogUtils.e("BitmapUtils", "bitmap2Bytes bitmap == null or bitmap.isRecycled()");
return null;
}
}
複製程式碼
compressScale
/**
* 圖片按比例大小壓縮方法
*
* @param image (根據Bitmap圖片壓縮)
* @return
*/
public static Bitmap compressScale(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
// 判斷如果圖片大於1M,進行壓縮避免在生成圖片(BitmapFactory.decodeStream)時溢位
if (baos.toByteArray().length / 1024 > 3072) {
baos.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, 80, baos);// 這裡壓縮50%,把壓縮後的資料存放到baos中
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 開始讀入圖片,此時把options.inJustDecodeBounds 設回true了
newOpts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
// 現在主流手機比較多是800*480解析度,所以高和寬我們設定為
// float hh = 800f;// 這裡設定高度為800f
// float ww = 480f;// 這裡設定寬度為480f
float hh = 512f;
float ww = 512f;
// 縮放比。由於是固定比例縮放,只用高或者寬其中一個資料進行計算即可
int be = 1;// be=1表示不縮放
if (w > h && w > ww) {// 如果寬度大的話根據寬度固定大小縮放
be = (int) (newOpts.outWidth / ww);
} else if (w < h && h > hh) { // 如果高度高的話根據高度固定大小縮放
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0)
be = 1;
newOpts.inSampleSize = be; // 設定縮放比例
// newOpts.inPreferredConfig = Config.RGB_565;//降低圖片從ARGB888到RGB565
// 重新讀入圖片,注意此時已經把options.inJustDecodeBounds 設回false了
isBm = new ByteArrayInputStream(baos.toByteArray());
bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
return compressImage(bitmap);// 壓縮好比例大小後再進行質量壓縮
// return bitmap;
}
public static Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 質量壓縮方法,這裡100表示不壓縮,把壓縮後的資料存放到baos中
int options = 90;
while (baos.toByteArray().length / 1024 > 100) { // 迴圈判斷如果壓縮後圖片是否大於100kb,大於繼續壓縮
baos.reset(); // 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 這裡壓縮options%,把壓縮後的資料存放到baos中
options -= 10;// 每次都減少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把壓縮後的資料baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream資料生成圖片
return bitmap;
}
複製程式碼
最後
經測試,圖片可吊起微信進行分享,但是圖片清晰度降低,上面的壓縮是先按比例大小壓縮,再按質量壓縮,均為有失真壓縮,目前較為流行的是魯班的壓縮(檔案File壓縮)。