@flyouting
2014-07-21T15:50:50.000000Z
字数 5758
阅读 6642
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
@Override
protected 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;
}
@Override
protected void deliverResponse(String response) {
if(null != mListener){
mListener.onResponse(response);
}
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed = null;
try {
byte[] data = response.data;
//convert array of bytes into file
FileOutputStream 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));
}
@Override
public 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[] {};
@Override
public 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.
}
@Override
public 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;
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
// TODO Auto-generated method stub
return 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的请求,默认允许所有证书。