[关闭]
@flyouting 2014-07-21T15:50:50.000000Z 字数 5758 阅读 6601

Volley框架的增强二

Android volley


添加支持GZIP的网络请求

实现很简单,用GZIPInputStream封装一下数据流,看代码:

  1. public class GZipRequest extends StringRequest {
  2. public GZipRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
  3. super(method, url, listener, errorListener);
  4. }
  5. public GZipRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
  6. super(url, listener, errorListener);
  7. }
  8. // parse the gzip response using a GZIPInputStream
  9. @Override
  10. protected Response<String> parseNetworkResponse(NetworkResponse response) {
  11. String output = "";
  12. try {
  13. GZIPInputStream gStream = new GZIPInputStream(new ByteArrayInputStream(response.data));
  14. InputStreamReader reader = new InputStreamReader(gStream);
  15. BufferedReader in = new BufferedReader(reader);
  16. String read;
  17. while ((read = in.readLine()) != null) {
  18. output += read;
  19. }
  20. reader.close();
  21. in.close();
  22. gStream.close();
  23. } catch (IOException e) {
  24. return Response.error(new ParseError());
  25. }
  26. return Response.success(output, HttpHeaderParser.parseCacheHeaders(response));
  27. }
  28. }

添加进度显示

首先需要定义一个接口,传递返回数据的进度:

  1. /** Callback interface for delivering the progress of the responses. */
  2. public interface ProgressListener {
  3. /**
  4. * Callback method thats called on each byte transfer.
  5. */
  6. void onProgress(long transferredBytes, long totalSize);
  7. }

然后需要在网络传输返回数据解析成字节数组的时候,添加上进度回调,网络执行主体代码在BasicNetwork文件中:

  1. /** Reads the contents of HttpEntity into a byte[]. */
  2. private byte[] entityToBytes(Request<?> request, HttpEntity entity) throws IOException,
  3. ServerError {
  4. PoolingByteArrayOutputStream bytes =
  5. new PoolingByteArrayOutputStream(mPool, (int) entity.getContentLength());
  6. byte[] buffer = null;
  7. long totalSize = (int) entity.getContentLength();
  8. try {
  9. ProgressListener progressListener = null;
  10. if (request instanceof ProgressListener) {
  11. progressListener = (ProgressListener) request;
  12. }
  13. InputStream in = entity.getContent();
  14. if (in == null) {
  15. throw new ServerError();
  16. }
  17. buffer = mPool.getBuf(1024);
  18. int count;
  19. int transferredBytes = 0;
  20. while ((count = in.read(buffer)) != -1) {
  21. bytes.write(buffer, 0, count);
  22. transferredBytes += count;
  23. if (null != progressListener) {
  24. progressListener.onProgress(transferredBytes, totalSize);
  25. }
  26. }
  27. return bytes.toByteArray();
  28. } finally {
  29. try {
  30. // Close the InputStream and release the resources by
  31. // "consuming the content".
  32. entity.consumeContent();
  33. } catch (IOException e) {
  34. // This can happen if there was an exception above that left the
  35. // entity in
  36. // an invalid state.
  37. VolleyLog.v("Error occured when calling consumingContent");
  38. }
  39. mPool.returnBuf(buffer);
  40. bytes.close();
  41. }
  42. }

