day05
1使用httpurlconnection方式把数据提交到服务器
基于什么协议?http
get方式:组拼URL地址把数据拼到url上 有大小限制 1kb 4kb
post方式: post方式提交安全 没有大小限制
post方式和get方式区别:
[1]路径不同
[2]请求方式不同
[3]post方式要自己组拼请求体的内容
post方式比get方式多了2个头(content-length和content-type)
get方式提交数据代码如下
new Thread(){public void run() {
try{
//[2]获取用户名和密码
String name = et_username.getText().toString().trim();
String pwd = et_password.getText().toString().trim();
//[2.1]定义get方式要提交的路径
String path = "http://192.168.11.73:8000/login/loginServlet?username=" + name + "&password=" + pwd;
//[2]
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
int code = conn.getResponseCode();
if(code == 200){
InputStream inputStream = conn.getInputStream();
String content = StreamTools.readStream(inputStream);
//把服务器的数据展示到Toast上
showToast(content);
}
}
catch(Exception e)
{
e.printStackTrace();
}
};}.start();
post方式提交数据代码如下(主要☆☆☆☆☆处)
new Thread(){public void run() {
try{
//[2]获取用户名和密码
String name = et_username.getText().toString().trim();
String pwd = et_password.getText().toString().trim();
//☆☆☆☆☆和get方式提交数据区别四:设置请求体
//String data = "username=" + name + "&password=" + pwd;
//[2.1]定义get方式要提交的路径
//☆☆☆☆☆和get方式提交数据区别一:路径不同
//String path = "http://192.168.11.73:8000/login/loginServlet";
String path = "http://192.168.11.73:8000/login/loginServlet?username=" + name + "&password=" + pwd;
//[2]
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//☆☆☆☆☆和get方式提交数据区别二:设置请求方式是post
//conn.setRequestMethod("POST");
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
//☆☆☆☆☆和get方式提交数据区别三:多设置两个请求头信息
//conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
//conn.setRequestProperty("Content-Length", data.length() + "");
//☆☆☆☆☆和get方式提交数据区别五:向服务器提交数据
//设置一个标记 允许输出
//conn.setDoOutput(true);
//conn.getOutputStream().write(data.getBytes());
int code = conn.getResponseCode();
if(code == 200){
InputStream inputStream = conn.getInputStream();
String content = StreamTools.readStream(inputStream);
//把服务器的数据展示到Toast上
showToast(content);
}
}
catch(Exception e)
{
e.printStackTrace();
}
};}.start();
2乱码问题解决
3以httpclient方式把数据提交到服务器
[1]开源项目
[2]谷歌一般以 base default simple 进行命名
[3]对http请求的封装
get方式提交数据代码如下
new Thread() {
public void run() {
try {
// [2]获取用户名和密码
String name = et_username.getText().toString().trim();
String pwd = et_password.getText().toString().trim();
name = URLEncoder.encode(name, "utf-8");
pwd = URLEncoder.encode(pwd, "utf-8");
String path = "http://192.168.11.73:8000/login/loginServlet?username="
+ name + "&password=" + pwd;
// 获取httpclient实例
DefaultHttpClient client = new DefaultHttpClient();
// 准备get请求 定义一个httpget实现
HttpGet get = new HttpGet(path);
// 执行一个get请求
HttpResponse response = client.execute(get);
// 获取服务器返回的状态码
int code = response.getStatusLine().getStatusCode();
if (code == 200) {
InputStream inputStream = response.getEntity()
.getContent();
String content = StreamTools.readStream(inputStream);
showToast(content + "");
}
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
post方式提交数据代码如下
new Thread() {
public void run() {
try {
// [2]获取用户名和密码
String name = et_username.getText().toString().trim();
String pwd = et_password.getText().toString().trim();
// [3]以httpclient方式进行提交
DefaultHttpClient client = new DefaultHttpClient();
// [3.1]准备post请求
String Path = "http://192.168.11.73:8080/login/LoginServlet";
HttpPost post = new HttpPost(Path);
//[3.1.0]准备parameters
List<NameValuePair> lists = new ArrayList<NameValuePair>();
//[3.1.1]准备NameValuePair 实际上就是我们要提交的用户名和密码
BasicNameValuePair nameValuePair = new BasicNameValuePair("username", name);
BasicNameValuePair pwdValuePair = new BasicNameValuePair("password", pwd);
lists.add(nameValuePair);
lists.add(pwdValuePair);
//[3.1.2]准备entity
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(lists);
post.setEntity(entity);
HttpResponse response = client.execute(post);
int code = response.getStatusLine().getStatusCode();
if (code == 200) {
InputStream inputStream = response.getEntity()
.getContent();
String content = StreamTools.readStream(inputStream);
showToast(content + "");
}
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
4开源项目方式把数据提交到服务器
asynchttpclient
get方式提交数据代码如下
String name = et_username.getText().toString().trim();
String pwd = et_password.getText().toString().trim();
name = URLEncoder.encode(name, "utf-8");
pwd = URLEncoder.encode(pwd, "utf-8");
path = "http://192.168.11.73:8000/login/loginServlet?username=" + name
+ "&password=" + pwd;
// [3]使用开源项目进行get请求
// [3.1]创建asynchttpclient
AsyncHttpClient client = new AsyncHttpClient();
// [3.2]进行get请求
client.get(path, new AsyncHttpResponseHandler() {
//请求成功
public void onSuccess(int statusCode, Header[] headers,
byte[] responseBody) {
Toast.makeText(getApplicationContext(), new String(responseBody,"gbk"), 1).show();
}
//请求失败
public void onSuccess(int statusCode, Header[] headers,
byte[] responseBody, Throwable error) {
//Toast.makeText(getApplicationContext(), new String(responseBody,"gbk"), 1).show();
}
});
post方式提交数据代码如下
String name = et_username.getText().toString().trim();
String pwd = et_password.getText().toString().trim();
String Path = "http://192.168.11.73:8080/login/LoginServlet";
//[3.1]创建asyncHttpClient
AsyncHttpClient client = new AsyncHttpClient();
//[3.1.0]准备请求体的内容
RequestParams params = new RequestParams();
params.put("username", name);
params.put("password", pwd);
//[3.2]进行post请求
client.post(Path, params, new AsyncHttpResponseHandler() {
//请求成功
public void onSuccess(int statusCode, Header[] headers,
byte[] responseBody) {
Toast.makeText(getApplicationContext(), new String(responseBody,"gbk"), 1).show();
}
//请求失败
public void onSuccess(int statusCode, Header[] headers,
byte[] responseBody, Throwable error) {
//Toast.makeText(getApplicationContext(), new String(responseBody,"gbk"), 1).show();
}
});
总结:
[1] httpurlconnection
[2] httpclient (了解 没人用)
[3] 开源项目(asynchttpclient)
5javase多线程下载
设置请求服务器文件的位置
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
为什么多线程能加速下载?
[1]不是说线程开的越多下载越快
[2]还受服务器带宽的影响
[3]获得更多的cup资源
每个线程下载的计算公式
package com.phone.download;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class MutiDownLoad {
// 定义下载路径
static String path = "http://192.168.11.73:8080/feiq.exe";
private static final int threadCount = 3;//线程数
public static void main(String[] args){
//[2]获取服务器文件的大小
try
{
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
int code = conn.getResponseCode();
if(code == 200)
{
//[☆☆☆☆]一、获取服务器文件的大小 要计算每个线程下载的开始位置和结束位置
int length = conn.getContentLength();
//[☆☆☆☆]二、创建一个大小和服务器一模一样的文件 目的是提前把空间申请出来
RandomAccessFile rafAccessFile = new RandomAccessFile("temp.exe", "rw");
rafAccessFile.setLength(length);
//算出每个线程下载的大小
int blocksize = length / threadCount;
//[☆☆☆☆]三、计算每个线程下载的开始位置和结束位置
for(int i=0; i<threadCount; i++)
{
//每个线程下载的开始位置
int startIndex = i*blocksize;
//每个线程下载的结束位置
int endIndex = (i+1)*blocksize - 1;
if(i == threadCount - 1)
{
//说明是最后一个线程
endIndex = length-1;
}
//[☆☆☆☆]四、开启线程去服务器下载文件
DownLoadThread downLoadThread = new DownLoadThread(startIndex, endIndex, i);
downLoadThread.start();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
//定义线程去服务器下载文件
private static class DownLoadThread extends Thread
{
//通过构造方法把每个线程下载的开始位置和结束位置传递过来
private int startIndex;
private int endIndex;
private int threadId;
public DownLoadThread(int startIndex,int endIndex,int threadId){
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
}
public void run() {
//四、开启线程去服务器下载文件
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
//设置一个请求头Range(作用告诉服务器每个线程下载的开始位置和结束位置)
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
int code = conn.getResponseCode();
//200代表获取服务器资源全部成功
//206请求部分资源成功
//if(code == 200)
if(code == 206)
{
//[6]创建随机读写文件对象
RandomAccessFile rafAccessFile = new RandomAccessFile("temp.exe", "rw");
//[6]每个线程要从自己的位置开始写
rafAccessFile.seek(startIndex);
InputStream inputStream = conn.getInputStream();
//[7]把数据写到文件中
int len = -1;
byte[] Buffer = new byte[1024];
while((len = inputStream.read(Buffer))!=-1)
{
rafAccessFile.write(Buffer,0,len);
}
rafAccessFile.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
6断点续传实现
package com.phone.download;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class MutiDownLoad {
// 定义下载路径
static String path = "http://192.168.11.73:8080/feiq.exe";
private static final int threadCount = 3;//线程数
//代表当前正在运行的线程
private static int runningThread;
public static void main(String[] args){
//[2]获取服务器文件的大小
try
{
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
int code = conn.getResponseCode();
if(code == 200)
{
//[☆☆☆☆]一、获取服务器文件的大小 要计算每个线程下载的开始位置和结束位置
int length = conn.getContentLength();
//把线程的数量赋值给正在运行的线程
runningThread = threadCount;
//[☆☆☆☆]二、创建一个大小和服务器一模一样的文件 目的是提前把空间申请出来
RandomAccessFile rafAccessFile = new RandomAccessFile("temp.exe", "rw");
rafAccessFile.setLength(length);
//算出每个线程下载的大小
int blocksize = length / threadCount;
//[☆☆☆☆]三、计算每个线程下载的开始位置和结束位置
for(int i=0; i<threadCount; i++)
{
//每个线程下载的开始位置
int startIndex = i*blocksize;
//每个线程下载的结束位置
int endIndex = (i+1)*blocksize - 1;
if(i == threadCount - 1)
{
//说明是最后一个线程
endIndex = length-1;
}
//[☆☆☆☆]四、开启线程去服务器下载文件
DownLoadThread downLoadThread = new DownLoadThread(startIndex, endIndex, i);
downLoadThread.start();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
//定义线程去服务器下载文件
private static class DownLoadThread extends Thread
{
//通过构造方法把每个线程下载的开始位置和结束位置传递过来
private int startIndex;
private int endIndex;
private int threadId;
public DownLoadThread(int startIndex,int endIndex,int threadId){
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
}
public void run() {
//四、开启线程去服务器下载文件
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
//如果中间断过 继续上次的位置继续下载 从文件中读取上次下载的位置
File file = new File(getFilename(path) + threadId + ".txt");
if(file.exists() && file.length()>0)
{
FileInputStream fis = new FileInputStream(file);
BufferedReader bufr = new BufferedReader(new InputStreamReader(fis));
//读取出的内容就是上一次下载的位置
String lastPositionn = bufr.readLine();
int lastPosition = Integer.parseInt(lastPositionn);
//改变startIndex位置
startIndex = lastPosition;
fis.close();
}
//设置一个请求头Range(作用告诉服务器每个线程下载的开始位置和结束位置)
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
int code = conn.getResponseCode();
//200代表获取服务器资源全部成功
//206请求部分资源成功
//if(code == 200)
if(code == 206)
{
//[6]创建随机读写文件对象
RandomAccessFile rafAccessFile = new RandomAccessFile(getFilename(path), "rw");
//[6]每个线程要从自己的位置开始写
rafAccessFile.seek(startIndex);
InputStream inputStream = conn.getInputStream();
//[7]把数据写到文件中
int len = -1;
byte[] Buffer = new byte[1024*1024];
//代表当前线程下载的大小
int total = 0;
while((len = inputStream.read(Buffer))!=-1)
{
rafAccessFile.write(Buffer,0,len);
total += len;
//[8]实现断点续传 就是把当前线程下载的位置给存起来 下次再下载的时候按照上次下载的位置继续下载就可以了
//存到一个普通的.txt文本中
int currentThreadPosition = startIndex + total;
//[9]用来存当前线程下载的位置
RandomAccessFile raff = new RandomAccessFile(getFilename(path) + threadId + ".txt", "rwd");
raff.write(String.valueOf(currentThreadPosition).getBytes());
raff.close();
/*
* 用这种方法有时候可能存不成功,因为硬盘有个缓存区
File file = new File(threadId + ".txt");
FileOutputStream fos = new FileOutputStream(file);
fos.write(String.valueOf(currentThreadPosition).getBytes());
fos.close();
*/
}
rafAccessFile.close();
synchronized(DownLoadThread.class){
runningThread--;
if(runningThread == 0)
{
//说明所有的线程都执行完毕了 就把.txt文件删除
for(int i = 0; i < threadCount; i++)
{
File delFile = new File(getFilename(path) + i + ".txt");
delFile.delete();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*
* 获取文件的名字
*/
public static String getFilename(String path){
int start = path.lastIndexOf("/");
return path.substring(start);
}
}
7断点续传逻辑移植到Android上
MainActivity.java
package com.phone.download;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
public class MainActivity extends ActionBarActivity {
private EditText et_path;
private String path;
private EditText et_threadCount;
private LinearLayout ll_pb_layout;
// 代表当前正在运行的线程
private static int runningThread;
//用来存进度条的引用
private List<ProgressBar> pbLists;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// [1]获取控件
et_path = (EditText) findViewById(R.id.et_path);
et_threadCount = (EditText) findViewById(R.id.et_threadCount);
ll_pb_layout = (LinearLayout) findViewById(R.id.ll_pb);
pbLists = new ArrayList<ProgressBar>();
}
// 点击按钮实现下载的逻辑
public void click(View v) {
// 获取下载的路径
path = et_path.getText().toString().trim();
// [3]获取线程的数量
String threadCountt = et_threadCount.getText().toString().trim();
// [3.0]先移除进度条再添加
ll_pb_layout.removeAllViews();
final int threadCount = Integer.parseInt(threadCountt);
pbLists.clear();
for (int i = 0; i < threadCount; i++) {
// [3.1]把我定义的item布局转换成一个View对象
ProgressBar child = (ProgressBar) View.inflate(getApplicationContext(), R.layout.item,
null);
//把child添加到集合中
pbLists.add(child);
// [4]动态的添加进度条
ll_pb_layout.addView(child);
}
// [5]开始移植
new Thread() {
public void run() {
// [2]获取服务器文件的大小
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
int code = conn.getResponseCode();
if (code == 200) {
// [☆☆☆☆]一、获取服务器文件的大小 要计算每个线程下载的开始位置和结束位置
int length = conn.getContentLength();
// 把线程的数量赋值给正在运行的线程
runningThread = threadCount;
// [☆☆☆☆]二、创建一个大小和服务器一模一样的文件 目的是提前把空间申请出来
RandomAccessFile rafAccessFile = new RandomAccessFile(
"temp.exe", "rw");
rafAccessFile.setLength(length);
// 算出每个线程下载的大小
int blocksize = length / threadCount;
// [☆☆☆☆]三、计算每个线程下载的开始位置和结束位置
for (int i = 0; i < threadCount; i++) {
// 每个线程下载的开始位置
int startIndex = i * blocksize;
// 每个线程下载的结束位置
int endIndex = (i + 1) * blocksize - 1;
if (i == threadCount - 1) {
// 说明是最后一个线程
endIndex = length - 1;
}
// [☆☆☆☆]四、开启线程去服务器下载文件
DownLoadThread downLoadThread = new DownLoadThread(
startIndex, endIndex, i);
downLoadThread.start();
}
}
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
// 定义线程去服务器下载文件
private class DownLoadThread extends Thread {
// 通过构造方法把每个线程下载的开始位置和结束位置传递过来
private int startIndex;
private int endIndex;
private int threadId;
//代表当前线程下载的最大值
private int PbMaxSize;
//如果中断过 获取上次下载的位置
private int PbLastPosition;
public DownLoadThread(int startIndex, int endIndex, int threadId) {
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
}
public void run() {
// 四、开启线程去服务器下载文件
try {
//计算当前进度条的最大值
PbMaxSize = endIndex - startIndex;
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
// 如果中间断过 继续上次的位置继续下载 从文件中读取上次下载的位置
File file = new File(getFilename(path) + threadId + ".txt");
if (file.exists() && file.length() > 0) {
FileInputStream fis = new FileInputStream(file);
BufferedReader bufr = new BufferedReader(
new InputStreamReader(fis));
// 读取出的内容就是上一次下载的位置
String lastPositionn = bufr.readLine();
int lastPosition = Integer.parseInt(lastPositionn);
//赋值给我们定义的进度条进度位置
PbLastPosition = lastPosition - startIndex;
// 改变startIndex位置
startIndex = lastPosition;
fis.close();
}
// 设置一个请求头Range(作用告诉服务器每个线程下载的开始位置和结束位置)
conn.setRequestProperty("Range", "bytes=" + startIndex + "-"
+ endIndex);
int code = conn.getResponseCode();
// 200代表获取服务器资源全部成功
// 206请求部分资源成功
// if(code == 200)
if (code == 206) {
// [6]创建随机读写文件对象
RandomAccessFile rafAccessFile = new RandomAccessFile(
getFilename(path), "rw");
// [6]每个线程要从自己的位置开始写
rafAccessFile.seek(startIndex);
InputStream inputStream = conn.getInputStream();
// [7]把数据写到文件中
int len = -1;
byte[] Buffer = new byte[1024 * 1024];
// 代表当前线程下载的大小
int total = 0;
while ((len = inputStream.read(Buffer)) != -1) {
rafAccessFile.write(Buffer, 0, len);
total += len;
// [8]实现断点续传 就是把当前线程下载的位置给存起来 下次再下载的时候按照上次下载的位置继续下载就可以了
// 存到一个普通的.txt文本中
int currentThreadPosition = startIndex + total;
// [9]用来存当前线程下载的位置
RandomAccessFile raff = new RandomAccessFile(
getFilename(path) + threadId + ".txt", "rwd");
raff.write(String.valueOf(currentThreadPosition)
.getBytes());
raff.close();
/*
* 用这种方法有时候可能存不成功,因为硬盘有个缓存区 File file = new
* File(threadId + ".txt"); FileOutputStream fos = new
* FileOutputStream(file);
* fos.write(String.valueOf(currentThreadPosition
* ).getBytes()); fos.close();
*/
//设置当前进度条的最大值和当前进度
pbLists.get(threadId).setMax(PbMaxSize);
pbLists.get(threadId).setProgress(PbLastPosition+total);
}
rafAccessFile.close();
// 获取线程的数量
String threadCountt = et_threadCount.getText().toString().trim();
final int threadCount = Integer.parseInt(threadCountt);
synchronized (DownLoadThread.class) {
runningThread--;
if (runningThread == 0) {
// 说明所有的线程都执行完毕了 就把.txt文件删除
for (int i = 0; i < threadCount; i++) {
File delFile = new File(getFilename(path) + i
+ ".txt");
delFile.delete();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*
* 获取文件的名字
*/
public static String getFilename(String path){
int start = path.lastIndexOf("/");
String substring = path.substring(start);
String fileName = Environment.getExternalStorageDirectory().getPath() + "/" + substring;
return fileName;
}
}
activity_main.xml
<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:orientation="vertical"
tools:context="com.phone.download.MainActivity" >
<EditText
android:id="@+id/et_path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入下载路径"/>
<EditText
android:id="@+id/et_threadCount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入线程的数量"/>
<Button
android:onClick="click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="下载"/>
<LinearLayout
android:id="@+id/ll_pb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
8开源项目实现多线程下载(xutils)
package com.phone.opensourcedownload;
import java.io.File;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
public class MainActivity extends Activity {
private EditText et_path;
private ProgressBar pb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[0]获取控件
et_path = (EditText) findViewById(R.id.et_path);
pb = (ProgressBar) findViewById(R.id.progressBar1);
}
//点击按钮实现断点续传下载逻辑
public void click(View v){
//[1]获取下载路径
String path = et_path.getText().toString().trim();
//[2]创建httputils对象HttpUtils http = new HttpUtils();
HttpUtils http = new HttpUtils();
//[3]实现断点下载
/**
* path:路径
* target:下载文件的路径,即下载到哪
* autoResume:是否支持断点续传的逻辑
*
*/
http.download(path, "/mnt/sdcard/haha.exe", true, new RequestCallBack<File>() {
//下载成功
@Override
public void onSuccess(ResponseInfo<File> responseInfo) {
Toast.makeText(getApplicationContext(), "下载成功", 1);
}
@Override
/**
* total:代表总进度
* current:代表当前进度
*/
public void onLoading(long total, long current, boolean isUploading) {
pb.setMax((int)total);
pb.setProgress((int)current);
}
//下载失败的回调函数
@Override
public void onFailure(HttpException error, String msg) {
}
});
}
}
<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:orientation="vertical"
tools:context="com.phone.download.MainActivity" >
<EditText
android:id="@+id/et_path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入下载路径" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="下载"
android:onClick="click" />
<ProgressBar
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
9今日总结
[1]httpurlConnection 用于发送或者接收数据(掌握)
get 组拼url地址
post 要自己组拼请求正文 请求头信息
[2]httpClient(了解)
[3]asyncHttpClient(掌握)
[4]多线程下载
1.获取文件大小
2.在客户端创建一个大小和服务器一模一样的文件(为了提前申请控件)
3.算出每个线程下载的开始位置和结束位置
需要考虑 最后一个线程 文件长度-1
4.开启一个线程去实现下载逻辑 httpurlConnection
设置Range 还要注意服务器返回的状态码不是200而是206
5.断点的逻辑 就是把当前线程下载的位置给保存起来 RandomAccessFile 直接同步到底层设备
6.移植到Android 算出进度条的进度 集合存进度条的引用
7.与进度有关的都可以在子线程直接更新UI
只言片语任我说,提笔句句无需忖。落笔不知寄何人,唯有邀友共斟酌。