解决Android云信突然不能发送图片,视频和语音异常问题 -- https惹的祸

去年写了一篇使用云信集成过程踩到的坑: 地址 集成上线之后,由于需要忙其他的项目,这个就扔给其他人了,直到最近有新的项目需要重新接入聊天组件,然后我们就aar集成了,过程什么的一切都很顺利,直到测试给了报出了异常:

突然发现不能发送图片,视频,还有语音,最后发现只要是文件类型的Message都不能发送!第一反应就是是不是集成本身存在问题,是不是云信的sdk出了问题,是不是我的主module中有什么设置导致云信不能正常进行???

由于时间非常紧,我给自己排期说最多三天可以解决问题,上面同意之后,我赶紧进行测试。首先说明一下云信上传文件的逻辑:首先像自家的服务器获取上传地址和上传token,然后使用上传token和文件一起上传!

首先我翻了线上正常的代码,打了个正式环境中的测试包,发送了一张图片,然后打印日志如下:
在这里插入图片描述
首先上传,然后返回值,再通过返回值response上传文件,这是正常的上传逻辑,最后也能上传数据,app数据中也有正确的回调,显示也正常。

然后我把目光转移有问题的新的APP上,打开日志,然后也得到了如下的日志:
在这里插入图片描述
但是它只显示 http post task is excuting ,最后就没有显示结果了。问题也到这里终结了,
在这里插入图片描述
这里发送消息三个接口都没有回调,页面也一直卡在这里。就像这样:
在这里插入图片描述
一直都是0%,没有显示上传失败,也没有成功!!!
一切弄得我很尴尬,没办法,那就看源码吧:
先找到sendMessage的实现类,目前来说是基于云信6.6.0的版本,代码混淆了,不过还能看:
在这里插入图片描述
然后找到com.netease.nimlib.q.f.a,最后一路找下去(其中的艰辛不想说了,不是人干的活儿),找到了我们的目标类:

com.netease.nimlib.m.a.b.a

e 

文件,其中c方法为 :

private c b(String var1, byte[] var2) {
        com.netease.nimlib.k.b.b(o, "http post task is executing");
        InputStream var3 = null;
        short var4 = 799;

        c var13;
        try {
            this.a = com.netease.nimlib.m.a.c.b.a(var1, "POST");
            com.netease.nimlib.m.a.c.b.a(this.a, "NIM-Android-NOS-Upload-V6.6.0", com.netease.nimlib.m.a.b.a.c().a(), com.netease.nimlib.m.a.b.a.c().b(), com.netease.nimlib.f.g.c());
            int var5 = var2.length;
            HttpURLConnection var14 = this.a;
            if ("POST".equals(var14.getRequestMethod())) {
                if (var5 <= 0) {
                    var14.setChunkedStreamingMode(0);
                } else {
                    var14.setFixedLengthStreamingMode(var5);
                }
            }

            if ((var14 = this.a) != null && var14 instanceof HttpsURLConnection && !TextUtils.isEmpty(com.netease.nimlib.f.g.c())) {
                com.netease.nimlib.m.a.c.b.a(this.a, "Host", com.netease.nimlib.f.g.c());
            }

            com.netease.nimlib.m.a.c.b.a(this.a, "x-nos-token", this.f);
            if (this.l != null) {
                if (!TextUtils.isEmpty(this.l.b())) {
                    com.netease.nimlib.m.a.c.b.a(this.a, "Content-Type", this.l.b());
                }

                if (!TextUtils.isEmpty(this.l.a())) {
                    com.netease.nimlib.m.a.c.b.a(this.a, "Content-MD5", this.l.a());
                }

                if (this.l.c() != null && this.l.c().size() > 0) {
                    Map var15;
                    Iterator var17 = (var15 = this.l.c()).keySet().iterator();

                    while(var17.hasNext()) {
                        String var6 = (String)var17.next();
                        com.netease.nimlib.m.a.c.b.a(this.a, "x-nos-meta-" + var6, (String)var15.get(var6));
                    }
                }
            }

            com.netease.nimlib.m.a.c.b.a(this.a, var2);
            int var16 = this.a.getResponseCode();
            if ((var3 = this.a.getInputStream()) != null) {
                var1 = com.netease.nimlib.m.a.c.b.a(var3);
                if (var16 == 200) {
                    com.netease.nimlib.k.b.b(o, "http post response is correct, response: " + var1);
                } else {
                    com.netease.nimlib.k.b.b(o, "http post response is failed, status code: " + var16);
                }

                var13 = new c(var16, new JSONObject(var1), (Exception)null);
            } else {
                var13 = new c(899, (JSONObject)null, (Exception)null);
            }
        } catch (SSLPeerUnverifiedException var10) {
            com.netease.nimlib.k.b.e(o, "http post exception, e=SSL_PEER_UNVERIFIED_EXCEPTION," + var10.getMessage());
            var13 = new c(1099, new JSONObject(), var10);
        } catch (Exception var11) {
            com.netease.nimlib.k.b.d(o, "http post exception, status code=" + var4, var11);
            var13 = new c(799, new JSONObject(), var11);
        } finally {
            com.netease.nimlib.m.a.c.b.b(var3);
            this.a.disconnect();
            this.a = null;
        }

        return var13;
    }

