基于HTTP网络编程
Android之基于HttpURLConnection下载文本与图片网络编程案例
一、HTTP通信
在开始前先简单介绍下HTTP协议中的两种不同的请求方式——GET和POST。GET方式在进行数据请求时,会把数据附加到URL后面传递给服务器,比如常见的:http://XXX.XXX.XXX/XX.jsp?id=1,POST方式则是将请求的数据放到HTTP请求头中,作为请求头的一部分传入服务器。所以,在进行HTTP编程前,首先要明确究竟使用的哪种方式进行数据请求的。
在Android中,可以有两种方式可以用来进行Http编程:
1、
HttpURLConnection
;
2、
HttpClient
。
二、HttpURLConnection
HttpURLConnection是继承自URLConnection的一个抽象类,在HTTP编程时,来自HttpURLConnection的类是所有操作的基础,获取该对象的代码如下:
1 public HttpURLConnection urlconn= null;
2 private void Init() throws IOException
3 {
4 if (urlStr=="")
5 {
6 urlStr="http://www.baidu.com";
7 }
8 URL url = new URL(urlStr);
9 //打开一个URL所指向的Connection对象
10 urlconn = (HttpURLConnection)url.openConnection();
11 }
HttpURLConnection对网络资源的请求在默认情况下是使用GET方式的,所以当使用GET方式时,不需要我们做太多的工作;
当我们需要使用POST方式时,就需要使用setRequestMethod()来设置请求方式了。
二、HttpClient
这个类并不是来自Android的,而是来自org.apache.http。和HttpURLConnection相同,HttpClient也存在GET和POST两种方式。
1、HttpGet
在HttpClient中,我们可以非常轻松使用HttpGet对象来通过GET方式进行数据请求操作,当获得HttpGet对象后我们可以使用HttpClient的execute方法来向我们的服务器发送请求。在发送的GET请求被服务器相应后,会返回一个HttpResponse响应对象,利用这个响应的对象我们能够获得响应回来的状态码,如:200、400、401等等。
1 public String HttpGetMethod()
2 {
3 String result = "";
4 try
5 {
6 HttpGet httpRequest = new HttpGet(urlStr);
7 HttpClient httpClient = new DefaultHttpClient();
8 HttpResponse httpResponse = httpClient.execute(httpRequest);
9 if(httpResponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK)
10 {
11 result = EntityUtils.toString(httpResponse.getEntity());
12 }
13 else
14 {
15 result = "null";
16 }
17 return result;
18 }
19 catch(Exception e)
20 {
21 return null;
22 }
23 }
2、HttpPost
当我们使用POST方式时,我们可以使用HttpPost类来进行操作。当获取了HttpPost对象后,我们就需要向这个请求体传入键值对,这个键值对我们可以使用NameValuePair对象来进行构造,然后再使用HttpRequest对象最终构造我们的请求体,最后使用HttpClient的execute方法来发送我们的请求,并在得到响应后返回一个HttpResponse对象。其他操作和我们在HttpGet对象中的操作一样。
1 public String HttpPostMethod(String key,String value)
2 {
3 String result = "";
4 try
5 {
6 // HttpPost连接对象
7 HttpPost httpRequest = new HttpPost(urlStr);
8 // 使用NameValuePair来保存要传递的Post参数
9 List<NameValuePair> params = new ArrayList<NameValuePair>();
10 // 添加要传递的参数
11 params.add(new BasicNameValuePair(key, value));
12 // 设置字符集
13 HttpEntity httpentity = new UrlEncodedFormEntity(params, "Utf-8");
14 // 请求httpRequest
15 httpRequest.setEntity(httpentity);
16 // 取得默认的HttpClient
17 HttpClient httpclient = new DefaultHttpClient();
18 // 取得HttpResponse
19 HttpResponse httpResponse = httpclient.execute(httpRequest);
20 // HttpStatus.SC_OK表示连接成功
21 if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
22 // 取得返回的字符串
23 result = EntityUtils.toString(httpResponse.getEntity());
24 return result;
25 } else {
26 return "null";
27 }
28 }
29 catch(Exception e)
30 {
31 return null;
32 }
33 }
三、上机任务
基于HTTP下载图像与文本文件
......
主界面类
MainActivity
(
1
)
IP
地址:安卓程序里用
localhost
或
127.0.0.1
表示是模拟器
IP
地址,而不是电脑的本机
IP
地址。在电脑上查看本机
IP
地址。
(
2
)
开子线程请求连接服务器(耗时的操作如果不开辟子线程,会导致主线程产生阻塞现象,影响用户体验)
(
3
)子线程里不能直接更新主线程
UI
,必须要通过消息处理器
Handler
对象来实现。
package net.lm.ied.download_text_image;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* 基于HttpURLConnection下载文本和图片
*/
public class MainActivity extends Activity {
private final String TAG = "download_text_image";
/**
* 服务器URL
*/
private final String SERVER_URL = "http://192.168.183.2:8080/lzy_server";
private ImageView ivImage;
private EditText edtText;
private Bitmap bitmap;
private String text;
private ProgressBar pbDownloadProgress;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//通过布局资源文件设置用户界面
setContentView(R.layout.activity_main);
//通过资源标识获取控件实例
ivImage = (ImageView) findViewById(R.id.iv_image);
edtText = (EditText) findViewById(R.id.edt_text);
pbDownloadProgress = (ProgressBar) findViewById(R.id.pb_download);
//实例化消息处理器
handler = new Handler(new Handler.Callback(){
@Override
public boolean handleMessage(Message message) {
//利用子线程获取的数据更新主界面元素
ivImage.setImageBitmap(bitmap);
edtText.setText(text);
//让进度条消失
pbDownloadProgress.setVisibility(View.GONE);
//事件往后传播
return false;
}
});
}
public void doDownloadImage(View view){
//让下载进度条出现
pbDownloadProgress.setVisibility(View.VISIBLE);
//创建子线程,连接服务器,下载图像资源
new Thread(new Runnable() {
@Override
public void run() {
//创建连接对象
HttpURLConnection conn = null;
try {
//定义图像资源URL
URL url = new URL(SERVER_URL+"/test.jpg");
//创建连接对象
conn= (HttpURLConnection) url.openConnection();
//获取响应码
int responseCode = conn.getResponseCode();
//根据响应码不同执行相应的操作
if(responseCode == HttpURLConnection.HTTP_OK){
//获取字节输入流
InputStream in = conn.getInputStream();
//利用位图工厂构建位图对象
bitmap = BitmapFactory.decodeStream(in);
//通过消息Message类获取消息处理器,往主线程发送消息
Message.obtain(handler).sendToTarget();
}else{
Log.d(TAG,"没有获取响应数据!");
//Toast.makeText(MainActivity.this,"没有获取响应数据",Toast.LENGTH_SHORT).show();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(conn != null){
//断开网络连接,释放资源
conn.disconnect();
}
}
}
}).start();
}
/**
* 下载文本文件
* @param view
*/
public void doDownloadText(View view) {
//创建子线程,连接服务器,下载文本资源
new Thread(new Runnable() {
@Override
public void run() {
//创建连接对象
HttpURLConnection conn = null;
try {
//定义文本资源URL
URL url = new URL(SERVER_URL+"/test.txt");
//创建连接对象
conn= (HttpURLConnection) url.openConnection();
//获取响应码
int responseCode = conn.getResponseCode();
//根据响应码不同执行相应的操作
if(responseCode == HttpURLConnection.HTTP_OK){
//获取字节输入流
InputStream in = conn.getInputStream();
//封转成缓冲字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(in,"UTF-8"));
//定义字符串生成器
StringBuilder builder = new StringBuilder();
//读取文本文件内容
String nextLine = "";
while ((nextLine = br.readLine())!= null){
builder.append(nextLine +"\n");
}
//将文件内容保存到文本变量
text = builder.toString();
//通过消息Message类获取消息处理器,往主线程发送消息
Message.obtain(handler).sendToTarget();
}else{
Log.d(TAG,"没有获取响应数据!");
//Toast.makeText(MainActivity.this,"没有获取响应数据",Toast.LENGTH_SHORT).show();
//java.net.SocketException: socket failed: EACCES (Permission denied) 没有权限访问
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(conn != null){
//断开网络连接,释放资源
conn.disconnect();
}
}
}
}).start();
}
// TODO download 将两个文件放在download目录中
}
受限访问在AndroidManifest.xml中添加:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<?xml version="1.0" encoding="utf-8"?>
<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:padding="15dp"
android:orientation="vertical"
tools:context="net.lm.ied.download_text_image.MainActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_download_text"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:onClick="doDownloadText"
android:text="@string/download_text"/>
<Button
android:id="@+id/btn_download_image"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:onClick="doDownloadImage"
android:text="@string/download_image"/>
</LinearLayout>
<ProgressBar
android:id="@+id/pb_download"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>
<ImageView
android:id="@+id/iv_image"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="fitXY"/>
<EditText
android:id="@+id/edt_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lines="8"
android:editable="false"
android:scrollbars="vertical"/>
</LinearLayout>
<resources>
<string name="app_name">基于HttpURLConnection下载文本和图片</string>
<string name="download_text">下载文本</string>
<string name="download_image">下载图片</string>
</resources>