Android微信分享大图遇到的问题的解决方法

起因:

要做一个微信图片分享的功能,但是对于大图会如下问题:

当时没有仔细查看错误日志,单纯的以为是图片太大的问题。

分享图片代码:

public void WXsharePic(String transaction, final boolean isSession, Bitmap bitmap) {
  //初始化WXImageObject和WXMediaMessage对象
  WXImageObject imageObject = new WXImageObject(bitmap);
  WXMediaMessage msg = new WXMediaMessage();
  msg.mediaObject = imageObject;
  //设置缩略图
  Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, true);
  bitmap.recycle();
  msg.thumbData = getBitmapByte(scaledBitmap);
  //构造一个Req
  SendMessageToWX.Req req = new SendMessageToWX.Req();
  req.transaction = transaction + Long.toString(System.currentTimeMillis());
  req.message = msg;
  //表示发送给朋友圈 WXSceneTimeline 表示发送给朋友 WXSceneSession
  req.scene = isSession ? SendMessageToWX.Req.WXSceneSession : SendMessageToWX.Req.WXSceneTimeline;
  //调用api接口发送数据到微信
  api.sendReq(req);
}

解决过程:

想法一:

查看微信的文档,发现如下信息:

初步判定是略缩图过大导致的,准备对略缩图进一步压缩。

但是在调试过程中发现略缩图并没有超过32K,于是 这种想法不正确 。

想法二:

既然不是略缩图过大,那大概率就是原图过大了。然而微信官方文档上也没有说明原图大小限制,所以也不知道是否是这个原因。

于是准备测试一下是否是这个原因,对原图进一步压缩。

public static byte[] bitmap2Bytes(Bitmap bitmap, int maxkb) {
  ByteArrayOutputStream output = new ByteArrayOutputStream();
  bitmap.compress(Bitmap.CompressFormat.PNG, 100, output);
  int options = 100;
  while (output.toByteArray().length > maxkb&& options != 10) {
    output.reset(); //清空output
    bitmap.compress(Bitmap.CompressFormat.JPEG, options, output);//这里压缩options%,把压缩后的数据存放到output中
    options -= 10;
  }
  return output.toByteArray();
}

从代码可知,设置了一个最大kb值,并每次循环压缩率递减10%.

然而实际运行中发现无论maxkb设置的多小,还是会出这个问题。

仔细调试发现,原图大小为3M多,即使是最小10%的压缩率也过大了。

于是将压缩率递减改为1%.

将压缩率递减改为1%,并且maxkb设置为500KB时,就没问题了!

但是,有两个很严重的问题:

1.微信的原图最大只能是500KB吗?

2.循环压缩所需时间太久,差不多半分钟才能压缩完毕,效率太低。

想法三:

这个时候,我才开始注意起错误日志来。

错误日志是Binder类出现的,字面意思是数据过大。查看微信的SDK源码可以发现实际上调用微信API,微信会将图片传递给一个新的活动。

而 Intent传值有大小限制,最大只能512KB !

现在错误原因知道了, 微信分享图片会涉及到启动一个新活动,而新活动涉及到Intent传值,而Intent传值有大小限制,于是就会出问题。

可是如何解决呢?

既然直接传图片的Bitmap太大,那就把图片先保存在本地,然后直接传递图片的地址。

解决过程:

分享图片:

public void WXsharePic(String transaction, final boolean isSession, Bitmap bitmap, String path) {
  //初始化WXImageObject和WXMediaMessage对象
  WXImageObject imageObject;
  if (!StringUtil.isBlank(path)) {
    imageObject = new WXImageObject();
    imageObject.setImagePath(path);
  } else {
    imageObject = new WXImageObject(bitmap);
  }
  WXMediaMessage msg = new WXMediaMessage();
  msg.mediaObject = imageObject;
  //设置缩略图
  Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, true);
  bitmap.recycle();
  msg.thumbData = getBitmapByte(scaledBitmap);
  //构造一个Req
  SendMessageToWX.Req req = new SendMessageToWX.Req();
  req.transaction = transaction + Long.toString(System.currentTimeMillis());
  req.message = msg;
  //表示发送给朋友圈 WXSceneTimeline 表示发送给朋友 WXSceneSession
  req.scene = isSession ? SendMessageToWX.Req.WXSceneSession : SendMessageToWX.Req.WXSceneTimeline;
  //调用api接口发送数据到微信
  api.sendReq(req);
}

调用分享:

private void shareToMoment() {
  final Bitmap sharePicture = getBitmapByView(svShare);
  AndPermission.with(this)
      .permission(Permission.WRITE_EXTERNAL_STORAGE)
      .onGranted(new Action() {
        @Override
        public void onAction(List<String> permissions) {
          String path = saveImageToGallery(sharePicture);
          WXsharePic("he" + System.currentTimeMillis(), true, sharePicture, path);
        }
      })
      .onDenied(new Action() {
        @Override
        public void onAction(@NonNull List<String> permissions) {
          Log.e("Activity", "权限申请失败");
        }
      })
      .start();
}

