在Android开发中,Android SDK附带了Apache的HttpClient,它是一个完善的客户端。它提供了对HTTP协议的全面支持,可以使用HttpClient的对象来执行HTTP GET和HTTP POST调用。
HTTP工作原理:
1.客户端(一般是指浏览器,这里是指自己写的程序)与服务器建立连接
2.建立连接后,客户端向服务器发送请求
3.服务器接收到请求后,向客户端发送响应信息
4.客户端与服务器断开连接
HttpClient的一般使用步骤:
1.使用DefaultHttpClient类实例化HttpClient对象
2.创建HttpGet或HttpPost对象,将要请求的URL通过构造方法传入HttpGet或HttpPost对象。
3.调用execute方法发送HTTP GET或HTTP POST请求,并返回HttpResponse对象。
4.通过HttpResponse接口的getEntity方法返回响应信息,并进行相应的处理。
最后记得要在AndroidManifest.xml文件添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
下面以聚合数据空气质量城市空气PM2.5指数数据接口为例来演示使用HttpClient进行Get方式通信,通过HttpClient建立网络连接,使用HttpGet方法读取数据,并且通过HttpResponse获取Entity返回值。
聚合数据空气质量城市空气PM2.5指数数据接口API文档参见:http://www.juhe.cn/docs/api/id/33/aid/79
请求示例:http://web.juhe.cn:8080/environment/air/pm?city=城市名称&key=你申请的APPKEY值
实例:HttpClientGetDemo
运行效果:
代码清单:
布局文件:activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="城市:" android:textSize="23sp" /> <EditText android:id="@+id/city" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="3" android:inputType="text" />" </LinearLayout> <Button android:id="@+id/query" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="查询" android:textSize="23sp" /> <TextView android:id="@+id/result" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Java源代码文件:MainActivity.java
package com.rainsong.httpclientgetdemo; import java.io.IOException; import java.net.URLEncoder; import java.util.ArrayList; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import android.os.Bundle; import android.os.StrictMode; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private static final String JUHE_URL_ENVIRONMENT_AIR_PM = "http://web.juhe.cn:8080/environment/air/pm"; private static final String JUHE_APPKEY = "你申请的APPKEY值"; EditText et_city; Button btn_query; TextView tv_result; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 强制直接在UI线程中进行网络操作 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads().detectDiskWrites().detectNetwork() .penaltyLog().build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() .penaltyLog().penaltyDeath().build()); setContentView(R.layout.activity_main); et_city = (EditText)findViewById(R.id.city); tv_result = (TextView)findViewById(R.id.result); btn_query = (Button)findViewById(R.id.query); btn_query.setOnClickListener(new OnClickListener() { public void onClick(View view) { tv_result.setText(""); String city; city = et_city.getText().toString(); if (city.length() < 1) { Toast.makeText(MainActivity.this, "请输入城市名", Toast.LENGTH_LONG).show(); return; } ArrayList<NameValuePair> headerList = new ArrayList<NameValuePair>(); headerList.add(new BasicNameValuePair("Content-Type", "text/html; charset=utf-8")); String targetUrl = JUHE_URL_ENVIRONMENT_AIR_PM; ArrayList<NameValuePair> paramList = new ArrayList<NameValuePair>(); paramList.add(new BasicNameValuePair("key", JUHE_APPKEY)); paramList.add(new BasicNameValuePair("dtype", "json")); paramList.add(new BasicNameValuePair("city", city)); for (int i = 0; i < paramList.size(); i++) { NameValuePair nowPair = paramList.get(i); String value = nowPair.getValue(); try { value = URLEncoder.encode(value, "UTF-8"); } catch (Exception e) { } if (i == 0) { targetUrl += ("?" + nowPair.getName() + "=" + value); } else { targetUrl += ("&" + nowPair.getName() + "=" + value); } } HttpGet httpRequest = new HttpGet(targetUrl); try { for (int i = 0; i < headerList.size(); i++) { httpRequest.addHeader(headerList.get(i).getName(), headerList.get(i).getValue()); } HttpClient httpClient = new DefaultHttpClient(); HttpResponse httpResponse = httpClient.execute(httpRequest); if (httpResponse.getStatusLine().getStatusCode() == 200) { String strResult = EntityUtils.toString(httpResponse.getEntity()); tv_result.setText(strResult); } else { Toast.makeText(MainActivity.this, "查询失败", Toast.LENGTH_LONG).show(); tv_result.setText(""); } } catch (IOException e) { e.printStackTrace(); } } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
注:本来不应该直接在UI线程进行网络操作,会阻塞UI,影响用户体验。但为了不引入其他知识点,把焦点聚集在HttpClient网络通信上,在本例中强制直接在UI线程中进行网络操作。在下篇文章中会介绍如何避免直接在UI线程中进行网络操作。
API知识点
public interface
HttpClient
org.apache.http.client.HttpClient
Known Indirect Subclasses
AbstractHttpClient, AndroidHttpClient, DefaultHttpClient
Class Overview
Interface for an HTTP client. HTTP clients encapsulate a smorgasbord of objects required to execute HTTP requests while handling cookies, authentication, connection management, and other features. Thread safety of HTTP clients depends on the implementation
and configuration of the specific client.
abstract HttpResponse execute(HttpUriRequest request)
Executes a request using the default context.
public class
DefaultHttpClient
extends AbstractHttpClient
org.apache.http.impl.client.DefaultHttpClient
Class Overview
Default implementation of an HTTP client.
Public Constructor
DefaultHttpClient()
Creates a new HTTP client.
public class
HttpGet
extends HttpRequestBase
Inherited Methods
From class org.apache.http.client.methods.HttpRequestBase
From class org.apache.http.message.AbstractHttpMessage
From class java.lang.Object
From interface org.apache.http.HttpMessage
From interface org.apache.http.HttpRequest
From interface org.apache.http.client.methods.AbortableHttpRequest
From interface org.apache.http.client.methods.HttpUriRequest
Public Constructors
HttpGet()
HttpGet(URI uri)
HttpGet(String uri)
abstract void addHeader(String name, String value)
Adds a header to this message.
public interface
HttpResponse
implements HttpMessage
org.apache.http.HttpResponse
Class Overview
An HTTP response.
abstract HttpEntity getEntity()
Obtains the message entity of this response, if any.
abstract StatusLine getStatusLine()
Obtains the status line of this response.
public interface
NameValuePair
org.apache.http.NameValuePair
Known Indirect Subclasses
BasicNameValuePair
Class Overview
A simple class encapsulating an attribute/value pair.
Public Methods
abstract String getName()
abstract String getValue()
public class
BasicNameValuePair
extends Object
implements Cloneable NameValuePair
org.apache.http.message.BasicNameValuePair
Public Constructors
BasicNameValuePair(String name, String value)
Default Constructor taking a name and a value.