android中多线程下载实例
程序员文章站
2023-11-27 18:45:58
复制代码 代码如下: public class mainactivity extends activity { // 声明控件 // 路径与线程数量 private edi...
复制代码 代码如下:
public class mainactivity extends activity {
// 声明控件
// 路径与线程数量
private edittext et_url, et_num;
// 进度条
public static progressbar pb_thread;
// 显示进度的操作
private textview tv_pb;
// 线程的数量
public static int threadnum = 3;
// 每个线程负责下载的大小
public int blocksize;
public static int threadcount;// 数量
// 访问的path
public string path;
public static boolean flag = true;
// 记录进度条的值
public static int pb_count = 0;
public static handler handler;
public static final int textvalue = 1;
public static int pb_num = 0;
public static int size = 0;
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
et_url = (edittext) findviewbyid(r.id.et_path);
et_num = (edittext) findviewbyid(r.id.et_threadnum);
pb_thread = (progressbar) findviewbyid(r.id.pb_down);
tv_pb = (textview) findviewbyid(r.id.tv_pb);
handler = new handler() {
@override
public void handlemessage(message msg) {
super.handlemessage(msg);
switch (msg.what) {
case textvalue:
system.out.println("-----------------------"
+ mainactivity.pb_count + "//////"
+ mainactivity.size);
// 改变textview
pb_num = (mainactivity.pb_count * 100) / mainactivity.size;
tv_pb.settext("当前进度是+" + pb_num + "%");
break;
default:
break;
}
}
};
}
@override
public boolean oncreateoptionsmenu(menu menu) {
// inflate the menu; this adds items to the action bar if it is present.
// getmenuinflater().inflate(r.menu.down, menu);
return true;
}
//下载操作
public void download(view v) {
// 改变变量值:
mainactivity.flag = true;
mainactivity.pb_count = 0;
path = et_url.gettext().tostring();
string threadnum_et = et_num.gettext().tostring();
if (textutils.isempty(path) || textutils.isempty(threadnum_et)) {
toast.maketext(this, "不能为空", toast.length_long).show();
return;
}
toast.maketext(this, "url:" + path + "--" + threadnum_et,
toast.length_long).show();
// 转换成数字
threadnum = integer.valueof(threadnum_et);
new thread(new runnable() {
@override
public void run() {
try {
// 创建出url对象
url url = new url(path);
// 创建出 httpurlconnection对象
httpurlconnection httpurlconnection = (httpurlconnection) url
.openconnection();
// 设置 发请求发送的方式
httpurlconnection.setrequestmethod("get");
// 设置请求是否超时时间
httpurlconnection.setconnecttimeout(5000);
// 设置
httpurlconnection
.setrequestproperty("user-agent",
" mozilla/5.0 (compatible; msie 10.0; windows nt 6.2; trident/6.0)");
// 是否响应成功
if (httpurlconnection.getresponsecode() == 200) {
// 获取文件的大小
size = httpurlconnection.getcontentlength();
system.out.println("文件的大小" + size);
// 设置进度条的最大值
pb_thread.setmax(size);
// 创建文件 //保存到sd卡上
// 首先判断是否拥有sdcard
if (environment.getexternalstoragestate().equals(
environment.media_mounted)) {
// 获取sdcard文件目录对象
file sdfile = environment
.getexternalstoragedirectory();
// 创建文件对象
file file = new file(sdfile, "youdao.exe");
randomaccessfile accessfile = new randomaccessfile(
file, "rwd");
// 设置文件的大小
accessfile.setlength(size);
// 每个线程下载的大小
blocksize = size / threadnum;
// 开三个线程 操作此文件
for (int i = 1; i <= threadnum; i++) {
// 1 2 3
// 计算出每个线程开始的位置
int startsize = (i - 1) * blocksize;
// 结束位置
int endsize = (i) * blocksize;
// 当线程是最后一个线程的时候
if (i == threadnum) {
// 判断文件的大小是否大于计算出来的结束位置
if (size > endsize) {
// 结束位置 等于 文件的大小
endsize = size;
}
}
// 为每个线程创建一个随机的读取
randomaccessfile threadaccessfile = new randomaccessfile(
file, "rwd");
new thread(new downloadthread(i,
threadaccessfile, startsize, endsize,
path)).start();
}
}
}
} catch (malformedurlexception e) {
// todo auto-generated catch block
e.printstacktrace();
} catch (ioexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
}
}).start();
}
//暂停操作
public void downpause(view v) {
toast.maketext(this, "暂停", toast.length_long).show();
this.flag = false;
}
}
复制代码 代码如下:
public class downloadthread implements runnable {
// 下载文件的封装
public randomaccessfile accessfile;
// 线程下载文件的起始位置
public int startsize;
public int endsize;
// 文件下载的path路径
public string path;
public int threadid; // 线程的标识
public downloadthread(int threadid, randomaccessfile accessfile,
int startsize, int endsize, string path) {
this.threadid = threadid;
this.accessfile = accessfile;
this.startsize = startsize;
this.endsize = endsize;
this.path = path;
}
@override
public void run() {
// 执行run方法
try {
// 创建文件到sd卡上去
// 首先判断是否拥有sdcard
if (environment.getexternalstoragestate().equals(
environment.media_mounted)) {
// 获取sdcard文件目录对象
file sdfile = environment.getexternalstoragedirectory();
file threadfile = new file(sdfile, threadid + ".txt");
if (threadfile.exists()) {
// 读取该文件的内容
// 创建文件的输入流对象
fileinputstream fis = new fileinputstream(threadfile);
// 采用工具类读取
byte data[] = streamtools.istodata(fis);
// 转化成字符串
string threadlen = new string(data);
if ((threadlen != null) && (!"".equals(threadlen))) {
startsize = integer.valueof(threadlen);
// 解决 416bug的错误
if (startsize > endsize) {
startsize = endsize - 1;
}
}
}
// 创建文件
// 创建url对象
url url = new url(path);
// 创建httpurlconnection对象
httpurlconnection httpurlconnection = (httpurlconnection) url
.openconnection();
// 设置请求的头
httpurlconnection.setrequestmethod("get");
// 设置请求是否超时时间
httpurlconnection.setconnecttimeout(5000);
// 设置
httpurlconnection
.setrequestproperty("user-agent",
" mozilla/5.0 (compatible; msie 10.0; windows nt 6.2; trident/6.0)");
// 关键的设置
httpurlconnection.setrequestproperty("range", "bytes="
+ startsize + "-" + endsize);
// 输出当前线程
system.out.println("当前线程" + threadid + " 下载开始位置:" + startsize
+ " 下载结束位置:" + endsize);
// 响应成功
// 设置随机读取文件的 开始位置
accessfile.seek(startsize);
// 获取相应流对象
inputstream is = httpurlconnection.getinputstream();
// 创建输出流对象
byte buffer[] = new byte[1024];
int len = 0;
int threadtotal = 0;// 每个线程下载后保存记录 /
while ((len = is.read(buffer)) != -1) {
accessfile.write(buffer, 0, len);
threadtotal += len;// 记录你写入的长度 //xml文件
//改变进度条:
setprogressbar(len);
// 通过文件记录文件下载的长度
fileoutputstream fos = new fileoutputstream(threadfile);
fos.write((threadtotal + "").getbytes());
fos.flush();
fos.close();
//发送handler消息
mainactivity.handler.sendemptymessage(mainactivity.textvalue);
if(!mainactivity.flag){
return;
}
}
accessfile.close();
is.close();
system.out.println(threadid + "线程执行完毕");
// 线程操作
synchronized (mainactivity.class) {
mainactivity.threadcount++;
if (mainactivity.threadcount >= mainactivity.threadnum) {
for (int i = 1; i <= mainactivity.threadnum; i++) {
// 获取sdcard上的文件
file deletefile = new file(sdfile, i + ".txt");
if (deletefile.exists()) {
// 文件删除
deletefile.delete();
}
}
}
}
}
} catch (malformedurlexception e) {
// todo auto-generated catch block
e.printstacktrace();
} catch (ioexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
}
public synchronized void setprogressbar(int len){
mainactivity.pb_count+=len;
mainactivity.pb_thread.setprogress(mainactivity.pb_count);
}
}
复制代码 代码如下:
public class streamtools {
public static byte[] istodata(inputstream is) throws ioexception{
// 字节输出流
bytearrayoutputstream bops = new bytearrayoutputstream();
// 读取数据的缓存区
byte buffer[] = new byte[1024];
// 读取长度的记录
int len = 0;
// 循环读取
while ((len = is.read(buffer)) != -1) {
bops.write(buffer, 0, len);
}
// 把读取的内容转换成byte数组
byte data[] = bops.tobytearray();
bops.flush();
bops.close();
is.close();
return data;
}
}
完整源码
上一篇: android 获取上一个activity返回值的方法
下一篇: 产品推广小课堂:提高转化率很重要