android Http协议访问网络
一、HttpURLConnection实现Http请求
1、HttpURLConnection基本用法
1、获取HttpURLConnection实例
2、new一个URL对象
3、传入URL对象(目标网络地址),并调用openConnection()方法
URL url = new URL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
4、得到HttpURLConnection后,可对其进行一些设置
- 设置HTTP请求所使用的方法(Get、Post):
Post方式请求网络,即提交数据给服务器时,需要在获取输入流之前把需要提交的数据写出,,每条数据以键值对的形式存在,数据与数据之间用&符号隔开。- 设置连接超时的毫秒数
- 设置读取超时的毫秒数
//"GET"方式访问网络
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
//"Post"方式访问网络
connection.setRequestMethod("POST");
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes("username=admin&password=123456");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
5、之后就可以通过调用getInputStream()方法获取服务器返回的输入流,并再对输入流进行读取
InputStream in = connection.getInputStream();
//下面对获取到的输入流进行读取
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
2、HttpURLConnection应用举例
例一:服务器获取网页并在客户端直接显示网页(在没有进行数据解析之前的到的是HTML代码)(GET)
/**
* http get方式
*/
private void sendRequestWithHttpURLConnection(){
//开启线程来发起网络请求
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
BufferedReader reader = 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();
//下面对获取到的输入流进行读取
reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine())!= null){
response.append(line);
}
showResponse(response.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if (reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
if (connection != null){
connection.disconnect();
}}}}
}).start();}
/**
*处理网络返回的数据
* @param response
*/
private void showResponse(final String response ){
runOnUiThread(new Runnable() {
@Override
public void run() {
//这里进行UI操作,将结果显示到界面
}});}
例二: 从服务器中获取照片并保存在硬盘中 (GET)
public class HttpUtils {
private static String URL_PATH = "http://...";
public HttpUtils(){
}
/**
* 将服务器中读取的输入流(数据)保存在硬盘中(客户端中显示)
*/
public static void saveImageToDisk(){
InputStream inputStream = getInputStream();
byte[] data = new byte[1024];
int len = 0;
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream("D:\\test.png");
while((len = inputStream.read(data)) != -1){
fileOutputStream.write(data,0,len );
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭输入、输出流
if(inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fileOutputStream != null){
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 发送http请求
* @return 返回从服务器得到的数据流
*/
public static InputStream getInputStream(){
InputStream inputStream = null;
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL(URL_PATH);
if(url != null){
httpURLConnection = (HttpURLConnection) url.openConnection();
//设置网络的超时时间与读取时间以及本次请求方式
httpURLConnection.setConnectTimeout(8000);
httpURLConnection.setReadTimeout(8000);
httpURLConnection.setRequestMethod("GET");
//设置打开输入流
httpURLConnection.setDoInput(true);
//获得请求的状态码,并判断
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == 200){
//此时可以从服务器获取输入流
inputStream = httpURLConnection.getInputStream();
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭连接
if (httpURLConnection != null){
httpURLConnection.disconnect();
}
}
return inputStream;
}
public static void main(String[] args){
//从服务器获得图片保存到本地
saveImageToDisk();
}
}
例三:用户名以及密码等数据提交给服务器 (POST)
public class HttpUtilsPost {
public HttpUtilsPost(){
}
//请求服务器端的url
private static String PATH = "";
private static URL url;
//通过静态代码模块实例化URL对象
static{
try {
url = new URL(PATH);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
/**
*
* @param params 填写的url的参数
* @param encode 字节编码
* @return
*/
public static String sendPostMessage(Map<String,String> params,String encode){
//作为StringBuffer初始化的字符串
StringBuffer buffer = new StringBuffer(PATH);
buffer.append("?");
if (params != null && !params.isEmpty()){
for(Map.Entry<String,String> entry : params.entrySet()){
try {
buffer.append(entry.getKey())
.append("=")
.append(URLEncoder.encode(entry.getValue(),encode));
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setConnectTimeout(8000);
httpURLConnection.setReadTimeout(8000);
httpURLConnection.setDoInput(true); //表示从服务器获取数据
httpURLConnection.setDoOutput(true); //表示向服务器写数据
//获得上传信息的字节大小以及长度
byte[] myData = buffer.toString().getBytes();
//设置请求体的类型是文本类型
httpURLConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
httpURLConnection.setRequestProperty("Content-Length",String.valueOf(myData.length));
//获得输出流,向服务器输出数据
OutputStream outputStream = httpURLConnection.getOutputStream();
outputStream.write(myData);
//获得服务器响应的结果和状态码
int responseCode = httpURLConnection.getResponseCode();
if(responseCode == 200){
return changeInputStream(httpURLConnection.getInputStream(),"utf-8");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println(buffer.toString());
return "";
}
/**
* 将一个输入流转化为指定编码的字符串
* @param inputStream
* @param encode
* @return
*/
private static String changeInputStream(InputStream inputStream,String encode) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); //一般表示内存流
byte[] data = new byte[1024];
int len = 0;
String result = "";
if(inputStream != null){
try {
while((len = inputStream.read(data))!= -1 ){
outputStream.write(data,0,len);
}
result = new String(outputStream.toByteArray(),"utf-8");
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
public static void main(String[] args){
Map<String,String> params = new HashMap<String, String>();
params.put("username","admin");
params.put("password","123");
sendPostMessage(params,"utf-8");
}
}
二、OkHttp实现HTTP申请
1、OkHttp的基本用法
有许多的网络通信库都可以代替原生的HttpURLConnection,而其中OKHttp是做的最出色的一个。
OkHttp是由Square公司开发的,这个公司在开源事业上面贡献良多,除了OkHttp之外,还开发了像Picasso、Retrofit等著名的开源项目。OkHttp不仅在接口封装上面做的简单易用,就连在底层实现上也是自成一派,比起原声的HttpURLConnection,可以说是有过之而不及,现在已经成为广大Android开发者首选的网络通信库。
1、创建一个OkHttpClient实例
OkHttpClient okHttpClient = new OkHttpClient();
2、创建一个空的Request对象
Request request = new Request.Builder().build();
3、丰富Request对象,在build()方法之前连缀很多其他的方法。
发起GET请求:
Request request = new Request.Builder() .url(PATH) .build();
发起POST请求:
首先构建出一个RequestBody对象来存放待提交的参数,然后在Request.Builder()方法中调用Post()方法,并将RequestBody对象传入Request request = new Request.Builder() .url(PATH) .build(); Request request = new Request.Builder() .url(PATH) .post(requestBody) .build();
4、创建一个Call对象,通过调用OkHttpClient的newCall()方法创建,并调用它的execute()方法来发送请求并获取服务器返回的数据。
Response response = okHttpClient.newCall(request).execute();
其中Response对象就是服务器返回的数据了,我们可以使用如下写法来得到具体的返回数据
String responseData = response.body().string();
2、OkHttp应用举例
将从服务器请求到的数据显示到界面的TextView上。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mTextView;
private Button mButton;
private static String PATH = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = ( TextView) findViewById(R.id.wv_http_test);
mButton = (Button)findViewById(R.id.btn_send_response);
mButton.setOnClickListener((View.OnClickListener) this);
}
@Override
public void onClick(View view){
if (view.getId() == R.id.wv_http_test){
sendRequestWithHttpURLConnection();
}
}
/**
* 发送网络请求,并得到返回数据
*/
private void sendRequestWithHttpURLConnection() {
//开启一个线程来发起网络请求
new Thread(new Runnable() {
@Override
public void run() {
//创建一个OkHttpClient实例
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(PATH)
.build();
try {
Response response = okHttpClient.newCall(request).execute();
String responseData = response.body().string();
showResponse(responseData);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 将服务器返回的数据显示到界面上
* @param responseData
*/
private void showResponse(final String responseData) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText(responseData);
}
});
}
}
三、实际编程
由于一个应用程序很可能会在许多地方都使用到网络功能,而发送HTTP请求的代码基本都是相同的,如果我们每次都去编写一遍发送HTTP请求的代码,这显然是非常差劲的做法。
通常情况下我们都应该将这些通用的网络操作提取到一个公共的类里,并提供一个静态方法,当想要发起网络请求的时候,只需要简单地调用一下这个方法即可。
1、 HttpURLConnection发送HTTP请求:
(1)、 基本思路:
public class HttpUtil {
public HttpUtil(){
}
public static String sendHttpRequest(String PATH){
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL(PATH);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setConnectTimeout(8000);
httpURLConnection.setReadTimeout(8000);
httpURLConnection.setDoInput(true);
httpURLConnection.setDoOutput(true);
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder response = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null){
response.append(line);
}
return response.toString();
} catch (IOException e) {
e.printStackTrace();
return e.getMessage();
}
}finally {
if(httpURLConnection != null){
httpURLConnection.disconnect();
}
}
}
}
(2)、由于此时sendHttpRequest()方法内没有开启线程,这样可能会导致在调用sendHttpRequest()方法时使得主线程被阻塞。但是直接在sendHttpRequest()方法内开启线程,无法返回服务器响应的数据。因此,我们在sendHttpRequest()方法中使用回调方法。
****(1)、首先定义一个接口:
public interface HttpCallbackListener {
/**
* 表示当服务器成功响应我们请求的时候调用
* @param response 代表服务器返回的数据
*/
void onFinish(String response);
/**
* 表表示当进行网络操作出现错误的时候被调用
* @param e 表示错误的详细信息
*/
void onError(Exception e);
}
****(2)、修改sendHttpRequest()方法:首先给此方法添加一个HttpCallbackListener的参数,并在此方法内部开启一个子线程,在子线程中进行具体的网络操作。子线程是无法用return进行数据返回的,因此这里我们将服务器响应的数据传入了HttpCallbackListener的onFinish()方法。
public class HttpUtil {
public static void sendHttpRequest(final String PATH, final HttpCallbackListener httpCallbackListener){
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL(PATH);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setConnectTimeout(8000);
httpURLConnection.setReadTimeout(8000);
httpURLConnection.setDoInput(true);
httpURLConnection.setDoOutput(true);
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder response = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null){
response.append(line);
}
if(httpCallbackListener != null){
// 回调onFinish()方法
httpCallbackListener.onFinish(response.toString());
}
} catch (IOException e) {
if(httpCallbackListener != null){
// 回调onError()方法
httpCallbackListener.onError(e);
}
}finally {
if(httpURLConnection != null){
httpURLConnection.disconnect();
}
}
}
}).start();
}
}
****(3)、调用sendHttpRequest()方法:在调用时要传入HttpCallbackListene的实例。
String PATH = "";
HttpUtil.sendHttpRequest(PATH,new HttpCallbackListener(){
@Override
public void onFinish(String response) {
//在这里根据返回内容执行具体的逻辑
}
@Override
public void onError(Exception e) {
//在这里对异常情况进行处理
}
} );
2、OkHttp发送网络请求
public class HttpUtilOkHttp {
public HttpUtilOkHttp(){
}
public static void sendHttpRequestOkHttp(final String PATH, final okhttp3.Callback callback){
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(PATH)
.build();
okHttpClient.newCall(request).enqueue(callback);
}
}
其中,我们用enqueue()方法并传入okhttp3.Callback参数代替之前的execute()方法,是因为在此方法内OkHttp已经帮我们开好子线程,并且会在此子线程中完成网络请求,并将最终的请求结果回调okhttp3.Callback中。
HttpUtilOkHttp.sendHttpRequestOkHttp(PATH, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});