3.Android HTTP请求方式之HttpURLConnection

引言:

好了,前两节我们已经对HTTP协议进行了学习。相信看完前两节的朋友对HTTP协议相比之前

应该更加熟悉吧。好吧。学了要用,相信非常多人都知道Android中HTTP的两种最主要的请求方式

他们各自是:HttpURLConnection和HttpClient。当然了解了最主要的两个后,我们实际开发中

可能并不会自己去慢慢写网络请求的代码,毕竟依据不同的web端接口,我们须要组织不同的数据

内容上传。这明显会添加我们的代码量,所以一般我们都会使用第三方的网络框架来请求网络,

经常使用的有volley,android-async-http,async-http-client,utils。loopj等等。有非常多,前面我们也说过

我们会解说retrofit封装我们的HTTP请求。一些基础的东西还是要会的,面试说不定会问呢,

并且了解底层的东西,看别人的框架的代码也不会一头雾水是吧,嗯,就唠叨这么多。開始本节内容~


两者的差别:

在学习他们两个的详细使用方法之前,我们先来对照下这两种方式有什么差别:

HttpURLConnection:继承至URLConnection,抽象类。无法直接实例化对象。通过调用openCollection( )方法获得对象实例,默认是带gzip压缩的。

HttpClient则是Apache给我们提供的HTTP訪问网络接口。相同也是无法直接创建实例的。而是通过

new DefaultHttpClient( )获得对象实例,默认不带gzip~

另外他们请求connection都是keep alive,而默认的User-Agent不同

前者是:Dalvik/16.0(Linux;U;Android 4.2.0;Lenovo S898T/4.6.13)

后者是:Apach-Http/UNAVAILABLE(java 1.4)

另外,Android API 22版本号后HttpClient就被无情的抛弃了~


HttpURLConnection的使用

①使用步骤:

  1. 创建一个URL对象:

    URL url = new URL(http://www.baidu.com);
  2. 调用URL对象的openConnection( )来获取HttpURLConnection对象实例:

    HttpURLConnection conn = (HttpURLConnection) url.openConnection( );
  3. 设置HTTP请求使用的方法:GET或者POST

    conn.setRequestMethod(“GET”);
  4. 设置连接超时,读取超时的毫秒数,以及server希望得到的一些消息头

    conn.setConnectTimeout(6*1000);

    conn.setReadTimeout(6 * 1000);
  5. 调用getInputStream( )方法获得server返回的输入流,然后输入流进行读取了

    InputStream in = conn.getInputStream( );
  6. 最后调用disconnect( )方法将HTTP连接关掉

    conn.disconnect( );

另外除了上面这些外,有时我们还可能须要对响应码进行推断,比方200:

if(conn.getResponseCode( ) != 200)然后一些处理

还有,可能有时我们并不须要传递什么參数,而是直接去訪问一个页面。我们能够直接用:

final InputStream in = new URL(“url”).openStream();

然后直接读流。只是这种方法适合于直接訪问页面的情况。底层实现事实上也是return openConnection().getInputStream(),并且我们还不能设置一些请求头的东东,用不用能够自己掂量掂量


②代码实例:

在開始每一个详细的样例编写前,我们先来编写一个工具类,用于将流转化为二进制数组:

StreamTool.java:

package com.jay.example.utils;
import java.io.ByteArrayOutputStream;
import java.io.InputStream; public class StreamTool {
//从流中读取数据
public static byte[] read(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = inStream.read(buffer)) != -1)
{
outStream.write(buffer,0,len);
}
inStream.close();
return outStream.toByteArray();
}
}

1.发送GET请求:

好了,那么接下来我们就来写个简单的样例来熟悉HttpURLConnection的使用方法吧:

先看执行的效果。然后我们再看实现代码,执行截图:

恩呢。看完执行效果,我们来開始写代码,我们程序的功能是:

