须知少年凌云志,曾许人间第一流。这篇文章主要讲述Android实战之旅 006Android中的HTTP通信相关的知识,希望能为你提供帮助。
对于http协议我想很多朋友并不陌生,
一次HTTP操作称为一个事务。http中需要掌握的基础知识包括:
URL,http三次握手,
http请求头信息,
http请求的方式,
http响应码信息,
http协议的特点,
TCP/IP四层协议,
OSI七层协议,
以及http1.0和http1.1区别。这里需要注意的http无连接:
限制每一次连接只处理一个请求,
服务器处理完客户的请求,
并收到客户的应答后,
即断开连接。http无状态:
协议对于事务处理没有记忆能力,
缺少状态意味着如果后续处理需要前面的信息,
则它必须重传。基础知识可以参考:
http://blog.csdn.net/davebobo/article/details/52728841
开发环境:
android Studio1.5 RC 1
Myeclipse 10
jdk-7u80-windows-x64
apache-tomcat-7.0.69
一、HttpURLConnection的介绍及使用 案例一:
http访问百度,
WebView展示内容
新建http_01项目,
首先我们需要进行网络操作,
在AndroidManifest.xml中添加permission权限
<
uses-permission android:name=
"
android.permission.INTERNET"
/>
activity_main.xml中添加WebView组件
<
WebView
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:id=
"
@
+
id/webView"
android:layout_alignParentTop=
"
true"
android:layout_alignParentLeft=
"
true"
android:layout_alignParentStart=
"
true"
android:layout_alignParentRight=
"
true"
android:layout_alignParentEnd=
"
true"
android:layout_alignParentBottom=
"
true"
/>
由于网络操作是一个耗时操作, 我们在线程中执行, 创建VisitWeb类继承Thread重写run方法处理网络耗时操作。
package com.davebobo.http_01;
import android.media.tv.TvView;
import android.os.Handler;
import android.webkit.WebView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by DaveBobo on 2016/10/9.
*/
public class VisitWeb extends Thread{privateString url;
private WebView webView;
private Handler handler;
public VisitWeb(String url, WebView webView, Handler handler){
this.url =
url;
this.webView =
webView;
this.handler =
handler;
}@
Override
public void run() {
super.run();
try {
URL httpUrl =
new URL(url);
try {
HttpURLConnection conn =
(HttpURLConnection)httpUrl.openConnection();
conn.setReadTimeout(5000);
//设置超时等待
conn.setRequestMethod("
GET"
);
final StringBuffer sb =
new StringBuffer();
//缓存
//通过网址回传网页流数据
BufferedReader reader =
new BufferedReader(new InputStreamReader(conn.getInputStream()));
String str;
while ((str =
reader.readLine())!=
null){
sb.append(str);
}handler.post(new Runnable(){
@
Override
public void run() {
webView.loadData(sb.toString(),"
text/html;
charset=
utf-8"
,null);
}
});
} catch (IOException e) {
e.printStackTrace();
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
在MainActivity中查找WebView创建VisitWeb对象调用它的start()方法。
package com.davebobo.http_01;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {private WebView webView;
private Handler handler =
new Handler();
private ImageView imageView;
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView =
(WebView) findViewById(R.id.webView);
imageView =
(ImageView) findViewById(R.id.imageView);
new VisitWeb("
https://www.baidu.com/"
,webView,handler).start();
//new DownImage("
http://avatar.csdn.net/3/B/3/1_davebobo.jpg"
,imageView,handler).start();
}
}
运行模拟器查看效果
文章图片
创建URL对象, 通过HttpURLConnection设置请求的方式, 得到读入流放到缓存区中, 通过webView加载本地的页面信息。
案例二: 通过网络请求下载图片到本地
在activity_main.xml中将WebView设置为隐藏, 添加 ImageView
<
WebView
android:visibility=
"
gone"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:id=
"
@
+
id/webView"
android:layout_alignParentTop=
"
true"
android:layout_alignParentLeft=
"
true"
android:layout_alignParentStart=
"
true"
android:layout_alignParentRight=
"
true"
android:layout_alignParentEnd=
"
true"
android:layout_alignParentBottom=
"
true"
/>
<
ImageView
android:layout_width=
"
200dp"
android:layout_height=
"
200dp"
android:id=
"
@
+
id/imageView"
android:layout_centerVertical=
"
true"
android:layout_centerHorizontal=
"
true"
/>
创建DownImage继承自Thread
package com.davebobo.http_01;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.Handler;
import android.widget.ImageView;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by DaveBobo on 2016/10/9.
*/
public class DownImage extends Thread{privateString url;
private ImageView imageView;
private Handler handler;
public DownImage(String url, ImageView imageView, Handler handler){
this.url =
url;
this.imageView =
imageView;
this.handler =
handler;
}@
Override
public void run() {
super.run();
try {
URL httpUrl =
new URL(url);
try {
HttpURLConnection conn =
(HttpURLConnection)httpUrl.openConnection();
conn.setReadTimeout(5000);
conn.setRequestMethod("
GET"
);
conn.setDoInput(true);
InputStream in =
conn.getInputStream();
FileOutputStream out =
null;
File downloadFile =
null;
String fileName =
String.valueOf(System.currentTimeMillis());
//判断SD卡是否存在
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File parent =
Environment.getExternalStorageDirectory();
//获取SD目录
downloadFile =
new File(parent,fileName);
out =
new FileOutputStream(downloadFile);
}byte[] b =
new byte[2*1024];
int len;
if (out!=
null){
while ((len =
in.read(b))!=
-1){
out.write(b,0,len);
}
}final Bitmap bitmap =
BitmapFactory.decodeFile(downloadFile.getAbsolutePath());
handler.post(new Runnable() {
@
Override
public void run() {
imageView.setImageBitmap(bitmap);
}
});
} catch (IOException e) {
e.printStackTrace();
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
在MainActivity中初始化ImageView组件并调用start()方法。
package com.davebobo.http_01;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {private WebView webView;
private Handler handler =
new Handler();
private ImageView imageView;
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView =
(WebView) findViewById(R.id.webView);
imageView =
(ImageView) findViewById(R.id.imageView);
//new VisitWeb("
https://www.baidu.com/"
,webView,handler).start();
new DownImage("
http://avatar.csdn.net/3/B/3/1_davebobo.jpg"
,imageView,handler).start();
}
}
运行效果
文章图片
二、通过HttpURLConnection传递post, get参数
1.服务器端
首先我们使用myeclipse创建j2ee WEB项目, 项目名称为web
文章图片
新建MyServlet的servlet程序, 重写doGet和doPost方法, 为了简单重写一个方法即可。
package com.davebobo.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {String name =
request.getParameter("
name"
);
String age =
request.getParameter("
age"
);
PrintWriter out =
response.getWriter();
out.println("
name=
"
+
name+
"
age=
"
+
age);
System.out.println("
name=
"
+
name);
System.out.println("
age=
"
+
age);
}}
在index.jsp中添加form表单通过action访问servlet
<
form action=
"
servlet/MyServlet"
method=
"
get"
>
name:<
input type=
"
text"
name=
"
name"
>
<
br/>
age:<
input type=
"
text"
name=
"
age"
>
<
br/>
submit:<
input type=
"
submit"
value=
"
submit"
>
<
br/>
<
/form>
运行效果
文章图片
2 客户端
当我们的服务器端搭建成功后, 开始编写客户端, 新建一个RegistActivity继承自AppCompatActivity
package com.davebobo.http_01;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
/**
* Created by DaveBobo on 2016/10/26.
*/
public class RegistActivity extends AppCompatActivity {private EditText name;
privateEditText age;
private Button regist;
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.regist);
name =
(EditText) findViewById(R.id.name);
age =
(EditText)findViewById(R.id.age);
regist =
(Button) findViewById(R.id.regist);
regist.setOnClickListener(new View.OnClickListener() {
@
Override
public void onClick(View v) {
String url =
"
http://192.168.1.100:8080/web/servlet/MyServlet"
;
new HttpTherad1(url,name.getText().toString(),age.getText().toString()).start();
}
});
}
}
RegistActivity对应的布局文件regist.xml为:
<
?xml version=
"
1.0"
encoding=
"
utf-8"
?>
<
RelativeLayout 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:paddingBottom=
"
@
dimen/activity_vertical_margin"
android:paddingLeft=
"
@
dimen/activity_horizontal_margin"
android:paddingRight=
"
@
dimen/activity_horizontal_margin"
android:paddingTop=
"
@
dimen/activity_vertical_margin"
tools:context=
"
com.davebobo.http_01.MainActivity"
>
<
RelativeLayout
android:id=
"
@
+
id/name_layout"
android:layout_width=
"
fill_parent"
android:layout_height=
"
wrap_content"
>
<
TextView
android:id=
"
@
+
id/name_textView"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:layout_alignParentLeft=
"
true"
android:layout_centerInParent=
"
true"
android:text=
"
name"
/>
<
EditText
android:layout_toRightOf=
"
@
id/name_textView"
android:id=
"
@
+
id/name"
android:layout_width=
"
fill_parent"
android:layout_height=
"
wrap_content"
/>
<
/RelativeLayout>
<
RelativeLayout
android:layout_below=
"
@
id/name_layout"
android:id=
"
@
+
id/age_layout"
android:layout_width=
"
fill_parent"
android:layout_height=
"
wrap_content"
>
<
TextView
android:id=
"
@
+
id/age_textView"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:layout_alignParentLeft=
"
true"
android:layout_centerInParent=
"
true"
android:text=
"
age"
/>
<
EditText
android:id=
"
@
+
id/age"
android:layout_toRightOf=
"
@
id/age_textView"
android:layout_width=
"
fill_parent"
android:layout_height=
"
wrap_content"
/>
<
/RelativeLayout>
<
Button
android:id=
"
@
+
id/regist"
android:layout_below=
"
@
id/age_layout"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:text=
"
regist"
/>
<
/RelativeLayout>
由于我们需要进行网络操作单独新建一个线程类HttpTherad1编写相关的get和post方法。
package com.davebobo.http_01;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by DaveBobo on 2016/10/26.
*/
public class HttpTherad1 extends Thread{privateString url;
privateString name;
privateString age;
public HttpTherad1(String url,String name,String age){
this.url =
url;
this.name =
name;
this.age =
age;
}privatevoid doGet(){
url =
url+
"
?name=
"
+
name+
"
&
age=
"
+
age;
//get方式只能通过url进行传参
try {
URL httpUrl =
new URL(url);
try {
HttpURLConnection conn =
(HttpURLConnection) httpUrl.openConnection();
conn.setRequestMethod("
GET"
);
conn.setReadTimeout(5000);
BufferedReader reader=
new BufferedReader(new InputStreamReader(conn.getInputStream()));
String str;
StringBuffer sb =
new StringBuffer();
while ((str =
reader.readLine())!=
null ){
sb.append(str);
}
System.out.println("
result:"
+
sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
} catch (MalformedURLException e) {
e.printStackTrace();
}}private void doPost(){try {
URL httpUrl =
new URL(url);
HttpURLConnection conn =
(HttpURLConnection) httpUrl.openConnection();
conn.setRequestMethod("
POST"
);
conn.setReadTimeout(5000);
OutputStream out =
conn.getOutputStream();
String content =
"
name=
"
+
name+
"
&
age=
"
+
age;
out.write(content.getBytes());
BufferedReader reader =
new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuffer sb =
new StringBuffer();
String str;
while ((str=
reader.readLine())!=
null){
sb.append(str);
}
System.out.println(sb.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}}
@
Override
public void run() {
super.run();
//doGet();
doPost();
}
}
客户端请求get方法 post方法测试:
文章图片
文章图片
服务器打印出结果:
文章图片
由此我们可以看出doGet是通过URL方式进行发送, 而doPost是通过OutputStream的方式进行发送。那有什么区别呢? 一般地如果发送的实体数据比较少的话我们使用doGet方式进行发送, 这种方式对发送的实体数据是有一定的限制的( 几K) , 如果发送的数据量比较大时我们使用doPost。另外通过doGet方式发送我们通过url将数据暴露出来, 如果想安全的话也采用doPost通过实体去发送。
三、httpClient的使用 Java给我们提供了一套访问网络的API但不远远足够我们开发应用程序, 在这里我们使用httpClient进行GET和POST请求。在API 23中, Google已经移除了Apache HttpClient相关的类 。谷歌推荐使用HttpUrlConnection, 如果要继续使用Apache HttpClient, 导入相应的jar包并需要在
Eclipse下libs里添加org.apache.http.legacy.jar,
Android studio里在相应的module下的build.gradle中加入如下即可。
导入我们用到的jar包httpclient-4.5.2.jar httpcore-4.4.4.jar
android {
useLibrary '
org.apache.http.legacy'
}android {
packagingOptions {
exclude '
META-INF/DEPENDENCIES.txt'
exclude '
META-INF/LICENSE.txt'
exclude '
META-INF/NOTICE.txt'
exclude '
META-INF/NOTICE'
exclude '
META-INF/LICENSE'
exclude '
META-INF/DEPENDENCIES'
exclude '
META-INF/notice.txt'
exclude '
META-INF/license.txt'
exclude '
META-INF/dependencies.txt'
exclude '
META-INF/LGPL2.1'
}
}
新建HttpClientThread继承自Thread
package com.davebobo.http_01;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
/**
* Created by DaveBobo on 2016/10/26.
*/
public class HttpClientThread extends Thread{privateString url;
privateString name;
privateString age;
public HttpClientThread(String url){
this.url=
url;
}
public HttpClientThread(String url,String name,String age){
this.url =
url;
this.name =
name;
this.age =
age;
}private void dohttpClientGet(){
//创建HttpGet对象
HttpGet httpGet =
new HttpGet(url);
//创建HttpClient对象
HttpClient client =
new DefaultHttpClient();
HttpResponse response;
try {
//发送请求
response =
client.execute(httpGet);
//判断类型
if (response.getStatusLine().getStatusCode()=
=
HttpStatus.SC_OK){
//取出服务器返回的数据
String content =
EntityUtils.toString(response.getEntity());
System.out.println("
content----->
"
+
content);
}
} catch (IOException e) {
e.printStackTrace();
}
}public void doHttpClientPost(){HttpClient client =
new DefaultHttpClient();
HttpPost post =
new HttpPost(url);
//通过NameValuePair存储数据
ArrayList<
NameValuePair>
list =
new ArrayList<
NameValuePair>
();
list.add(new BasicNameValuePair("
name"
,name));
list.add(new BasicNameValuePair("
age"
,age));
try {
//设置要发送的数据
post.setEntity(new UrlEncodedFormEntity(list));
try {
HttpResponse response =
client.execute(post);
if (response.getStatusLine().getStatusCode()=
=
HttpStatus.SC_OK){
String content =
EntityUtils.toString(response.getEntity());
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
@
Override
public void run() {
//dohttpClientGet();
doHttpClientPost();
}
}
RegistActivity.java中的onCreate方法测试
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.regist);
name =
(EditText) findViewById(R.id.name);
age =
(EditText)findViewById(R.id.age);
regist =
(Button) findViewById(R.id.regist);
regist.setOnClickListener(new View.OnClickListener() {
@
Override
public void onClick(View v) {
String url =
"
http://192.168.1.100:8080/web/servlet/MyServlet"
;
//new HttpTherad1(url,name.getText().toString(),age.getText().toString()).start();
//url =
url+
"
?name=
"
+
name.getText().toString()+
"
&
age=
"
+
age.getText().toString();
//new HttpClientThread(url).start();
new HttpClientThread(url,name.getText().toString(),age.getText().toString()).start();
}
});
}
文章图片
文章图片
文章图片
四、Http多线程下载和文件上传 案例一: Http多线程下载
首先我们在服务器端拷贝一张图片并重新发布。
文章图片
新建DownLoadActivity.继承自AppCompatActivity
package com.davebobo.http_01;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
/**
* Created by DaveBobo on 2016/10/26.
*/
public class DownLoadActivity extends AppCompatActivity {private Button button;
private TextView textView;
private int count =
0;
//更新UI操作
private Handler handler =
new Handler(){
publicvoid handleMessage(android.os.Message msg){
int result =
msg.what;
count+
=
result;
if (count=
=
3){
textView.setText("
download success!"
);
}};
};
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.download);
button =
(Button) findViewById(R.id.button1);
textView =
(TextView) findViewById(R.id.textView);
button.setOnClickListener(new View.OnClickListener() {
@
Override
public void onClick(View v) {new Thread(){
public voidrun(){
DownLoad load =
new DownLoad(handler);
load.downLoadFile("
http://192.168.1.100:8080/web/head.jpg"
);
}
}.start();
}
});
}
}
多线程下载业务处理在DownLoad.java中
package com.davebobo.http_01;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* Created by DaveBobo on 2016/10/26.
*/
public class DownLoad {private Handler handler;
public DownLoad(Handler handler){
this.handler =
handler;
}
//创建线程池
private Executor threadPool =
Executors.newFixedThreadPool(3);
static class DownLoadRunnable implements Runnable{
private String url;
private String fileName;
private long start;
private long end;
private Handler handler;
DownLoadRunnable(String url,String fileName,long start,long end,Handler handler){
this.url =
url;
this.fileName =
fileName;
this.start =
start;
this.end =
end;
this.handler =
handler;
}
@
Override
public void run() {
try {
URLhttpUrl =
new URL(url);
HttpURLConnection conn =
(HttpURLConnection)httpUrl.openConnection();
conn.setRequestMethod("
GET"
);
conn.setReadTimeout(5000);
conn.setRequestProperty("
Range"
, "
bytes=
"
+
start +
"
-"
+
end);
RandomAccessFile access =
new RandomAccessFile(new File(fileName),"
rwd"
);
access.seek(start);
InputStream in =
conn.getInputStream();
byte[] b=
new byte[1024*4];
int len=
0;
while ((len =
in.read(b))!=
-1){
access.write(b,0,len);
}
if (access!=
null){
access.close();
}
if (in!=
null){
in.close();
}Message message =
new Message();
message.what =
1;
handler.sendMessage(message);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void downLoadFile(String url){try {
URLhttpUrl =
new URL(url);
HttpURLConnection conn =
(HttpURLConnection)httpUrl.openConnection();
conn.setRequestMethod("
GET"
);
conn.setReadTimeout(5000);
/**
* 11/3 32
* 第一个线程 0-2
* 第二个线程 3-5
* 第三个线程 6-10
*/
int count =
conn.getContentLength();
int block =
count/3;
String fileName =
getFileName(url);
File parent =
Environment.getExternalStorageDirectory();
File fileDownLoad =
new File(parent,fileName);
for (int i=
0;
i<
3;
i+
+
){
long start =
i*block;
long end =
(i+
1)*block-1;
if (i=
=
2){
end =
count;
}
DownLoadRunnable runnable =
new DownLoadRunnable(url,fileDownLoad.getAbsolutePath(),start,end,handler);
threadPool.execute(runnable);
;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}public String getFileName(String url){
return url.substring(url.lastIndexOf("
/"
)+
1);
}
}
布局配置文件很简单
<
?xml version=
"
1.0"
encoding=
"
utf-8"
?>
<
RelativeLayout 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:paddingBottom=
"
@
dimen/activity_vertical_margin"
android:paddingLeft=
"
@
dimen/activity_horizontal_margin"
android:paddingRight=
"
@
dimen/activity_horizontal_margin"
android:paddingTop=
"
@
dimen/activity_vertical_margin"
tools:context=
"
com.davebobo.http_01.MainActivity"
>
<
Button
android:id=
"
@
+
id/button1"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:layout_alignParentTop=
"
true"
android:layout_centerInParent=
"
true"
android:text=
"
Button"
/>
<
TextView
android:id=
"
@
+
id/textView"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:layout_centerInParent=
"
true"
/>
<
/RelativeLayout>
在AndroidManifest.xml中配置默认加载的Activity
<
activity android:name=
"
.DownLoadActivity"
>
<
intent-filter>
<
action android:name=
"
android.intent.action.MAIN"
/>
<
category android:name=
"
android.intent.category.LAUNCHER"
/>
<
/intent-filter>
<
/activity>
运行测试结果
文章图片
文章图片
知识总结:
1.Http协议字段Range “bytes= ”+ start+ " -' + end
2.RandomAccessFile设置写入的位置
3.开启线程发送网络请求
案例二: http文件上传
服务器端:
在这里我们需要用到servlet3.0的新特性, 不需要添加额外的jar包, servlet3.0对文件的操作做了很好的支持。开发Servlet3的程序需要一定的环境支持。Servlet3是Java EE6规范的一部分, MyEclipse10和Tomcat7都提供了对Java EE6规范的支持。Tomcat需要Tomcat7才支持Java EE6, Tomcat7需要使用JDK6。
使用Myeclipse新建servlet命名为AnnotationUpload
文章图片
对上图进行如下操作: 如果要使用Servlet3.0新特性——采用注释的方式该servlet接受的请求路径, 则取消上图被红框框定的复选框( 取消后web.xml文件中将不会含有创建的Servlet的一些配置信息, 此处取消该复选选中项) ; 否则直接点击“Finish”按钮即可。至此3.0版的Servlet创建成功。将该Servlet修改为如下代码:
package com.davebobo.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
/**
* 使用注解描述Servlet
* @
author DaveBobo
*//**
* 注解WebServlet用来描述一个Servlet
* 属性name描述Servlet的名字,可选
* 属性urlPatterns定义访问的URL,或者使用属性value定义访问的URL.(定义访问的URL是必选属性)
*/
@
WebServlet(name=
"
AnnotationUpload"
,urlPatterns=
"
/AnnotationUpload"
)
@
MultipartConfig(
location =
"
D:\\\\"
)
public class AnnotationUpload extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Part part =
request.getPart("
file"
);
part.write("
upload.jpg"
);
response.setCharacterEncoding("
UTF-8"
);
PrintWriter out =
response.getWriter();
out.print("
upload success"
);
System.out.println("
upload success"
);
}}
新建upload.jsp
<
%@
page language=
"
java"
import=
"
java.util.*"
pageEncoding=
"
ISO-8859-1"
%>
<
%
String path =
request.getContextPath();
String basePath =
request.getScheme()+
"
://"
+
request.getServerName()+
"
:"
+
request.getServerPort()+
path+
"
/"
;
%>
<
!DOCTYPE HTML PUBLIC "
-//W3C//DTD HTML 4.01 Transitional//EN"
>
<
html>
<
head>
<
base href=
"
<
%=
basePath%>
"
>
<
title>
My JSP '
upload.jsp'
starting page<
/title>
<
meta http-equiv=
"
pragma"
content=
"
no-cache"
>
<
meta http-equiv=
"
cache-control"
content=
"
no-cache"
>
<
meta http-equiv=
"
expires"
content=
"
0"
>
<
meta http-equiv=
"
keywords"
content=
"
keyword1,keyword2,keyword3"
>
<
meta http-equiv=
"
description"
content=
"
This is my page"
>
<
!--
<
link rel=
"
stylesheet"
type=
"
text/css"
href=
"
styles.css"
>
-->
<
/head>
<
body>
<
form action=
"
AnnotationUpload"
method=
"
post"
enctype=
"
multipart/form-data"
>
<
input type =
"
file"
name=
"
file"
/>
<
br>
<
input type=
"
submit"
value=
"
submit"
/>
<
br>
<
/form>
<
/body>
<
/html>
运行测试图片传到指定文件夹中。
【Android实战之旅 006Android中的HTTP通信】
文章图片
客户端:
UploadThread.java
package com.davebobo.http_01;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by DaveBobo on 2016/10/26.
*/
public class UploadThread extends Thread{private String fileName;
private String url;
publicUploadThread(String url,String fileName){
this.url =
url;
this.fileName =
fileName;
}
@
Override
public void run() {
//上传表单分割线的描述符
String boundary =
"
---------------------------7e01ee305f069a"
;
//Content-Type
String reqCon =
"
-----------------------------7e01ee305f069a"
;
//请求正文比Content-Type多两个-
String prefix =
"
--"
;
String end=
"
\\r\\n"
;
try {
URL httpUrl =
new URL(url);
HttpURLConnection conn =
(HttpURLConnection) httpUrl.openConnection();
conn.setRequestMethod("
POST"
);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("
Content-Type"
,
"
multipart/form-data;
boundary=
"
+
boundary);
DataOutputStream out =
new DataOutputStream(conn.getOutputStream());
out.writeBytes(prefix+
boundary+
end);
out.writeBytes("
Content-Disposition: form-data;
"
+
"
name=
\\"
file\\"
;
filename=
\\"
"
+
"
head.jpg"
+
"
\\"
"
+
end);
//实体数据
out.writeBytes(end);
FileInputStream fileInputStream =
new FileInputStream(new File(fileName));
byte[] b =
new byte[1024*4];
int len;
while ((len=
fileInputStream.read(b))!=
-1){
out.write(b,0, len);
}
out.writeBytes(end);
out.writeBytes(prefix +
boundary +
prefix +
end);
out.flush();
BufferedReader reader =
new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuffer sb =
new StringBuffer();
String str;
while ((str=
reader.readLine())!=
null){
sb.append(str);
System.out.println("
respose:"
+
sb.toString());
if (out!=
null){
out.close();
}
if (reader!=
null){
reader.close();
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这儿需要注意我们拼写上传表单分割线的描述符时, 需要使用IE的开发人员工具。
文章图片
UploadActivity.java
package com.davebobo.http_01;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import java.io.File;
/**
* Created by DaveBobo on 2016/10/27.
*/
public class UploadActivity extends AppCompatActivity {private Button button;
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.upload);
button =
(Button) findViewById(R.id.button2);
button.setOnClickListener(new View.OnClickListener() {
@
Override
public void onClick(View v) {
String url=
"
http://192.168.1.100:8080/web/AnnotationUpload"
;
File file =
Environment.getExternalStorageDirectory();
File fileAbs =
new File(file,"
head.jpg"
);
String fileName=
fileAbs.getAbsolutePath();
UploadThread thread =
new UploadThread(url,fileName);
thread.start();
}
});
}
}
布局文件upload.xml, 就一个button
<
?xml version=
"
1.0"
encoding=
"
utf-8"
?>
<
LinearLayout xmlns:android=
"
http://schemas.android.com/apk/res/android"
android:layout_width=
"
match_parent"
android:layout_height=
"
match_parent"
>
<
Button
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:text=
"
Button"
android:id=
"
@
+
id/button2"
/>
<
/LinearLayout>
修改默认Activity为UploadActivity,运行程序成功。
httpclient简单实现
这里我们要将httpmime-4.5.2.jar包导入工程, 修改UploadThread.java为
package com.davebobo.http_01;
import android.os.Environment;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by DaveBobo on 2016/10/26.
*/
public class UploadThread extends Thread{private String fileName;
private String url;
publicUploadThread(String url,String fileName){
this.url =
url;
this.fileName =
fileName;
}private void httpUpload(){
//上传表单分割线的描述符
String boundary =
"
---------------------------7e01ee305f069a"
;
//Content-Type
String reqCon =
"
-----------------------------7e01ee305f069a"
;
//请求正文比Content-Type多两个-
String prefix =
"
--"
;
String end=
"
\\r\\n"
;
try {
URL httpUrl =
new URL(url);
HttpURLConnection conn =
(HttpURLConnection) httpUrl.openConnection();
conn.setRequestMethod("
POST"
);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("
Content-Type"
,
"
multipart/form-data;
boundary=
"
+
boundary);
DataOutputStream out =
new DataOutputStream(conn.getOutputStream());
out.writeBytes(prefix+
boundary+
end);
out.writeBytes("
Content-Disposition: form-data;
"
+
"
name=
\\"
file\\"
;
filename=
\\"
"
+
"
head.jpg"
+
"
\\"
"
+
end);
//实体数据
out.writeBytes(end);
FileInputStream fileInputStream =
new FileInputStream(new File(fileName));
byte[] b =
new byte[1024*4];
int len;
while ((len=
fileInputStream.read(b))!=
-1){
out.write(b,0, len);
}
out.writeBytes(end);
out.writeBytes(prefix +
boundary +
prefix +
end);
out.flush();
BufferedReader reader =
new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuffer sb =
new StringBuffer();
String str;
while ((str=
reader.readLine())!=
null){
sb.append(str);
System.out.println("
respose:"
+
sb.toString());
if (out!=
null){
out.close();
}
if (reader!=
null){
reader.close();
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}private void uploadHttpClient(){HttpClient client =
new DefaultHttpClient();
HttpPost post =
new HttpPost(url);
MultipartEntity muti =
new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
File parent =
Environment.getExternalStorageDirectory();
File fileAbs =
new File(parent,"
head.jpg"
);
FileBody fileBody =
new FileBody(fileAbs);
muti.addPart("
file"
, fileBody);
post.setEntity(muti);
try {
HttpResponse response =
client.execute(post);
if (response.getStatusLine().getStatusCode() =
=
HttpStatus.SC_OK){
System.out.println(EntityUtils.toString(response.getEntity()));
}
} catch (IOException e) {
e.printStackTrace();
}
}
@
Override
public void run() {
uploadHttpClient();
}
}
在这里有一点小插曲, 我使用的httpClient版本为httpcomponents-client-4.5.2, Android Studio提示错误:
10-27 10:33:06.980 24750-24826/com.davebobo.http_01 E/AndroidRuntime:
FATAL EXCEPTION: Thread-249
Process: com.davebobo.http_01, PID: 24750
java.lang.NoSuchFieldError: No static field INSTANCE of type Lorg/apache/http/message/BasicHeaderValueFormatter;
in class Lorg/apache/http/message
/BasicHeaderValueFormatter;
or its superclasses (declaration of '
org.apache.http.message.BasicHeaderValueFormatter'
解决方式: 下载使用 httpclient-4.3.1即可。
替换为httpclient-4.3.1后测试运行成功。
【Android实战之旅 006】Android中的HTTP通信 配套的资源下载
推荐阅读
- Android studio 第三次作业
- Android之ViewPager 第二课
- Android开发之神奇的Fading Edge,让你的View更有层次感!
- 学习笔记Android中Service通信
- A缓冲法详细指南(图解)
- 算法设计(如何解决布尔矩阵问题(?))
- 算法设计(如何解决布尔数组难题())
- C++标准模板库(STL)介绍和指南
- JavaScript按位运算符用法指南