保存图片:

public String saveImageToGallery(Bitmap bmp) {
   // 首先保存图片
   String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "dearxy";
   File appDir = new File(storePath);
   if (!appDir.exists()) {
     appDir.mkdir();
   }
   String fileName = System.currentTimeMillis() + ".jpg";
   File file = new File(appDir, fileName);
   try {
     FileOutputStream fos = new FileOutputStream(file);
     //通过io流的方式来压缩保存图片
     bmp.compress(Bitmap.CompressFormat.JPEG, 60, fos);
     fos.flush();
     fos.close();
   } catch (IOException e) {
     e.printStackTrace();
   }
   return storePath + "/" + fileName;
 }

反思:

  1. 遇到问题直接查看错误日志,找到问题的根源,不能想当然;
  2. 对于安卓基础的了解有待加强;
  3. 总算明白了为什么QQ分享需要请求存储权限;
  4. BAT现在是大家,对于他们的API需要熟悉了解。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • android 软键盘的POPUP布局的问题解决

    我正在开发一个软键盘,做得很好,但是我不知道如何自定义一个长按键的弹出窗口. 我的键盘视图: <?xml version="1.0" encoding="UTF-8"?> <android.inputmethodservice.KeyboardView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/keyboard

  • Android面试题问答整理

    概述 找工作挺难,为更好的应对面试,我将一些面试题收集整理起来,好让自己随时复习. 1.请谈一下Android系统的架构. 答:Android系统采用了分层架构,从高层到低层分别是应用程序层.应用程序框架层.系统运行库层和linux核心层. 2.谈谈android大众常用的五种布局. 答:在Android中,共有五种布局方式,分别是:FrameLayout(框架布局),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),Ta

  • Android解决ScrollView下嵌套ListView和GridView中内容显示不全的问题

    最近为公司做的一个Demo里面用到了ScrollView嵌套了GridView和ListView,然而在嵌套的时候我发现GridView和ListView都是不能完全显示,显示的基本上都是单行的数据,最后查找资料和翻阅文档看到原因是ListView和GridView的绘制过程中在ScrollView中无法准确的测量自身的高度,而且listVIew和GridView抢占了焦点,使得ListView和GrideView具有自身的显示的效果,这样就测量出显示一行条目即可的距离,其他的条目根据自身的滑动

  • Android工程师面试题大全

    下面对这段时间面试遇到的问题进行整理,分享给大家供大家参考,具体内容如下 Java基础: 1.内存泄露的原因 1).资源对象没关闭. 如Cursor.File等资源.他们会在finalize中关闭,但这样效率太低.容易造成内存泄露. SQLiteCursor,当数据量大的时候容易泄露 2).使用Adapter时,没有使用系统缓存的converview. 3).即时调用recycle()释放不再使用的Bitmap. 适当降低Bitmap的采样率,如: BitmapFactory.Options o

  • Android 面试题汇总

        Android 70道面试题汇总不再愁面试 本文为开发者奉献了70道经典Android面试题加答案--重要知识点几乎都涉及到了,你还等啥,赶紧收藏吧!! 1. 下列哪些语句关于内存回收的说明是正确的? (b) A. 程序员必须创建一个线程来释放内存 B. 内存回收程序负责释放无用内存 C. 内存回收程序允许程序员直接释放内存 D. 内存回收程序可以在指定的时间释放内存对象 2. 下面异常是属于Runtime Exception 的是(abcd)(多选) A.ArithmeticExcep

  • Android开发解决popupWindow重叠报错问题

    在popupWindow里面再弹出popupWindow的时候会报这样的错误 ERROR/AndroidRuntime(888): android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRoot$W@44ef1b68 is not valid; is your activity running? 报错的意思大概就是说依赖的Activity没了. 解决方法1 不要在当

  • Android招聘面试题解答

    一般简单题1. Android dvm的进程和Linux的进程,应用程序的进程是否为同一个概念?DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例.而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个概念.2. SIM卡的 EF 文件有何作用?sim卡的文件系统有自己规范,主要是为了和手机通讯,sim本身可以有自己的操作系统,EF就是作存储并和手机通讯用的.3. 嵌入式操作系统内存管理有哪几种,各有何特性?页式

  • 腾讯、百度、华为、搜狗和滴滴Android面试题汇总

    前言:前一段时间和大家交流,据反馈现在Android岗位也没有以前那么多了,当然这不意味着饱和,只是市场更趋于合理一些,Android还有有很多机会的.最近结合一些面试的同学(包含社招和校招),整理了下一些面试题目.实际上,很多面试题网上都能找得到.我整理面试题如下,供大家参考,知道比没知道的好.可以帮大家查漏不缺.以下是(腾讯,百度,华为,搜狗和滴滴 这些厂的面试题) Android基础 View的绘制流程:自定义View如何考虑机型适配:自定义View的事件分发机制:View和ViewGro

  • android: targetSdkVersion升级中Only fullscreen activities can request orientation问题的解决方法

    前言 这几天同事跟我在升级Android target SDK和build tool版本的时候,碰到了一个非常搞笑的问题,基本可以算作是"坑"了!我在这里跟大家分享一下,希望对您有所帮助. 特征 当我们把targetSdkVersion升级到27,buildToolsVersion和相关的support library升级到27.0.1后,在Android 8.0(API level 26)上,部分Activity出现了一个莫名其妙的crash,异常信息如下: java.lang.Ru

  • Android微信分享大图遇到的问题的解决方法

    起因: 要做一个微信图片分享的功能,但是对于大图会如下问题: 当时没有仔细查看错误日志,单纯的以为是图片太大的问题. 分享图片代码: public void WXsharePic(String transaction, final boolean isSession, Bitmap bitmap) { //初始化WXImageObject和WXMediaMessage对象 WXImageObject imageObject = new WXImageObject(bitmap); WXMedia

  • 基于IOS端微信分享失效的踩坑及解决方法

    最近的一个公众号是基于vue的spa应用,在接入微信分享和微信语音的时候出现了:在Android上一切正常,但是在ios端调用wx.config的时候总是失败,去翻了官方文档也并没有找到解决方案,最后在测试中发现是因为初始化的时候传入的URL的问题.具体过程如下: 微信config接口配置,官方文档如下: 所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支

  • Android微信支付获取二次签名Sign的方法

    本文实例为大家分享了Android微信支付获取二次签名Sign的方法,供大家参考,具体内容如下 /** * 获取sign签名 * * @return */ private String genPayReq() { // 获取参数的值 PayReq request = new PayReq(); request.appId = ConstantsMember.APP_ID; request.partnerId = ConstantsMember.MCHID; request.prepayId =

  • ios微信浏览器返回不刷新问题完美解决方法

    开始用的表单提交,返回参数就丢失,换成url跳转,popstate监听 (注释部分)ios10测试始终有问题,继续搜,最后用pageshow,pagehide完美解决(另外说一句:珍爱生命,远离微信和ios) var wxback = { init :function(){ //隐藏微信分享按钮等 document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() { WeixinJSBridge.call('hid

  • Android自定义照相机Camera出现黑屏的解决方法

    本文实例讲述了Android自定义照相机Camera出现黑屏的解决方法.分享给大家供大家参考,具体如下: 对于一些手机,像HTC,当自定义Camera时,调用Camera.Parameters的 parameters.setPreviewSize(width, height)方法时,如果width和height为奇数情况下,则会出现黑屏现象,解决办法可参考SDK提供的ApiDemos中关于Camera的 例子: List<Size> sizes = parameters.getSupporte

  • Android开发中听筒无法播放音乐的解决方法

    本文实例讲述了Android开发中听筒无法播放音乐的解决方法.分享给大家供大家参考,具体如下: 这个问题让我蛋疼了,既然百度也木有资料. 耗时的主要原因是因为权限不足时,而没有终止程序,只用了一小行日志提醒,没有看到 用听筒播放很简单 AudioManager.setMode(AudioManager.MODE_IN_CALL) //设定为通话中即可 还是这一句代码的事,不过记得要加上权限 Android.permission.MODIFY_AUDIO_SETTINGS 不然会像我一样蛋疼半天

  • Android 文件夹显示红色叹号的解决方法(必看)

    有感叹号,说明有的文件损坏或丢失了 解决方法: 右击工程,Build Path..->Configure Build Path...->Java Build Path 可以看到引用的jar包,看看是不是带x了 不用的话就移除,要用的引用回正确路径就可以了 以上这篇Android 文件夹显示红色叹号的解决方法(必看)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • Android开发之TabHost选项卡及相关疑难解决方法

    本文实例分析了Android开发之TabHost选项卡及相关疑难解决方法.分享给大家供大家参考,具体如下: 前言: 虽然现在谷歌已经不推荐使用TabHost,但是初学者还是很有必要接触下这一成金的经典的,本文将介绍纤细介绍这一空间的使用,以及大家可能遇到的问题.注:文末给出完整实现代码 三个问题: 1. 无法显示TabHost 2. 添加图片 + 文字 无法同时 3. 说在最后:点击事件 4. 底部导航无法实现 现在 从问题出发: 问题一:无法显示 TabHost 很多人调用TabHost的方法

  • Android 自定义Dialog去除title导航栏的解决方法

    如下所示: Dialog dialog = new Dialog(context); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setContentView(view); 以上这篇Android 自定义Dialog去除title导航栏的解决方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • Android使用TextView,设置onClick属性无效的解决方法

    Android在布局文件中为View提供了onClick属性,使用方法如下: <TextView android:id="@+id/user" android:layout_width="@dimen/px_171" android:layout_height="fill_parent" android:onClick="iconClickListener" android:clickable="true&qu

随机推荐