Android - HTTP 协议访问网络

使用 HTTP 协议访问网络

果真的说要去深入分析 HTTP 协议,可能需要花费整整一本书的篇幅。这里我当然不
会这么干,因为毕竟你是跟着我学习 Android 开发的,而不是网站开发。对于 HTTP 协议,
你只需要稍微了解一些就足够了,它的工作原理特别的简单,就是客户端向服务器发出一条
HTTP 请求,服务器收到请求之后会返回一些数据给客户端,然后客户端再对这些数据进行
解析和处理就可以了。是不是非常简单?一个浏览器的基本工作原理也就是如此了。比如说
上一节中使用到的 WebView 控件,其实也就是我们向百度的服务器发起了一条 HTTP 请求,
接着服务器分析出我们想要访问的是百度的首页,于是会把该网页的 HTML 代码进行返回,
然后WebView再调用手机浏览器的内核对返回的HTML代码进行解析, 最终将页面展示出来。


使用 HttpURLConnection

首先需要获取到 HttpURLConnection 的实例,一般只需 new 出一个 URL 对象,并传入
目标的网络地址,然后调用一下 openConnection()方法即可,如下所示:

URL url = new URL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

得到了 HttpURLConnection 的实例之后,我们可以设置一下 HTTP 请求所使用的方法。
常用的方法主要有两个,GET 和 POST。GET 表示希望从服务器那里获取数据,而 POST 则
表示希望提交数据给服务器。写法如下:

connection.setRequestMethod("GET");

接下来就可以进行一些自由的定制了,比如设置连接超时、读取超时的毫秒数,以及服
务器希望得到的一些消息头等。这部分内容根据自己的实际情况进行编写,示例写法如下:
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);

之后再调用 getInputStream()方法就可以获取到服务器返回的输入流了, 剩下的任务就是
对输入流进行读取,如下所示:

InputStream in = connection.getInputStream();

最后可以调用 disconnect()方法将这个 HTTP 连接关闭掉,如下所示:

connection.disconnect();

实例 : 

public class MainActivity extends Activity implements OnClickListener {
public static final int SHOW_RESPONSE = 0;
private Button sendRequest;
private TextView responseText;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_RESPONSE:
String response = (String) msg.obj;
// 在这里进行UI操作,将结果显示到界面上
responseText.setText(response);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendRequest = (Button) findViewById(R.id.send_request);
responseText = (TextView) findViewById(R.id.response_text);
sendRequest.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.send_request) {
sendRequestWithHttpURLConnection();
}
}
private void sendRequestWithHttpURLConnection() {
// 开启线程来发起网络请求
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
try {
URL url = new URL("http://www.baidu.com");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
InputStream in = connection.getInputStream();
// 下面对获取到的输入流进行读取
BufferedReader reader = new BufferedReader(new
InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
Message message = new Message();
message.what = SHOW_RESPONSE;
// 将服务器返回的结果存放到Message中
message.obj = response.toString();
handler.sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}).start();
}
}
可以看到,我们在 Send Request 按钮的点击事件里调用了 sendRequestWithHttpURL-
Connection()方法, 在这个方法中先是开启了一个子线程, 然后在子线程里使用HttpURLConnection
发出一条 HTTP 请求,请求的目标地址就是百度的首页。接着利用 BufferedReader 对服务器
返回的流进行读取,并将结果存放到了一个 Message 对象中。这里为什么要使用 Message 对
象呢?当然是因为子线程中无法对 UI 进行操作了。我们希望可以将服务器返回的内容显示
到界面上, 所以就创建了一个 Message 对象, 并使用 Handler 将它发送出去。 之后又在 Handler
的 handleMessage()方法中对这条 Message 进行处理,最终取出结果并设置到 TextView 上。
完整的一套流程就是这样,不过在开始运行之前,仍然别忘了要声明一下网络权限。修
改 AndroidManifest.xml 中的代码,如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.networktest"
android:versionCode="1"
android:versionName="1.0" >
……
<uses-permission android:name="android.permission.INTERNET" />
……
</manifest>


使用 HttpClient(注 : Android Studio已经不能使用了,因为Google在Android6.0对这个接口放弃了使用)

HttpClient是 Apache提供的 HTTP网络访问接口, 从一开始的时候就被引入到了 Android
API 中。它可以完成和 HttpURLConnection 几乎一模一样的效果,但两者之间的用法却有较
大的差别,那么我们自然要看一下 HttpClient 是如何使用的了。
首先你需要知道,HttpClient 是一个接口,因此无法创建它的实例,通常情况下都会创
建一个 DefaultHttpClient 的实例,如下所示:

HttpClient httpClient = new DefaultHttpClient();

接下来如果想要发起一条 GET 请求,就可以创建一个 HttpGet 对象,并传入目标的网络
地址,然后调用 HttpClient 的 execute()方法即可:

HttpGet httpGet = new HttpGet("http://www.baidu.com");
httpClient.execute(httpGet);

如果是发起一条 POST 请求会比 GET 稍微复杂一点,我们需要创建一个 HttpPost 对象,
并传入目标的网络地址,如下所示:

	HttpPost post = new HttpPost("http://www.baidu.com");
	List<NameValuePair> list = new ArrayList<NameValuePair>();
	list.add(new BasicNameValuePair("username", "admin"));
	list.add(new BasicNameValuePair("password", "123456"));
	UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "utf-8");
	post.setEntity(entity);

接下来的操作就和 HttpGet 一样了,调用 HttpClient 的 execute()方法,并将 HttpPost 对
象传入即可:

httpClient.execute(httpPost);
执行 execute()方法之后会返回一个 HttpResponse对象, 服务器所返回的所有信息就会包
含在这里面。通常情况下我们都会先取出服务器返回的状态码,如果等于 200就说明请求和
响应都成功了,如下所示:
if (httpResponse.getStatusLine().getStatusCode() == 200) {
// 请求和响应都成功了
}
接下来在这个 if 判断的内部取出服务返回的具体内容,可以调用 getEntity()方法获取到
一个 HttpEntity 实例, 然后再用 EntityUtils.toString()这个静态方法将 HttpEntity 转换成字符串
即可,如下所示:

HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity);

注意如果服务器返回的数据是带有中文的,直接调用 EntityUtils.toString()方法进行转换
会有乱码的情况出现,这个时候只需要在转换的时候将字符集指定成 utf-8 就可以了,如下
所示:

String response = EntityUtils.toString(entity, "utf-8");
好了,基本的用法就是如此

实例 :

public class MainActivity extends Activity implements OnClickListener {
……
@Override
public void onClick(View v) {
if (v.getId() == R.id.send_request) {
sendRequestWithHttpClient();
}
}
private void sendRequestWithHttpClient() {
new Thread(new Runnable() {
@Override
public void run() {
try {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://www.baidu.com");
HttpResponse httpResponse = httpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
//  请求和响应都成功了
HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity,
"utf-8");
Message message = new Message();
message.what = SHOW_RESPONSE;
//  将服务器返回的结果存放到Message 中
message.obj = response.toString();
handler.sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
……
}













發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章