`
qinya06
  • 浏览: 598865 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

android多线程下载详解

 
阅读更多
一个线程类,来完成对指定区域的数据进行下载

package com.ideasandroid.demo;
 
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;
 
import android.util.Log;
/**
*  Copyright (C) 2010 ideasandroid
*  演示android多线程下载
*  欢迎访问http://www.ideasandroid.com
*  让程序开发不再那么神秘
*
*  单个下载线程
*/
public class FileDownloadThread extends Thread{
private static final int BUFFER_SIZE=1024;
private URL url;
private File file;
private int startPosition;
private int endPosition;
private int curPosition;
//用于标识当前线程是否下载完成
private boolean finished=false;
private int downloadSize=0;
public FileDownloadThread(URL url,File file,int startPosition,int endPosition){
this.url=url;
this.file=file;
this.startPosition=startPosition;
this.curPosition=startPosition;
this.endPosition=endPosition;
}
@Override
public void run() {
BufferedInputStream bis = null;
RandomAccessFile fos = null;
byte[] buf = new byte[BUFFER_SIZE];
URLConnection con = null;
try {
con = url.openConnection();
con.setAllowUserInteraction(true);
//设置当前线程下载的起点,终点
con.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition);
//使用java中的RandomAccessFile 对文件进行随机读写操作
fos = new RandomAccessFile(file, "rw");
//设置开始写文件的位置
fos.seek(startPosition);
bis = new BufferedInputStream(con.getInputStream());
//开始循环以流的形式读写文件
while (curPosition < endPosition) {
int len = bis.read(buf, 0, BUFFER_SIZE);
if (len == -1) {
break;
}
fos.write(buf, 0, len);
curPosition = curPosition + len;
if (curPosition > endPosition) {
downloadSize+=len - (curPosition - endPosition) + 1;
} else {
downloadSize+=len;
}
}
//下载完成设为true
this.finished = true;
bis.close();
fos.close();
} catch (IOException e) {
Log.d(getName() +" Error:", e.getMessage());
}
}
 
public boolean isFinished(){
return finished;
}
 
public int getDownloadSize() {
return downloadSize;
}
}

接下来就是使用图形界面来获取需要下载的内容,并实时更新下载进度条,代码如下所示:
package com.ideasandroid.demo;
 
import java.io.File;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
*  Copyright (C) 2010 ideasandroid
*  演示android多线程下载
*  欢迎访问http://www.ideasandroid.com
*  让程序开发不再那么神秘
*/
public class FileDownloadDemo extends Activity {
 
private EditText downloadUrl;
private EditText downloadFileName;
private EditText downloadThreadNum;
private Button downloadBt;
private ProgressBar downloadProgressBar;
private TextView progressMessage;
private int downloadedSize = 0;
private int fileSize = 0;
 
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
 
downloadUrl = (EditText) findViewById(R.id.downloadUrl);
downloadFileName = (EditText) findViewById(R.id.downloadFileName);
downloadThreadNum = (EditText) findViewById(R.id.downloadThreadNum);
progressMessage = (TextView) findViewById(R.id.progressMessage);
downloadBt = (Button) findViewById(R.id.downloadBt);
downloadProgressBar = (ProgressBar) findViewById(R.id.downloadProgressBar);
downloadProgressBar.setVisibility(View.VISIBLE);
downloadProgressBar.setMax(100);
downloadProgressBar.setProgress(0);
downloadBt.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
download();
}
});
}
 
private void download() {
// 获取SD卡目录
String dowloadDir = Environment.getExternalStorageDirectory()
+ "/ideasdownload/";
File file = new File(dowloadDir);
//创建下载目录
if (!file.exists()) {
file.mkdirs();
}
 
//读取下载线程数,如果为空,则单线程下载
int downloadTN = Integer.valueOf("".equals(downloadThreadNum.getText()
.toString()) ? "1" : downloadThreadNum.getText().toString());
//如果下载文件名为空则获取Url尾为文件名
int fileNameStart = downloadUrl.getText().toString().lastIndexOf("/");
String fileName = "".equals(downloadFileName.getText().toString()) ? downloadUrl
.getText().toString().substring(fileNameStart)
: downloadFileName.getText().toString();
//开始下载前把下载按钮设置为不可用
downloadBt.setClickable(false);
//进度条设为0
downloadProgressBar.setProgress(0);
//启动文件下载线程
new downloadTask(downloadUrl.getText().toString(), Integer
.valueOf(downloadTN), dowloadDir + fileName).start();
}
 
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//当收到更新视图消息时,计算已完成下载百分比,同时更新进度条信息
int progress = (Double.valueOf((downloadedSize * 1.0 / fileSize * 100))).intValue();
if (progress == 100) {
downloadBt.setClickable(true);
progressMessage.setText("下载完成!");
} else {
progressMessage.setText("当前进度:" + progress + "%");
}
downloadProgressBar.setProgress(progress);
}
 
};
 
/**
* @author ideasandroid
* 主下载线程
*/
public class downloadTask extends Thread {
private int blockSize, downloadSizeMore;
private int threadNum = 5;
String urlStr, threadNo, fileName;
 
public downloadTask(String urlStr, int threadNum, String fileName) {
this.urlStr = urlStr;
this.threadNum = threadNum;
this.fileName = fileName;
}
 
@Override
public void run() {
FileDownloadThread[] fds = new FileDownloadThread[threadNum];
try {
URL url = new URL(urlStr);
URLConnection conn = url.openConnection();
//获取下载文件的总大小
fileSize = conn.getContentLength();
//计算每个线程要下载的数据量
blockSize = fileSize / threadNum;
// 解决整除后百分比计算误差
downloadSizeMore = (fileSize % threadNum);
File file = new File(fileName);
for (int i = 0; i < threadNum; i++) {
//启动线程,分别下载自己需要下载的部分
FileDownloadThread fdt = new FileDownloadThread(url, file,
i * blockSize, (i + 1) * blockSize - 1);
fdt.setName("Thread" + i);
fdt.start();
fds[i] = fdt;
}
boolean finished = false;
while (!finished) {
// 先把整除的余数搞定
downloadedSize = downloadSizeMore;
finished = true;
for (int i = 0; i < fds.length; i++) {
downloadedSize += fds[i].getDownloadSize();
if (!fds[i].isFinished()) {
finished = false;
}
}
//通知handler去更新视图组件
handler.sendEmptyMessage(0);
//休息1秒后再读取下载进度
sleep(1000);
}
} catch (Exception e) {
 
}
 
}
}
}
分享到:
评论

相关推荐

    Android多线程处理 详解

    ### Android多线程处理详解 #### 一、Android进程与线程基础 在深入探讨Android中的多线程处理之前,我们需要先理解Android的基本进程和线程模型。 **Android进程:** 当一个Android应用首次启动时,系统会为该...

    Android多线程详解与Demo

    本文将深入探讨Android多线程的使用,包括其原理、常见方法以及如何通过实例进行实践。 首先,我们需要理解Android主线程,也被称为UI线程,它的主要任务是处理用户界面事件,如触摸事件、绘制视图等。如果在这个...

    详解Android中的多线程断点下载

    首先来看一下多线程下载的原理。多线程下载就是将同一个网络上的原始文件根据线程个数分成均等份,然后每个单独的线程下载对应的一部分,然后再将下载好的文件按照原始文件的顺序“拼接”起来就构 成了完整的文件了...

    12_Android 多线程AsyncTask详解

    Android中的多线程处理是应用程序性能优化的关键,特别是当涉及到UI更新和长时间运行的任务时。在Android系统中,每个应用程序都有一个主线程(Main Thread),也称为UI线程,负责处理用户交互和绘制用户界面。由于...

    android多线程handler/message机制详解

    Android 多线程Handler/Message机制详解 Android 多线程机制是 Android 应用程序中最重要的组件之一,它允许应用程序在后台执行一些操作,而不影响用户的交互体验。在 Android 中,多线程机制是基于 Handler 和 ...

    android多线程机制

    ### Android多线程机制详解 #### 一、引言 Android多线程机制是Android开发中非常重要的一部分,尤其是在处理耗时任务(如网络请求、大数据处理等)时,避免阻塞UI线程,保证应用程序的流畅性和响应性。本文将详细...

    android客户端多线程下载案例(实现断点续传,包括客户端服务端,还有注释)

    android客户端多线程下载,断点续传,多线程下载,网络编程详解代码 网络搜索《Android 4.0 网络编程详解代码》中的 第5章:Android中的网络数据下载及JSON的操作 中代码不全,少了个终于的activity,现自己跑通后上传以...

    Android多线程下载示例详解

    主要为大家详细介绍了Android多线程下载示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    Android多线程断点续传下载示例详解

    在上一篇博文《Android多线程下载示例》中,我们讲解了如何实现Android的多线程下载功能,通过将整个文件分成多个数据块,开启多个线程,让每个线程分别下载一个相应的数据块来实现多线程下载的功能。多线程下载中,...

    android多任务多线程断点下载.pdf

    在Android开发中,多任务多线程断点下载是一项常见的需求,尤其是在处理大文件时,为了提高下载效率和用户体验,通常会采用这种方式。AndroidHttpClient是Android SDK 2.2版本引入的一个类,提供了更高效、易用的...

    android多线程

    ### Android多线程详解 #### 一、进程与线程概览 在深入探讨Android多线程之前,我们首先理解进程和线程的基本概念。**进程**是正在运行的程序实例,每个进程拥有自己独立的内存空间和系统资源。而**线程**则是...

    Android多线程详解.pdf

    本文将深入探讨Android多线程的相关知识点。 首先,`Thread`类是Java语言中用于创建和管理线程的核心类。通过调用其`currentThread()`方法,我们可以获取当前正在执行的线程对象。`getName()`和`getId()`方法分别...

    Android AsyncTask多线程详解

    Android Asynctask 先小试牛刀,了解一下各个方法执行过程,关注博客http://himici.com/

    android多线程模型和service分析

    ### Android多线程模型与Service深入解析 #### 线程与进程概念解析 在深入探讨Android中的多线程模型之前,我们先明确一下基本概念。在计算机科学中,**进程**(Process)与**线程**(Thread)是两个核心概念。进程是...

    Handler与Android多线程详解

    下面是一段大家都比较熟悉的代码: 代码如下:Handler ...上述代码中的handler并没有调用线程myThread的start()方法,而是直接调用了run()方法,这也就意味着实际上并没有创建一个新的线程,只是在当前线程中调用run()

    Android多线程AsyncTask详解

    "Android多线程AsyncTask详解" Android多线程AsyncTask详解主要为大家详细介绍了Android多线程AsyncTask的相关资料,具有一定的参考价值,本篇随笔将讲解一下Android的多线程的知识,以及如何通过AsyncTask机制来...

    andorid 多线程下载

    ### Android多线程下载工具类实现详解 #### 一、背景与目的 在移动应用开发过程中,文件下载是一项常见的功能需求。特别是在Android平台,随着应用功能的不断扩展,用户对于下载速度的要求也越来越高。传统的单...

    Android Task 进程与线程详解

    "Android Task 进程与线程详解" Android 中的 Task 概念是指一组以栈的模式聚集在一起的 Activity 组件集合,具有潜在的前后驱关联。Task 的主要作用是将组件之间的连接,从进程概念的细节中剥离出来,可以以一种...

    《给 Android 开发者的 RxJava 详解》 PDF

    《给 Android 开发者的 RxJava 详解》这本书深入浅出地介绍了如何在 Android 开发环境中应用 RxJava 这个强大的响应式编程库。RxJava 是一个用于处理异步数据流和事件流的库,它引入了函数式编程的概念,使得复杂的...

Global site tag (gtag.js) - Google Analytics