Volley 已经发布很长时间了, 也已被广泛应用, 相关教程到处都是. 本文只说两个值得注意的地方.

本文讲解部分比较少,
请参阅提供的相关链接. 完整的实现代码在 Github
dodocat/AndroidNetworkDemo
 可能看起来比这里更清晰.

使用 OkHttp 作为传输层的实现.

Volley 默认根据 Android 系统版本使用不同的 Http 传输协议实现.

在 Android 2.3以下使用 ApacheHttpStack 作为传输协议, 在 3.0 及以下使用 HttpURLConnection 作为传输层协议 (感谢评论中指正的朋友).

OkHttp 相较于其它的实现有以下的优点.

  • 支持SPDY,允许连接同一主机的所有请求分享一个socket。
  • 如果SPDY不可用,会使用连接池减少请求延迟。
  • 使用GZIP压缩下载内容,且压缩操作对用户是透明的。
  • 利用响应缓存来避免重复的网络请求。
  • 当网络出现问题的时候,OKHttp会依然有效,它将从常见的连接问题当中恢复。
  • 如果你的服务端有多个IP地址,当第一个地址连接失败时,OKHttp会尝试连接其他的地址,这对IPV4和IPV6以及寄宿在多个数据中心的服务而言,是非常有必要的。

因此使用 OkHttp 作为替代是好的选择.

  1. 首先用 OkHttp 实现一个新的 HurlStack 用于构建 Volley 的 requestQueue.

    public class OkHttpStack extends HurlStack {
    
     private OkHttpClient okHttpClient;
    
     /**
      * Create a OkHttpStack with default OkHttpClient.
      */
     public OkHttpStack() {
         this(new OkHttpClient());
     }
    
     /**
      * Create a OkHttpStack with a custom OkHttpClient
      * @param okHttpClient Custom OkHttpClient, NonNull
      */
     public OkHttpStack(OkHttpClient okHttpClient) {
         this.okHttpClient = okHttpClient;
     }
    
     @Override
     protected HttpURLConnection createConnection(URL url) throws IOException {
         OkUrlFactory okUrlFactory = new OkUrlFactory(okHttpClient);
         return okUrlFactory.open(url);
     }
    }
  2. 然后使用 OkHttpStack 创建新的 Volley requestQueue.

    requestQueue = Volley.newRequestQueue(getContext(), new OkHttpStack());
    requestQueue.start();

    这样就行了.

使用 Https

作为一个有节操的开发者应该使用 Https 来保护用户的数据, Android 开发者网站上文章Security with HTTPS and SSL做了详尽的阐述.OkHttp
自身是支持 Https 的. 参考文档 OkHttp Https, 直接使用上面的 OkHttpStack 就可以了, 但是如果遇到服务器开发哥哥使用了自签名的证书(不要问我为什么要用自签名的), 就无法正常访问了.

网上有很多文章给出的方案是提供一个什么事情都不做的TrustManager 跳过
SSL 的验证, 这样做很容受到攻击, Https 也就形同虚设了.

我采用的方案是将自签名的证书打包入 APK 加入信任.

好处:

  • 应用难以逆向, 应用不再依赖系统的 trust store, 使得 Charles 抓包等工具失效. 要分析应用 API 必须反编译 APK.
  • 不用额外购买证书, 省钱....

缺点:

  • 证书部署灵活性降低, 一旦变更证书必须升级程序.

实现步骤

以最著名的自签名网站12306为例说明

  1. 导出证书

     echo | openssl s_client -connect kyfw.12306.cn:443 2>&1 |  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > kyfw.12306.cn.pem
  2. 将证书转为 bks 格式

    下载最新的bcprov-jdk, 执行下面的命令. storepass 是导出密钥文件的密码.

    keytool -importcert -v \
     -trustcacerts \
     -alias 0 \
     -file <(openssl x509 -in kyfw.12306.cn.pem) \
     -keystore $CERTSTORE -storetype BKS \
     -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \
     -providerpath ./bcprov-jdk16-1.46.jar \
     -storepass asdfqaz
  3. 将导出的 kyfw.bks 文件放入 res/raw 文件夹下.

  4. 创建 SelfSignSslOkHttpStack

    /**
    * A HttpStack implement witch can verify specified self-signed certification.
    */
    public class SelfSignSslOkHttpStack extends HurlStack {
    
     private OkHttpClient okHttpClient;
    
     private Map<String, SSLSocketFactory> socketFactoryMap;
    
     /**
      * Create a OkHttpStack with default OkHttpClient.
      */
     public SelfSignSslOkHttpStack(Map<String, SSLSocketFactory> factoryMap) {
         this(new OkHttpClient(), factoryMap);
     }
    
     /**
      * Create a OkHttpStack with a custom OkHttpClient
      * @param okHttpClient Custom OkHttpClient, NonNull
      */
     public SelfSignSslOkHttpStack(OkHttpClient okHttpClient, Map<String, SSLSocketFactory> factoryMap) {
         this.okHttpClient = okHttpClient;
         this.socketFactoryMap = factoryMap;
     }
    
     @Override
     protected HttpURLConnection createConnection(URL url) throws IOException {
         if ("https".equals(url.getProtocol()) && socketFactoryMap.containsKey(url.getHost())) {
             HttpsURLConnection connection = (HttpsURLConnection) new OkUrlFactory(okHttpClient).open(url);
             connection.setSSLSocketFactory(socketFactoryMap.get(url.getHost()));
             return connection;
         } else {
             return  new OkUrlFactory(okHttpClient).open(url);
         }
     }
    }
  5. 然后用 SelfSignSslOkHttpStack 创建 Volley 的 RequestQueue.

     String[] hosts = {"kyfw.12306.cn"};
     int[] certRes = {R.raw.kyfw};
     String[] certPass = {"asdfqaz"};
     socketFactoryMap = new Hashtable<>(hosts.length);
    
     for (int i = 0; i < certRes.length; i++) {
         int res = certRes[i];
         String password = certPass[i];
         SSLSocketFactory sslSocketFactory = createSSLSocketFactory(context, res, password);
         socketFactoryMap.put(hosts[i], sslSocketFactory);
     }
    
     HurlStack stack = new SelfSignSslOkHttpStack(socketFactoryMap);
    
     requestQueue = Volley.newRequestQueue(context, stack);
     requestQueue.start();
  6. 我们来试一试, 用上一步穿件的 RequestQueue 替换掉原来的, 然后发请求试试.

         StringRequest request = new StringRequest(
                 Request.Method.GET,
                 "https://kyfw.12306.cn/otn/",
                 new Response.Listener<String>() {
                     @Override
                     public void onResponse(String response) {
                         responseContentTextView.setText(response);
                     }
                 },
                 new Response.ErrorListener() {
                     @Override
                     public void onErrorResponse(VolleyError error) {
                         responseContentTextView.setText(error.toString());
                     }
                 });
         RequestManager.getInstance(this).addRequest(request, this);