定义了一个上下文菜单,通过点击不同的菜单项,做一些不同的网络请求,

载入图片,载入网页代码,依据代码载入网页到WebView中

由于篇幅原因。直接贴核心代码。要细致研究的能够自行下载代码參考

处理网络请求的类:GetData.java:

package com.jay.example.httpurlconnectiondemo.util;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL; public class GetData {
// 定义一个获取网络图片数据的方法:
public static byte[] getImage(String path) throws Exception {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置连接超时为5秒
conn.setConnectTimeout(5000);
// 设置请求类型为Get类型
conn.setRequestMethod("GET");
// 推断请求Url是否成功
if (conn.getResponseCode() != 200) {
throw new RuntimeException("请求url失败");
}
InputStream inStream = conn.getInputStream();
byte[] bt = StreamTool.read(inStream);
inStream.close();
return bt;
} // 获取网页的html源码
public static String getHtml(String path) throws Exception {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if (conn.getResponseCode() == 200) {
InputStream in = conn.getInputStream();
byte[] data = StreamTool.read(in);
String html = new String(data, "UTF-8");
return html;
}
return null;
}
}

代码非常easy,然后是MainActivity.java:

package com.jay.example.httpurlconnectiondemo;

import com.jay.example.httpurlconnectiondemo.util.GetData;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.webkit.WebView;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast; public class MainActivity extends Activity { private TextView txtMenu, txtshow;
private ImageView imgPic;
private WebView webView;
private ScrollView scroll;
private Bitmap bitmap;
private String detail="";
private boolean flag = false;
private final static String PIC_URL = "http://d.hiphotos.baidu.com/image/pic/item/b03533fa828ba61e0bd9f7ef4534970a304e593e.jpg";
private final static String HTML_URL = "http://www.baidu.com"; // 用于刷新界面
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 0x001:
hideAllWidget();
imgPic.setVisibility(View.VISIBLE);
imgPic.setImageBitmap(bitmap);
Toast.makeText(MainActivity.this, "图片载入完成", Toast.LENGTH_SHORT).show();
break;
case 0x002:
hideAllWidget();
scroll.setVisibility(View.VISIBLE);
txtshow.setText(detail);
Toast.makeText(MainActivity.this, "HTML代码载入完成", Toast.LENGTH_SHORT).show();
break;
case 0x003:
hideAllWidget();
webView.setVisibility(View.VISIBLE);
webView.loadDataWithBaseURL("",detail, "text/html","UTF-8","");
Toast.makeText(MainActivity.this, "网页载入完成", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
};
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
setView();
} private void initView() {
txtMenu = (TextView) findViewById(R.id.txtMenu);
txtshow = (TextView) findViewById(R.id.txtshow);
imgPic = (ImageView) findViewById(R.id.imgPic);
webView = (WebView) findViewById(R.id.webView);
scroll = (ScrollView) findViewById(R.id.scroll);
} private void setView() {
registerForContextMenu(txtMenu);
// webView.getSettings().setDefaultTextEncodingName("UTF-8");
} // 定义一个隐藏全部控件的方法:
private void hideAllWidget() {
imgPic.setVisibility(View.GONE);
scroll.setVisibility(View.GONE);
webView.setVisibility(View.GONE);
} @Override
// 重写上下文菜单的创建方法
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
MenuInflater inflator = new MenuInflater(this);
inflator.inflate(R.menu.menus, menu);
super.onCreateContextMenu(menu, v, menuInfo);
} // 上下文菜单被点击是触发该方法
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.one:
new Thread() {
public void run() {
try {
byte[] data = GetData.getImage(PIC_URL);
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
}
handler.sendEmptyMessage(0x001);
};
}.start();
break;
case R.id.two:
new Thread() {
public void run() {
try {
detail = GetData.getHtml(HTML_URL);
} catch (Exception e) {
e.printStackTrace();
}
handler.sendEmptyMessage(0x002);
};
}.start();
break;
case R.id.three:
if(detail.equals("")){
Toast.makeText(MainActivity.this, "先请求HTML先嘛~", Toast.LENGTH_SHORT).show();
}else{
handler.sendEmptyMessage(0x003);
}
break;
}
return true;
} }

