Volley has been around for a long time, has been widely used, and tutorials are everywhere. There are only two noteworthy points in this article. This article is short, see the links provided. The realization of the complete code in making dodocat/AndroidNetworkDemo may seem more clear than here.
Use OkHttp as the transport layer implementation.
By default, Volley uses different Http transport protocols based on the Android version. Volley uses ApacheHttpStack as the transport protocol above Android 3.0, and HttpURLConnection as the transport layer protocol in 2.3 and below
OkHttp has the following advantages over other implementations.
- SPDY support allows all requests connected to the same host to share a socket.
- If SPDY is not available, connection pooling is used to reduce request latency.
- GZIP is used to compress the downloaded content and the compression operation is transparent to the user.
- Use response caching to avoid repeated network requests.
- When a network problem occurs, OKHttp will still work, and it will recover from common connection problems.
- If your server has multiple IP addresses, when the first address fails to connect, OKHttp attempts to connect to other addresses, which is necessary for IPV4 and IPV6 services and services that reside in multiple data centers.
So using OkHttp is a good alternative.
-
Start by implementing a new HurlStack using OkHttp to build Volley’s 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); }}Copy the code
-
Then use OkHttpStack to create a new Volley requestQueue.
requestQueue = Volley.newRequestQueue(getContext(), new OkHttpStack()); requestQueue.start();Copy the code
That will do.
As an honest developer, you should use Https to protect users’ data. The article Security with Https and SSL on the Android developer website explains this in detail.
OkHttp itself supports Https. See OkHttp Https, and use the OkHttpStack, but if the server developer uses a self-signed certificate (don’t ask me why I use a self-signed certificate), it will not work.
There are a number of articles on the web offering solutions that provide a do-nothing TrustManager that skips SSL authentication, leaving the door open to attacks and making Https obsolete.
My approach is to package self-signed certificates into APK for trust.
Benefits:
- It is difficult to reverse the application, and the application no longer depends on the trust Store of the system, which makes tools such as Charles packet capture invalid. To analyze the application API, you must decompile APK.
- Don’t buy extra certificates, save money….
Disadvantages:
Implementation steps
Take 12306, the most famous self-signed website, for example
-
Export certificate
echo | openssl s_client -connect kyfw.12306.cn:443 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > kyfw.12306.cn.pemCopy the code
-
Convert the certificate to BKS format to download the latest BCprov-JDK and run the following command: storepass is the password for exporting the key file.
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 \ - the storepass asdfqazCopy the code
-
Save the exported kyfw. BKS file to the RES/RAW folder.
-
Create SelfSignSslOkHttpStack
/** * A HttpStack implement witch can verify specified self-signed certification. */ public class SelfSignSslOkHttpStack extends HurlStack { private OkHttpClient okHttpClient; private Map socketFactoryMap; /** * Create a OkHttpStack with default OkHttpClient. */ public SelfSignSslOkHttpStack(Map factoryMap) { this(new OkHttpClient(), factoryMap); } /** * Create a OkHttpStack with a custom OkHttpClient * @param okHttpClient Custom OkHttpClient, NonNull */ public SelfSignSslOkHttpStack(OkHttpClient okHttpClient, Map 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); }}}Copy the code
-
SelfSignSslOkHttpStack is then used to create Volley’s 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();Copy the code
-
done