Android 网络之 Volley+OkHttp+Https的更多相关文章

  1. Android网络框架Volley(体验篇)

    Volley是Google I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...

  2. Android网络框架Volley

    Volley是Google I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...

  3. Android网络框架Volley(实战篇)

      之前讲了ym—— Android网络框架Volley(体验篇),大家应该了解了volley的使用,接下来我们要看看如何把volley使用到实战项目里面,我们先考虑下一些问题: 从上一篇来看 mQu ...

  4. Android网络框架-Volley实践 使用Volley打造自己定义ListView

    这篇文章翻译自Ravi Tamada博客中的Android Custom ListView with Image and Text using Volley 终于效果 这个ListView呈现了一些影 ...

  5. ym—— Android网络框架Volley(终极篇)

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103).谢谢支持! 没看使用过Volley的同学能够,先看看Android网络框架Volley(体验篇)和 ...

  6. ym—— Android网络框架Volley(体验篇)

    VolleyGoogle I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...

  7. Android 网络框架Volley的使用

    Volley简介 在平时的开发过程中,我们的应用几乎总是在和网络打交道, 在android下的网络编程一般都是基于Http协议的 ,常见的是HttpURLConnection和HttpClient 两 ...

  8. Android 网络框架 volley源码剖析

    转载请注明出处:  http://blog.csdn.net/guolin_blog/article/details/17656437 经过前三篇文章的学习,Volley的用法我们已经掌握的差不多了, ...

  9. Android 网络框架---Volley

    /** * Volley 可以同时请求多个,允许高并发 * 特性: * 1.JSON.图片等的异步下载 * 2.网络请求的排序(Scheduling) * 3.网络请求的优先级处理 * 4.缓存 * ...

随机推荐

  1. JSP与HTML及前后分离

    JSP是什么 首先要知道JSP的本质其实是个Servlet,index.jsp在访问的时候首先会自动将该页面翻译生一个index_jsp.java文件,即Servlet代码. 打开这个类你会发现这个类 ...

  2. java对象引用-要掌握的细节2

    目的:加深对java引用变量的理解,避免数据的处理的偏差. 问题: 1.一个集合List ,将新建Student对象stu放入List之后,再给stu的成员变量例如id,name赋值.此时List中的 ...

  3. 面向切面编程之cglib代理方式

    思想: 和上一篇面向切面编程之手动JDK代理方式上的需求和开发模式一样.不同的是目标类没有接口,只有实现类,采用的是spring中提供的Enhancer类继承目标类实现的代理方式. 需要导入的jar包 ...

  4. CSS3属性详解(图文教程)

    本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 前言 我们在上一篇文章中学习了CSS3的选择器,本文来学一下CSS3的一 ...

  5. 免费分享Navicat12各版本破解(仅供学习使用)

    花了几个小时终于找到比较"绿色"的安装包了...(无力吐槽下现在网上好多挂羊头卖狗肉的网站) https://pan.baidu.com/s/1geMIkfT 密码:9a98 里面 ...

  6. Angular2学习笔记四(之Http通信)

    前言: 在这里,我描述三个场景,即系统的注册与登录,及登录后的操作: 1.注册场景,前端页面传入用户名密码,通过一个api接口传到后台,在后台对这用户及密码进行保存: 2.登录场景,前端用户传入用户名 ...

  7. .NET Core 2.0 问题杂记

    一. Ubuntu 14.04 安装 1.安装之前请先删除之前的.net core 版本 命令如下: 1.1 获取安装的.net core 版本 sudo apt --installed list | ...

  8. CF698C. LRU [容斥原理 概率]

    CF698C. LRU 题意:n种物品,大小为k的队列,\(p_i\)的概率选择第i种物品放入队尾,如果已经有i了就不放了.队列大小>k时弹出队首.求\(10^{100}\)次操作后每种物品在队 ...

  9. Material使用11 核心模块和共享模块、 如何使用@angular/material

    1 创建项目 1.1 版本说明 1.2 创建模块 1.2.1 核心模块 该模块只加载一次,主要存放一些核心的组件及服务 ng g m core 1.2.1.1 创建一些核心组件 页眉组件:header ...

  10. iOS 使用NTP时间同步服务

    githup上有相关开源库, ios-ntp 导入即可使用 NetworkClock *netClock = [NetworkClock sharedNetworkClock]; netClock.n ...