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

Posted microhex

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决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请求也出现过这种问题,不妨先查查自己的网络是否联通,是否被代理。如果有,修复一下再试试!

以上是关于解决Android云信突然不能发送图片,视频和语音异常问题 -- https惹的祸的主要内容,如果未能解决你的问题,请参考以下文章

IM聊天教程:发送图片/视频/语音/表情

IM聊天教程:发送图片/视频/语音/表情

Android 网易云信直播

Android 网易云信直播

微信登录黑屏

在 android 的视频视图中播放视频时不录制语音