注意事项:

用handler的原因就不用讲了吧~

另外我们载入html代码的使用的是webView的loadDataWithBaseURL而非LoadData。假设用LoadData又要去纠结中文乱码的问题,so…用loadDataWithBaseURL就能够不用纠结那么多了

另外有些页面可能须要我们提交一些參数,比方账号password:我们仅仅需把相应參数拼接到url尾部就可以。比方:

http://192.168.191.1:8080/ComentServer/LoginServlet?

passwd=123&name=Jack

然后服务端getParamater(“passwd”)这样就能够获得相应的參数了,我们请求时这些东西都会看得清清楚楚,所以GET方式并不安全


2.发送Post请求

有GET自然有POST,我们通过openConnection获取到的HttpURLConnection默认是进行Get请求的,

所以我们使用POST提交数据,应提前设置好相关的參数:conn.setRequestMethod(“POST”);

还有:conn.setDoOutput(true);conn.setDoInput(true);设置同意输入,输出

还有:conn.setUseCaches(false); POST方法不能缓存,要手动设置为false,详细实现看代码:

核心代码:

PostUtils.java

package com.jay.example.httpurlconnectiondemo.util;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder; public class PostUtils { public static String LOGIN_URL = "http://172.16.2.54:8080/HttpTest/ServletForPost"; public static String LoginByPost(String number,String passwd)
{
String msg = "";
try{
HttpURLConnection conn = (HttpURLConnection) new URL(LOGIN_URL).openConnection();
//设置请求方式,请求超时信息
conn.setRequestMethod("POST");
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
//设置执行输入,输出:
conn.setDoOutput(true);
conn.setDoInput(true);
//Post方式不能缓存,需手动设置为false
conn.setUseCaches(false);
//我们请求的数据:
String data = "passwd="+ URLEncoder.encode(passwd, "UTF-8")+
"&number="+ URLEncoder.encode(number, "UTF-8");
//这里能够写一些请求头的东东...
//获取输出流
OutputStream out = conn.getOutputStream();
out.write(data.getBytes());
out.flush();
if (conn.getResponseCode() == 200) {
// 获取响应的输入流对象
InputStream is = conn.getInputStream();
// 创建字节输出流对象
ByteArrayOutputStream message = new ByteArrayOutputStream();
// 定义读取的长度
int len = 0;
// 定义缓冲区
byte buffer[] = new byte[1024];
// 依照缓冲区的大小,循环读取
while ((len = is.read(buffer)) != -1) {
// 依据读取的长度写入到os对象中
message.write(buffer, 0, len);
}
// 释放资源
is.close();
message.close();
// 返回字符串
msg = new String(message.toByteArray());
return msg;
}
}catch(Exception e){e.printStackTrace();}
return msg;
}
}

执行效果图:


总结:

好的。本节关于HttpURLConnection的内容就到这里,主要介绍了两种不同的请求方式的实现,GET和POST,代码是比較简单的,就多多解释了~另外,另一些复杂的东西。以后有机会再深究…

下节我们来学习的是Apache为我峨嵋你提供的HttpClient。操作会更加简单。敬请期待~

本节代码下载:

Demo下载

