@flyouting
2014-07-21T07:50:50.000000Z
字数 5758
阅读 6988
Android volley
实现很简单,用GZIPInputStream封装一下数据流,看代码:
public class GZipRequest extends StringRequest {public GZipRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {super(method, url, listener, errorListener);}public GZipRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {super(url, listener, errorListener);}// parse the gzip response using a GZIPInputStream@Overrideprotected Response<String> parseNetworkResponse(NetworkResponse response) {String output = "";try {GZIPInputStream gStream = new GZIPInputStream(new ByteArrayInputStream(response.data));InputStreamReader reader = new InputStreamReader(gStream);BufferedReader in = new BufferedReader(reader);String read;while ((read = in.readLine()) != null) {output += read;}reader.close();in.close();gStream.close();} catch (IOException e) {return Response.error(new ParseError());}return Response.success(output, HttpHeaderParser.parseCacheHeaders(response));}}
首先需要定义一个接口,传递返回数据的进度:
/** Callback interface for delivering the progress of the responses. */public interface ProgressListener {/*** Callback method thats called on each byte transfer.*/void onProgress(long transferredBytes, long totalSize);}
然后需要在网络传输返回数据解析成字节数组的时候,添加上进度回调,网络执行主体代码在BasicNetwork文件中:
/** Reads the contents of HttpEntity into a byte[]. */private byte[] entityToBytes(Request<?> request, HttpEntity entity) throws IOException,ServerError {PoolingByteArrayOutputStream bytes =new PoolingByteArrayOutputStream(mPool, (int) entity.getContentLength());byte[] buffer = null;long totalSize = (int) entity.getContentLength();try {ProgressListener progressListener = null;if (request instanceof ProgressListener) {progressListener = (ProgressListener) request;}InputStream in = entity.getContent();if (in == null) {throw new ServerError();}buffer = mPool.getBuf(1024);int count;int transferredBytes = 0;while ((count = in.read(buffer)) != -1) {bytes.write(buffer, 0, count);transferredBytes += count;if (null != progressListener) {progressListener.onProgress(transferredBytes, totalSize);}}return bytes.toByteArray();} finally {try {// Close the InputStream and release the resources by// "consuming the content".entity.consumeContent();} catch (IOException e) {// This can happen if there was an exception above that left the// entity in// an invalid state.VolleyLog.v("Error occured when calling consumingContent");}mPool.returnBuf(buffer);bytes.close();}}
从代码中可以看到,我们是多传了一个Request的参数,把Request转化成了progressListener对象,这需要我们的Request实现ProgressListener接口,这里有个文件下载的Request,可以参考看看:
/*** A canned request for retrieving the response body at a given URL as a String.*/public class DownloadRequest extends Request<String> implements ProgressListener {private final Listener<String> mListener;private final String mDownloadPath;private ProgressListener mProgressListener;/*** Creates a new request with the given method.** @param method the request {@link Method} to use* @param url URL to fetch the string at* @param download_apth path to save the file to* @param listener Listener to receive the String response* @param errorListener Error listener, or null to ignore errors*/public DownloadRequest(String url, String download_path, Listener<String> listener,ErrorListener errorListener) {super(Method.GET, url, errorListener);mDownloadPath =download_path;mListener = listener;}public void setOnProgressListener(ProgressListener listener){mProgressListener = listener;}@Overrideprotected void deliverResponse(String response) {if(null != mListener){mListener.onResponse(response);}}@Overrideprotected Response<String> parseNetworkResponse(NetworkResponse response) {String parsed = null;try {byte[] data = response.data;//convert array of bytes into fileFileOutputStream fileOuputStream = new FileOutputStream(mDownloadPath);fileOuputStream.write(data);fileOuputStream.close();parsed = mDownloadPath;} catch (UnsupportedEncodingException e) {parsed = new String(response.data);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally{if(TextUtils.isEmpty(parsed)){parsed = "";}}return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));}@Overridepublic void onProgress(long transferredBytes, long totalSize) {if(null != mProgressListener){mProgressListener.onProgress(transferredBytes, totalSize);}}}
volley默认是支持https的,但是因为默认调用中不包含SSLSocketFactory参数,所以默认都是http的,我们可以修改源码,默认调用中添加参数,或者用更简单的一个方法,允许所有证书。
public class HTTPSTrustManager implements X509TrustManager {private static TrustManager[] trustManagers;private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};@Overridepublic void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s)throws java.security.cert.CertificateException {// To change body of implemented methods use File | Settings | File// Templates.}@Overridepublic void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s)throws java.security.cert.CertificateException {// To change body of implemented methods use File | Settings | File// Templates.}public boolean isClientTrusted(X509Certificate[] chain) {return true;}public boolean isServerTrusted(X509Certificate[] chain) {return true;}@Overridepublic X509Certificate[] getAcceptedIssuers() {return _AcceptedIssuers;}public static void allowAllSSL() {HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {@Overridepublic boolean verify(String arg0, SSLSession arg1) {// TODO Auto-generated method stubreturn true;}});SSLContext context = null;if (trustManagers == null) {trustManagers = new TrustManager[] {new HTTPSTrustManager()};}try {context = SSLContext.getInstance("TLS");context.init(null, trustManagers, new SecureRandom());} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (KeyManagementException e) {e.printStackTrace();}HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());}}
修改创建连接的地方:
protected HttpURLConnection createConnection(URL url) throws IOException {if ("https".equals(url.getProtocol())) {HTTPSTrustManager.allowAllSSL();}return (HttpURLConnection) url.openConnection();}
这样,如果发现是https的请求,默认允许所有证书。