zoukankan      html  css  js  c++  java
  • Android文件下载(实现断点续传)

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

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

        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

  • 相关阅读:
    第四章JAVA EE基础知识
    第二章代码审计环境搭建
    第三章代码审计辅助工具简介
    python json.dumps 中文需要注意的事项
    multiprocessing 使用实践
    Python中*args和**kwargs的使用实践
    python 继承学习记录
    关于vue-element-admin启动项目遇到的一些问题
    @RequestParam
    前端菜单点击切换样式,菜单控制iframe
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/4588376.html
Copyright © 2011-2022 走看看