移动应用和Ajax很重的前端网站类似,都是用Api和后端打交道,很少有纯粹的单机版App,那种一般都是工具,算不上移动互联网的应用。
想访问网络,首先要在AndroidManifest.xml中加入访问网络的权限,另外注意:网络操作要异步进行,不能阻塞UI渲染线程!
<uses-permission android:name="android.permission.INTERNET" />
安卓框架本身里面有两个用来做网络访问的常用库,感兴趣的同学可以看Android’s HTTP Clients。这里只说结论,对应安卓2.2之前来讲HttpClient要优于HttpURLConnection,而从2.3向后的版本,HttpURLConnection是比较推荐的选择。
推荐一个基于Apache的HttpClient的封装库,loopj/android-async-http,大家可以试用下。因为loopj的这个库是封装了异步操作的,如果需要自己做异步并且做更多的定制的话,还是要自己来做。不过这个库里提供的RequestParams和SimpleMultipartEntity这两个类很不错,支持处理普通的和multipart上传的form,比较轻便。我一般把用这两个拿出来和自己定制的HttpClient配合用。下面说下HttpClient需要注意的一些点:
httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
public void process(HttpRequest request, HttpContext context) {
if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {
request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
}
}
});
httpClient.addResponseInterceptor(new HttpResponseInterceptor() {
public void process(HttpResponse response, HttpContext context) {
final HttpEntity entity = response.getEntity();
final Header encoding = entity.getContentEncoding();
if (encoding != null) {
for (HeaderElement element : encoding.getElements()) {
if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) {
response.setEntity(new InflatingEntity(response.getEntity()));
break;
}
}
}
}
});
public static void setTrustAllFactory(HttpClient httpClient){
try{
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
setSSLSocketFactory(httpClient, sf);
}catch (Exception e){
e.printStackTrace();
}
}
具体这个问题可以参考android-making-https-request,一个典型的MySSLSocketFactory如下。
class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port,
autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
推荐基于URLConnection的开源项目:kevinsawicki/http-request,具体使用可以直接看项目主页的介绍。
注意在2.2及以下使用时,需要做下面的处理:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
HttpRequest.keepAlive(false);
}
具体见HttpURLConnection的“Avoiding Bugs In Earlier Releases”一节,以及issues#2939。