其实大家也看到了,我们之所以这么能确定是这个方法,是因为这个打印了最后语句:

http post task is executing

中间是有一段拼接参数的,我们着重看这句话:

 com.netease.nimlib.m.a.c.b.a(this.a, var2);
 
 int var16 = this.a.getResponseCode();
 if ((var3 = this.a.getInputStream()) != null) {
      var1 = com.netease.nimlib.m.a.c.b.a(var3);
      if (var16 == 200) {
           com.netease.nimlib.k.b.b(o, "http post response is correct, response: " + var1);
     } else {
          com.netease.nimlib.k.b.b(o, "http post response is failed, status code: " + var16);
     }

    var13 = new c(var16, new JSONObject(var1), (Exception)null);
}

既然我们找到这里的输出,那我们就打个debug吧,一打就打出了问题了:
在这里插入图片描述
问题是这样的:
首先在488行的时候,a应该是HttpURLConnection,但是到了下面我们发现它变成了OkHttpsURLConnection,云信是没有用到OKHttp的啊,OKHttp只是我的项目中用到的啊,我的项目中的OkHttp怎么会影响到云信这个module中的内部请求呢?那么这个HttpURLConnection怎么转变为OkHttpsURLConnection的呢?
那我们来看看这个方法:
在这里插入图片描述
深入发现

 public static HttpURLConnection a(String var0, String var1) throws IOException {
        HttpURLConnection var2;
        (var2 = (HttpURLConnection)(new URL(var0)).openConnection()).setRequestMethod(var1);
        return var2;
    }

此时发现的HttpURLConnection已经变成了OkHttpsURLConnection,那么这个OkHttpsURLConnection是哪里来的呢?

经过查找和分析,这是当年加的一个测试工具,用来检测网络请求的,具体的逻辑是代理了网络请求,在中间网络请求OkHttp中又加了一个Interceptor,不过没想到的是这个Interceptor代理了全部网络请求,包括https,那么此时我的Interceptor就相当于中间人,所以发起的https的请求都将无效。

然后,去掉这个工具,再次测试,一切OK!图片、视频和语音可以正常发送!!!

对了,这个网络测试工具为:

api "com.github.whataa:pandora:v2.0.4"

github地址为:https://github.com/whataa/pandora 除了网络测试,它还可以用来检测UI界面:

大家可以尝试一下:)

总结一下:
这次主要是https惹的祸,花了我好几天的世界才确定问题所在,分析几次代码都没搞定,最后一次偶然情况下才发现了是我的这个代理问题。

最后,如果你发现你的https请求也出现过这种问题,不妨先查查自己的网络是否联通,是否被代理。如果有,修复一下再试试!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值