从代码中可以看到,我们是多传了一个Request的参数,把Request转化成了progressListener对象,这需要我们的Request实现ProgressListener接口,这里有个文件下载的Request,可以参考看看:

  1. /**
  2. * A canned request for retrieving the response body at a given URL as a String.
  3. */
  4. public class DownloadRequest extends Request<String> implements ProgressListener {
  5. private final Listener<String> mListener;
  6. private final String mDownloadPath;
  7. private ProgressListener mProgressListener;
  8. /**
  9. * Creates a new request with the given method.
  10. *
  11. * @param method the request {@link Method} to use
  12. * @param url URL to fetch the string at
  13. * @param download_apth path to save the file to
  14. * @param listener Listener to receive the String response
  15. * @param errorListener Error listener, or null to ignore errors
  16. */
  17. public DownloadRequest(String url, String download_path, Listener<String> listener,
  18. ErrorListener errorListener) {
  19. super(Method.GET, url, errorListener);
  20. mDownloadPath =download_path;
  21. mListener = listener;
  22. }
  23. public void setOnProgressListener(ProgressListener listener){
  24. mProgressListener = listener;
  25. }
  26. @Override
  27. protected void deliverResponse(String response) {
  28. if(null != mListener){
  29. mListener.onResponse(response);
  30. }
  31. }
  32. @Override
  33. protected Response<String> parseNetworkResponse(NetworkResponse response) {
  34. String parsed = null;
  35. try {
  36. byte[] data = response.data;
  37. //convert array of bytes into file
  38. FileOutputStream fileOuputStream = new FileOutputStream(mDownloadPath);
  39. fileOuputStream.write(data);
  40. fileOuputStream.close();
  41. parsed = mDownloadPath;
  42. } catch (UnsupportedEncodingException e) {
  43. parsed = new String(response.data);
  44. } catch (FileNotFoundException e) {
  45. e.printStackTrace();
  46. } catch (IOException e) {
  47. e.printStackTrace();
  48. } finally{
  49. if(TextUtils.isEmpty(parsed)){
  50. parsed = "";
  51. }
  52. }
  53. return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
  54. }
  55. @Override
  56. public void onProgress(long transferredBytes, long totalSize) {
  57. if(null != mProgressListener){
  58. mProgressListener.onProgress(transferredBytes, totalSize);
  59. }
  60. }
  61. }

关于HTTPS

volley默认是支持https的,但是因为默认调用中不包含SSLSocketFactory参数,所以默认都是http的,我们可以修改源码,默认调用中添加参数,或者用更简单的一个方法,允许所有证书。

  1. public class HTTPSTrustManager implements X509TrustManager {
  2. private static TrustManager[] trustManagers;
  3. private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};
  4. @Override
  5. public void checkClientTrusted(
  6. java.security.cert.X509Certificate[] x509Certificates, String s)
  7. throws java.security.cert.CertificateException {
  8. // To change body of implemented methods use File | Settings | File
  9. // Templates.
  10. }
  11. @Override
  12. public void checkServerTrusted(
  13. java.security.cert.X509Certificate[] x509Certificates, String s)
  14. throws java.security.cert.CertificateException {
  15. // To change body of implemented methods use File | Settings | File
  16. // Templates.
  17. }
  18. public boolean isClientTrusted(X509Certificate[] chain) {
  19. return true;
  20. }
  21. public boolean isServerTrusted(X509Certificate[] chain) {
  22. return true;
  23. }
  24. @Override
  25. public X509Certificate[] getAcceptedIssuers() {
  26. return _AcceptedIssuers;
  27. }
  28. public static void allowAllSSL() {
  29. HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
  30. @Override
  31. public boolean verify(String arg0, SSLSession arg1) {
  32. // TODO Auto-generated method stub
  33. return true;
  34. }
  35. });
  36. SSLContext context = null;
  37. if (trustManagers == null) {
  38. trustManagers = new TrustManager[] {
  39. new HTTPSTrustManager()
  40. };
  41. }
  42. try {
  43. context = SSLContext.getInstance("TLS");
  44. context.init(null, trustManagers, new SecureRandom());
  45. } catch (NoSuchAlgorithmException e) {
  46. e.printStackTrace();
  47. } catch (KeyManagementException e) {
  48. e.printStackTrace();
  49. }
  50. HttpsURLConnection.setDefaultSSLSocketFactory(context
  51. .getSocketFactory());
  52. }
  53. }

修改创建连接的地方:

  1. protected HttpURLConnection createConnection(URL url) throws IOException {
  2. if ("https".equals(url.getProtocol())) {
  3. HTTPSTrustManager.allowAllSSL();
  4. }
  5. return (HttpURLConnection) url.openConnection();
  6. }

这样,如果发现是https的请求,默认允许所有证书。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注