package com.test.multithread;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import android.util.Log;
public class DownloadTask {
private String mFileDir = null;
//private String mCharSet = null; // 编码格式
private String mFileName = null; // 将要下载的文件的名称
private URL mURL = null;
private int threadNumber = 5;
private double contentLengthPerThread = 0.0;
private ChildThread[] childThreads = new ChildThread[threadNumber];
private boolean mStatusError = false;
private int mSleepSecondes = 0;
private String LOGTAG = "download";
/**
* 第一步是用来设置断点续传时候的一些信息的,第二步就是主要的分多线程来下载了,最后是数据的合并。
*
* @param urlString
* 将要下载的页面的url
* @param charset
* 将要下载的页面的编码方式
*/
public void download(String urlString, String charset) {
//mCharSet = charset;// 编码格式
long contentLength = 0;// 文件总大小
CountDownLatch latch = new CountDownLatch(threadNumber);
long[] startPosition = new long[threadNumber];
long endPosition = 0;
try {
// 从url中获得下载的文件格式与名字
mFileName = urlString.substring(urlString.lastIndexOf("/") + 1);
mFileDir = "/sdcard/";
mURL = new URL(urlString);
URLConnection con = mURL.openConnection();
//setHeader(con);
// 得到content的长度
contentLength = con.getContentLength();
// 把context分为threadNumber段的话,每段的长度。
contentLengthPerThread = contentLength / threadNumber;
// 第一步,分析已下载的临时文件,设置断点,如果是新的下载任务,则建立目标文件。在第4点中说明。
startPosition = setThreadBreakpoint(mFileDir, mFileName,
contentLength, startPosition);
// 第二步,分多个线程下载文件
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < threadNumber; i++) {
// 创建子线程来负责下载数据,每段数据的起始位置为(contentLengthPerThread * i + 已下载长度)
//startPosition[i] += contentLengthPerThread * i;//错误,要去掉+号或者*号
startPosition[i] += contentLengthPerThread * i;
// 设置子线程的终止位置,非最后一个线程即为(contentLengthPerThread * (i + 1) - 1)
// 最后一个线程的终止位置即为下载内容的长度
if (i == threadNumber - 1) {
endPosition = contentLength;
} else {
endPosition = (long) contentLengthPerThread * (i + 1) - 1;
}
// 开启子线程,并执行。
ChildThread thread = new ChildThread(this, latch, i,
startPosition[i], endPosition);
childThreads[i] = thread;
exec.execute(thread);
}
// 等待CountdownLatch信号为0,表示所有子线程都结束。
latch.await();
exec.shutdown();
// 第三步,把分段下载下来的临时文件中的内容写入目标文件中。在第3点中说明。
tempFileToTargetFile(childThreads);
} catch (Exception e) {
e.printStackTrace();
}
}
public class ChildThread extends Thread {
private static final int RECONNECT_MAX = 10;
private static final int STATUS_HTTPSTATUS_ERROR = 0;
private static final int STATUS_HAS_FINISHED = 1;
private DownloadTask task;
private int threadId;
private long startPosition;
private long endPosition;
private final CountDownLatch latch;
private File tempFile = null;
private boolean hasFinished = false;
private int status = STATUS_HAS_FINISHED;
public ChildThread(DownloadTask task, CountDownLatch latch,
int threadId, long startPosition, long endPosition) {
super();
this.task = task;
this.threadId = threadId;
this.startPosition = startPosition;
this.endPosition = endPosition;
this.latch = latch;
try {
tempFile = new File(this.task.mFileDir + this.task.mFileName
+ "_" + threadId);
if (!tempFile.exists()) {
tempFile.createNewFile();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
Log.d(LOGTAG,"Thread " + threadId + " run ...");
HttpURLConnection con = null;
InputStream inputStream = null;
BufferedOutputStream outputStream = null;
long count = 0;
long threadDownloadLength = endPosition - startPosition;
try {
outputStream = new BufferedOutputStream(new FileOutputStream(tempFile.getPath(), true));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
for(int k = 0; k < RECONNECT_MAX; k++){
if(k > 0)
Log.d("download","Now thread " + threadId + "is reconnect, start position is " + startPosition);
try {
//打开URLConnection
con = (HttpURLConnection) task.mURL.openConnection();
// setHeader(con);
con.setAllowUserInteraction(true);
//设置连接超时时间为10000ms
con.setConnectTimeout(10000);
//设置读取数据超时时间为10000ms
con.setReadTimeout(10000);
if(startPosition < endPosition){
//设置下载数据的起止区间
con.setRequestProperty("Range", "bytes=" + startPosition + "-"
+ endPosition);
Log.d(LOGTAG, "Thread " + threadId + " startPosition is " + startPosition);
Log.d(LOGTAG, "Thread " + threadId + " endPosition is " + endPosition);
// 判断http status是否为HTTP/1.1 206 Partial Content或者200 OK
// 如果不是以上两种状态,把status改为STATUS_HTTPSTATUS_ERROR
if (con.getResponseCode() != HttpURLConnection.HTTP_OK
&& con.getResponseCode() != HttpURLConnection.HTTP_PARTIAL) {
Log.d(LOGTAG, "Thread " + threadId + ": code = "
+ con.getResponseCode() + ", status = "
+ con.getResponseMessage());
status = ChildThread.STATUS_HTTPSTATUS_ERROR;
this.task.mStatusError = true;
outputStream.close();
con.disconnect();
Log.d(LOGTAG, "Thread " + threadId + " finished.");
latch.countDown();
break;
}
inputStream = con.getInputStream();
int len = 0;
byte[] b = new byte[1024];
while ((len = inputStream.read(b)) != -1) {
outputStream.write(b, 0, len);
count += len;
startPosition += count;
//每读满4096个byte(一个内存页),往磁盘上flush一下
if(count % 4096 == 0){
outputStream.flush();
}
}
Log.d(LOGTAG, "count is " + count);
if(count == threadDownloadLength){
hasFinished = true;
}
outputStream.flush();
outputStream.c
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
本资源也可从人民邮电出版社网站下载。但由于源代码资源CSDN尚未有朋友提供,在此也补充一下。 本书共分25章,对Android系统的各个层面进行了详细讲解,旨在让读者在尽量短的时间内对Andriod系统的各个方面有一个全面的了解,为进一步学习开发和研究Android操作系统源程序打下坚实的基础。首先,在Android应用程序层面,详细讲解了应用程序开发的各项技术,着重讲解了应用程序的开发基础、应用程序的结构、4大组件工作原理与功能,以及它们之间通信的基础Intent类。此外,给出了一些实例让读者能够更深刻地理解这些知识并加以应用。然后,讲解了AndroidNDK开发的方方面面,为了更好地开发出高质量的应用程序,详细讲解了Android调试技术,包括普通Android应用程序和NDK应用程序调试。 当然,为满足一些有着丰富应用程序开发经验的读者和对Android系统底层有很大兴趣的读者的学习需求,本书还详细讲解了如何编译Android源程序工程,并对Android编译系统进行了深入剖析,让读者对Android工程的高效组织和自动编译有更深刻的理解。此外,本书还结合着源程序深入讲解了Android系统中的某些子系统,包括子系统的功能、结构和工作原理。 本书还着重讲解了Android系统改造的思路,详细讲解了一些改造Android系统的实例,如状态栏定制、开机动画、系统服务、系统应用改造,使读者通过动手实践来真正将所学知识融会贯通。 本书适合作为Android应用程序开发者的实践教材,也适合对Android系统原理有极大兴趣的爱好者阅读,还可供Android系统改造人员作为参考书使用。
资源推荐
资源详情
资源评论
收起资源包目录
Android应用开发与系统改造实战.王保卫等.源代码 (932个子文件)
IHelloWorldAidlService.aidl 124B
IHelloWorldAidlService.aidl 124B
resources.ap_ 75KB
resources.ap_ 30KB
resources.ap_ 28KB
resources.ap_ 28KB
resources.ap_ 22KB
resources.ap_ 12KB
resources.ap_ 12KB
resources.ap_ 12KB
resources.ap_ 11KB
resources.ap_ 11KB
resources.ap_ 11KB
resources.ap_ 11KB
resources.ap_ 11KB
resources.ap_ 11KB
resources.ap_ 11KB
resources.ap_ 11KB
resources.ap_ 11KB
resources.ap_ 11KB
resources.ap_ 10KB
resources.ap_ 6KB
resources.ap_ 6KB
resources.ap_ 6KB
resources.ap_ 6KB
resources.ap_ 6KB
HelloWorld.apk 79KB
HelloAndroid.apk 32KB
HelloAndroid.apk 31KB
HelloAndroid.apk 31KB
HelloWorld.apk 25KB
androidMultiDownloadTest.apk 18KB
SqlLite.apk 17KB
HelloWorld.apk 17KB
HelloWorld.apk 16KB
Test.apk 16KB
startService.apk 15KB
HelloWorld.apk 15KB
HelloWorld.apk 15KB
HelloWorld.apk 15KB
Location.apk 15KB
HelloWorld.apk 15KB
HelloWorld.apk 14KB
SharedPreferencesActivity.apk 14KB
HelloWorld.apk 13KB
HelloAndroid.apk 9KB
HelloAndroid.apk 9KB
HelloAndroid.apk 8KB
HelloAndroid.apk 8KB
HelloAndroid.apk 8KB
hello-jni.c 2KB
hello-jni.c 2KB
hello-jni.c 2KB
hello-jni.c 2KB
hello-jni.c 1KB
proguard.cfg 1KB
proguard.cfg 1KB
proguard.cfg 1KB
DownloadTask.class 6KB
DownloadTask.class 6KB
DownloadTask$ChildThread.class 5KB
DownloadTask$ChildThread.class 5KB
TestDbActivity.class 4KB
LocationActivity.class 3KB
DbHelper.class 3KB
ServiceDemo.class 3KB
ImageAdapter.class 2KB
ImageAdapter.class 2KB
TestSharedPreferencesActivityActivity.class 2KB
TestDbActivity$2.class 2KB
MyList.class 2KB
StartService.class 2KB
ServiceDemo$1.class 2KB
TestDbActivity$1.class 2KB
MyGrid.class 2KB
MyActivity$1.class 2KB
MyActivity$1.class 2KB
MyActivity$1.class 2KB
MyActivity$1.class 2KB
MyActivity$1.class 2KB
MyActivity$1.class 2KB
HelloWorld$1.class 1KB
HelloWorld$1.class 1KB
ResultActivity.class 1KB
ResultActivity.class 1KB
LocationActivity$1.class 1KB
HelloWorld.class 1KB
HelloWorld.class 1KB
R.class 1KB
R.class 1KB
R.class 1KB
HelloWorld$1.class 1KB
HelloWorld$1.class 1KB
R$drawable.class 1KB
HelloWorld$1.class 1KB
HelloWorld$1.class 1KB
R$id.class 1KB
ResultActivity.class 1KB
R$id.class 1KB
R$id.class 1KB
共 932 条
- 1
- 2
- 3
- 4
- 5
- 6
- 10
资源评论
- qinhai012014-12-21下载了配套的这本书,结合代码看不错!
lelehehe2008
- 粉丝: 1
- 资源: 12
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 各种排序算法java实现的源代码.zip
- 金山PDF教育版编辑器
- 基于springboot+element的校园服务平台源代码项目包含全套技术资料.zip
- 自动化应用驱动的容器弹性管理平台解决方案
- 各种排序算法 Python 实现的源代码
- BlurAdmin 是一款使用 AngularJs + Bootstrap实现的单页管理端模版,视觉冲击极强的管理后台,各种动画效果
- 基于JSP+Servlet的网上书店系统源代码项目包含全套技术资料.zip
- GGJGJGJGGDGGDGG
- 基于SpringBoot的毕业设计选题系统源代码项目包含全套技术资料.zip
- Springboot + mybatis-plus + layui 实现的博客系统源代码全套技术资料.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功