Android之Http通信——3.Android HTTP请求方式:HttpURLConnection的更多相关文章

  1. Android线程间通信的几种实现方式

    1. 通过Handler机制: private void one() { handler=new Handler(){ @Override public void handleMessage(Mess ...

  2. Android之Socket通信、List加载更多、Spinner下拉列表

    Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务 ...

  3. Android开发--Socket通信

    一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是"请求-响应方式",即在请求时 ...

  4. SSH服务器与Android通信(2)--Android客户端接收数据

    基本原理是Android客户端通过HttpClient向服务器发出请求,服务器向Android客户端返回JSON字符串,Android客户端解析JSON字符串获得数据. 1. 新建一个Android项 ...

  5. Android学习笔记之HttpClient实现Http请求....

    PS:最近光忙着考试了....破组成原理都看吐了....搞的什么也不想干...写篇博客爽爽吧....貌似明天就考试了...sad... 学习笔记: 1.如何实现Http请求来实现通信.... 2.解决 ...

  6. Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)

    转载地址:http://blog.csdn.net/mad1989/article/details/9147661 ZERO.前言 有关通信原理内容是在网上或百科整理得到,代码部分为本人所写,如果不当 ...

  7. Android 之 Socket 通信

    Android 之 Socket 通信 联系一下 Socket 编程,之后需要将一个 JavaEE 项目移植到 Android,暂时现尝试写一个简单的 DEMO,理解一下 Socket Server ...

  8. 基于android的Socket通信

    一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户 ...

  9. Android基础_web通信

    一.发展史 1G 模拟制式手机,只能进行语音通话2G 数字制式手机,增加接收数据等功能3G 智能手机,它已经成了集语音通信和多媒体通信相结合,并且包括图像.音乐.网页浏览.电话会议以及其它一些信息服务 ...

随机推荐

  1. Vanya and Lanterns

    Description Vanya walks late at night along a straight street of length l, lit by n lanterns. Consid ...

  2. Java中@Deprecated、@SupressWarning、@Override的作用

    Annotation注解在 Java 中有着很广泛的,他是做为一种标识 为javac所识别.每一个注解 都对应这一个Java类  在java.lang包中 有三个注解  分别是 Deprecated  ...

  3. Ubuntu_开启root 登陆

    默认的安装完ubuntu ,root 用户没有开启 1.使用安装时的用户,先给root用户设置密码 设置root密码 sudo passwd root 之后会提示输入新的密码 切换到root用户 su ...

  4. express for node 路由route几种实现方式的思考

    1.路由实现方式和顺序 express框架创建的模板app,js中默认代码 var express = require('express'); var routes = require('./rout ...

  5. uva 705

    题意,给你迷宫算出其中个封闭空间的个数,以及求出所有封闭的空间的最大步长,但是给你的迷宫式“/”,“\”来标记的所以需要将每个格子分开来3*3的格子来算, 一开始按照2*2来算,2*2有临界情况不好算 ...

  6. mmtests使用简介

    1.简介 mmtests是一个可配置的测试套件,可以被MM开发者用来进行一个常规测试.理想情况下,它可以与LTP,xfstests等测试工具结合起来实现自动化测试. 2.软件组织 run-mmtest ...

  7. Oracle静态监听与动态监听概念全解析

    基于11g,linux5.5做出的测试,单实例数据库做出的测试. 1.注册 Instance到监听器去注册自己的Instance_name与ORACLE_HOME,还可以选择添加global_dbna ...

  8. javascript (十二)对象二

    JavaScript 中的所有事物都是对象:字符串.数字.数组.日期,等等. 在 JavaScript 中,对象是拥有属性和方法的数据. 属性和方法 属性是与对象相关的值. 方法是能够在对象上执行的动 ...

  9. 浙江大学PAT上机题解析之2-06. 数列求和

    给定某数字A(1<=A<=9)以及非负整数N(0<=N<=100000),求数列之和S = A + AA + AAA + … + AA…A(N个A).例如A=1, N=3时,S ...

  10. 微微信.NET:开源的ASP.NET微信公众号应用平台

    题记: 平时喜欢使用 C# 编程.近半年玩微信公众平台,看到一些微信的应用系统大多是PHP.Python的,于是就有想法做一套开放的 C# ASP.NET的微信应用系统. 微微信.NET  基于ASP ...