Android文件下载(实现断点续传)

摘要:
importjava.net.URL;importjava.net.URLConnection;importandroid.app.活动;downloadBt=(按钮)findViewById(R.id.downloadBt);downloadProgressBar=(ProgressBar)findViewById(R.id.downloadProgressBar);

本文将介绍在android平台下如何实现多线程下载,大家都知道,android平台使用java做为开发语言,所以java中支持的多线程下载方式在android平台下都支持,其中主要有两种方式可以实现多线程下载。
一种方式是使用很多个线程分别下载文件的不同部分,最后把所有下载完的文件合并成一个文件。另一种方式是使用java为我们提供的RandomAccessFile类实现多线程的下载。
从性能上分析,第二种方式的存取速度会慢一些,但开发起来较为容易,不需要进行合并文件等操作。本文将使用第二种方式来实现多线程下载,最终效果如下图所示:

Android文件下载(实现断点续传)第1张

使用图形界面来获取需要下载的内容,并实时更新下载进度条,代码如下所示:

    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) {  
       
                }  
       
            }  
        }  
    }  
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;
    }
}

Andorid多线程断点续传下载器:http://www.jcodecraeer.com/a/opensource/2015/0602/2978.html

免责声明:文章转载自《Android文件下载(实现断点续传)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇网页设计太麻烦?15款免费优质Bootstrap UI工具包助你效率倍增!Java平台下利用aspose转word为PDF实现文档在线预览下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

2个线程 循环打印ababab...

第一种方式: package mianshi.Thread; /** * 2个线程 循环打印 abab * 实现1: * note: 2个线程操作 Work类, work类里面 实现互斥的 2个打印方法 A B。 2个线程各自调用A,B */ public class ThreadA { public static void main(...

设置修改CentOS系统时区

一、时区 1. 查看当前时区date -R 2. 修改设置时区方法(1)tzselect方法(2) 仅限于RedHat Linux 和 CentOS系统timeconfig方法(3) 适用于Debiandpkg-reconfigure tzdata3. 复制相应的时区文件,替换CentOS系统时区文件;或者创建链接文件cp /usr/share/zonei...

在Android Studio使用ButterKnife的步骤详解

ButterKnife是一个android的view注入的框架,什么是view注入呢,就是我们经常进行的操作findViewById(),在控件个数和需要添加点击的次数比较少的情况下,并感觉不到有什么区别,但是如果数量比较多的情况下,还一个一个的findViewById(),再添加点击事件的话,那就心态爆炸了,还会容易出错,所以下面介绍一下ButterKn...

QuickRun-快速运行助手

  大家平时需要打开软件的时候都是怎么操作的?一般来说有三种方式: 切换到桌面再点击软件的快捷方式(会将当前正在操作的软件隐藏,再切换回之前的状态比较麻烦,特别是桌面被密密麻麻的图标铺满的时候,找到一个快捷方式更是费劲) 是点击开始菜单,从程序列表中找到软件的快捷方式(安装的软件较多候,找到快捷方式也会花点时间) 是将常用软件锁定到任务栏,直接点击任务栏...

Hadoop HDFS命令行操作

1、列出所有命令 hdfs dfs -help 2、查看某个一个命令的详细 hdfs dfs -help -put 3、ls 查看HDFS系统中文件和目录,例如查看根目录 hdfs dfs -ls /  列出所有目录和文件 hdfs dfs -ls -R /  4、put 将本地文件上传道HDFS系统中 hdfs dfs -put test.txt...

C#中的多线程

原文:http://www.albahari.com/threading/part2.aspx 文章来源:http://blog.gkarch.com/threading/part2.html 1同步概要 在第 1 部分:基础知识中,我们描述了如何在线程上启动任务、配置线程以及双向传递数据。同时也说明了局部变量对于线程来说是私有的,以及引用是如何在线程之间...