android断点续传

转载 2012年03月26日 16:04:23

本文将介绍在android平台下如何实现多线程下载,大家都知道,android平台使用java做为开发语言,所以java中支持的多线程下载方式在android平台下都支持,其中主要有两种方式可以实现多线程下载。


一种方式是使用很多个线程分别下载文件的不同部分,最后把所有下载完的文件合并成一个文件。另一种方式是使用java为我们提供的RandomAccessFile类实现多线程的下载。

从性能上分析,第二种方式的存取速度会慢一些,但开发起来较为容易,不需要进行合并文件等操作。本文将使用第二种方式来实现多线程下载,最终效果如下图所示:


5.png

 

 


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

Java代码
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) {

            }

        }
    }
}

Java代码
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多线程下载
*  让程序开发不再那么神秘

*  单个下载线程
*/
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;
    }
}

Scratch少儿趣味编程.pdf

  • 2017年11月20日 16:11
  • 35.57MB
  • 下载

武汉Scratch青少儿趣味编程公开课,强势来袭!

刚会打酱油的孩子就能学编程了吗?真的,这不是在逗你玩!   近两年来,人工智能(AI)概念大热,少儿编程教育也随之受到了不少家长的关注。但家长们可别误以为少儿编程教育只是为了把孩子培...
  • jiadabin
  • jiadabin
  • 2018年01月11日 12:51
  • 134

SCRATCH 少儿趣味编程 2.pdf

  • 2017年11月20日 16:06
  • 33.93MB
  • 下载

Android 断点续传下载功能实现

主要实现文件下载的暂停和继续下载功能。 用到的知识点: 1、Service的使用以及Service与Activity之间的数据交互; 2、SQLite数据库的简单使用; 3、文件下载与存储; ...
  • c19344881x
  • c19344881x
  • 2015年05月19日 16:22
  • 874

Android学习笔记(十三)-使用Socket进行大文件断点上传续传

在Android中上传文件可以采用HTTP方式,也可以采用Socket方式,但是HTTP方式不能上传大文件,这里介绍一种通过Socket方式来进行断点续传的方式,服务端会记录下文件的上传进度,当某一次...
  • geniusxiaoyu
  • geniusxiaoyu
  • 2012年02月28日 17:16
  • 9412

Android开发——断点续传原理以及实现

0.  前言在Android开发中,断点续传听起来挺容易,在下载一个文件时点击暂停任务暂停,点击开始会继续下载文件。但是真正实现起来知识点还是蛮多的,因此今天有时间实现了一下,并进行记录。本文原创,转...
  • SEU_Calvin
  • SEU_Calvin
  • 2016年12月19日 22:16
  • 19134

Android多文件断点续传(三)——实现文件断点续传

上一篇中我们主要介绍了如何实现数据库储存下载信息,如果你还没阅读过,建议先阅读上一篇Android多文件断点续传(二)——实现数据库储存下载信息。数据库我们已经准备好,现在就可以开始来实现Downlo...
  • a1533588867
  • a1533588867
  • 2016年11月11日 18:40
  • 1162

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

本文将介绍在android平台下如何实现多线程下载,大家都知道,android平台使用java做为开发语言,所以java中支持的多线程下载方式在android平台下都支持,其中主要有两种方式可以实现多...
  • findsafety
  • findsafety
  • 2016年02月18日 00:07
  • 2118

android 多线程断点续传下载 一

想做一个下载功能,当然理想的功能要支持多任务同时下载,断点续传的功能,我想一步一步来,首先困难摆在了多任务这里 开始我的思路是在一个Service中启动下载的流操作,然后通过Service中声明一个...
  • shimiso
  • shimiso
  • 2011年09月09日 14:26
  • 14002

android断点续传实现应用程序更新下载

断点续传用到的知识点: 1.使用RandomAccessFile设定文件大小并于指定位置开始读数据[randomAccessFile.seek(position)]。     2.请求资源链接时指...
  • xiaozhang226
  • xiaozhang226
  • 2014年10月24日 09:43
  • 1363
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android断点续传
举报原因:
原因补充:

(最多只允许输入30个字)