移动应用和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。