在Android中针对HTTP进行网络通信有两种:一是HttpURLConnection;二是Apache HTTP客户端。HTTP通信中使用最多的就是Get和Post,Get请求可以获取静态页面,也可以把参数放在URL字符串后面,传递给服务器。Post与Get的不同之处在于Post的参数不是放在URL字符串里面,而是放在http请求数据中。
1、HttpURLConnection接口
HttpURLConnection是Java的标准类,继承自URLConnection类,URLConnection与HttpURLConnection都是抽象类,无法直接实例化对象。其对象主要通过URL的openConnection方法获得,创建一个HttpURLConnection连接的代码如下:
URL url;
url = new URL("http://www.baidu.com");
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
openConnection方法只创建URLConnection或者HttpURLConnection实例,但并不进行真正的连接操作。并且,每次openConnection都将创建一个新的实例。因此,在连接之前我们可以对其一些属性进行设置,比如超时时间等。下面是对HttpURLConnection实例的属性设置:
//设置输入(输出)流
urlConn.setDoInput(true);
urlConn.setDoOutput(true);
//设置请求方式为get
urlConn.setRequestMethod("GET");
//设置不使用缓存
urlConn.setUseCaches(false);
下面我们通过一个程序分别以get和post方式向服务提交用户名和登录密码,服务比较android端传送过的数据后,返回是否登录成功的结果,界面效果如下:
public class MainActivity extends Activity {
private EditText etUsername;
private EditText etPassword;
private Button btnGet;
private Button btnPost;
private TextView tvresult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
etUsername = (EditText) findViewById(R.id.username);
etPassword = (EditText) findViewById(R.id.password);
btnGet = (Button) findViewById(R.id.btnGet);
btnPost = (Button) findViewById(R.id.btnPost);
tvresult = (TextView)findViewById(R.id.tvresult);
btnGet.setOnClickListener(getListener);
btnPost.setOnClickListener(postListener);
}
以Get方式传递参数,需要将参数拼接到url后面。我们首先声明请求的URL,通过该地址创建URL对象,通过URL对象打开连接,获得HttpURLConnection对象。调用HttpURLConnection对象的getResponseCode方法判断是否请求成功,如果成功获得输入流,则读入登录反馈信息。
private OnClickListener getListener = new OnClickListener() {
@Override
public void onClick(View v) {
String urlStr = "http://192.168.0.100:8080/myweb/servlet/LoginAction?";
String param = "username="+etUsername.getText().toString()+"&password="+etPassword.getText().toString();
urlStr += param;
try {
//实例化URL
URL url = new URL(urlStr);
//获得HttpsURLConnection实例
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
//如果请求成功
if(conn.getResponseCode() == HttpURLConnection.HTTP_OK){
//获得输入流
InputStream in = conn.getInputStream();
//数组缓存
byte []b = new byte[in.available()];
//读数据到缓存
in.read(b);
//转换为字符串
String msg = new String (b);
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
//显示结果
tvresult.setText(msg);
//关闭输入流
in.close();
}
//断开连接
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
};
由于HttpURLConnection默认使用Get方式,所以如果我们要使用Post方式,则需要调用setRequestMethod进行设置。然后将我们要传递的参数内容通过writeBytes方法写入数据流。
private OnClickListener postListener = new OnClickListener() {
@Override
public void onClick(View v) {
String urlStr = "http://192.168.0.100:8080/myweb/servlet/LoginAction";
String param = "username="+etUsername.getText().toString()+"&password="+etPassword.getText().toString();
try {
//实例化URL
URL url = new URL(urlStr);
//获得HttpsURLConnection实例
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
//因为是POST请求,要设置输出流,输入流
conn.setDoOutput(true);
conn.setDoInput(true);
//设置以POST方式
conn.setRequestMethod("POST");
//post请求不能使用缓存
conn.setUseCaches(false);
conn.connect();
//获取输出流对象
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
//将要传送的内容写入流中
dos.writeBytes(param);
//刷新、关闭
dos.flush();
dos.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
//获取数据
String msg = reader.readLine();
reader.close();
//关闭http连接
conn.disconnect();
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
//显示结果
tvresult.setText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
};
在服务器端创建LoginAction,响应请求并返回登录结果。该Servlet只做简单判断,没有连接后台数据库。
public class LoginAction extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//从请求中获取用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//设置内容类型
response.setContentType("text/html");
//设置字符编码
response.setCharacterEncoding("utf-8");
//获得打印输出流
PrintWriter out = response.getWriter();
String msg = "Get方式请求";
if(username!=null&&username.equals("admin")&&
password!=null&&password.equals("123456")){
msg += "登录成功";
}else{
msg += "登录失败";
}
//返回信息给客户端
out.print(msg);
//刷新输出流
out.flush();
//关闭输出流
out.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//从请求中获取用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//设置内容类型
response.setContentType("text/html");
//设置字符编码
response.setCharacterEncoding("utf-8");
//获得打印输出流
PrintWriter out = response.getWriter();
String msg = "Post方式请求";
if(username!=null&&username.equals("admin")&&
password!=null&&password.equals("123456")){
msg += "登录成功";
}else{
msg += "登录失败";
}
//返回信息给客户端
out.print(msg);
//刷新输出流
out.flush();
//关闭输出流
out.close();
}
}
程序运行结果如下:
2、使用Apache HTTP客户端
Android集成了Apache HTTP客户端,使得针对HTTP的编程更加方便、高效。在Servlet编程中我们会用HttpServletRequest和HttpServletResponse来表示请求和响应。Apache HTTP客户端也对请求和响应进行封装,根据请求方法的不同,我们会用到HttpGet和HttpPost两个对象。响应对象是HttpResponse,使用DefaultHttpClient执行请求获得响应。
DefaultHttpClient是默认的一个HTTP客户端,我们可以使用它创建一个HTTP连接,代码如下:
HttpClient httpclient = new DefaultHttpClient();
HttpResponse是一个HTTP连接响应,当执行一个HTTP连接后,就会返回一个HttpResponse,可以通过HttpResponse获得一些响应的信息。下面是请求一个HTTP连接并获得该请求是否成功的代码。
HttpResponse httpResponse = httpclient.execute(httpRequest);
if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
//连接成功
}
我们把上面的例子改成使用HttpClient方式实现用户登录功能。
private OnClickListener getListener = new OnClickListener() {
@Override
public void onClick(View v) {
String urlStr = "http://192.168.0.100:8080/myweb/servlet/LoginAction?";
String param = "username="+etUsername.getText().toString()+"&password="+etPassword.getText().toString();
urlStr += param;
//HttpGet连接对象
HttpGet httpRequest = new HttpGet(urlStr);
//获得HttpClient对象
HttpClient httpclient = new DefaultHttpClient();
HttpResponse httpResponse;
try {
httpResponse = httpclient.execute(httpRequest);
if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
//连接成功
//获取返回的字符串
String msg = EntityUtils.toString(
httpResponse.getEntity());
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
//显示结果
tvresult.setText(msg);
}
else{
tvresult.setText("请求失败");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
Post方式比Get方式稍微复杂一点,首先使用HttpPost来构件一个Post方式的请求。需要使用NameValuePair来保存要被传递的参数,然后通过add方法添加这个参数到NameValuePair中。最后通过HttpClient来请求这个连接,返回响应并处理。
private OnClickListener postListener = new OnClickListener() {
@Override
public void onClick(View arg0) {
String urlStr = "http://192.168.0.100:8080/myweb/servlet/LoginAction";
//httpPost连接对象
HttpPost httpRequest = new HttpPost(urlStr);
//使用NameValuePair来保存要传递的Post参数
List<NameValuePair> params = new ArrayList<NameValuePair>();
//添加要传递的参数
params.add(new BasicNameValuePair("username", etUsername.getText().toString()));
params.add(new BasicNameValuePair("password", etPassword.getText().toString()));
HttpEntity entity;
try {
entity = new UrlEncodedFormEntity(params);
//设置请求参数
httpRequest.setEntity(entity);
//获得默认的HttpClient
HttpClient httpclient = new DefaultHttpClient();
//获得HttpResponse
HttpResponse httpResponse = httpclient.execute(httpRequest);
if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
//连接成功
//获取返回的字符串
String msg = EntityUtils.toString(
httpResponse.getEntity());
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
//显示结果
tvresult.setText(msg);
}
else{
tvresult.setText("请求失败");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
程序运行会得到同上面的结果。