Android实现多线程断点下载的方法

本文实例讲述了Android实现多线程断点下载的方法。分享给大家供大家参考。具体实现方法如下:

package cn.itcast.download;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import cn.itcast.mutiledownload.StreamTool;
import android.app.Activity;
import android.os.Bundle;
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;
import android.widget.Toast;
public class MutiledownloadActivity extends Activity implements OnClickListener {
  private ProgressBar pb;
  private Button bt;
  private TextView tv;
  private EditText et;
  boolean flag = true;
  boolean stopflag = false;
  private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      pb.setProgress(total);
      int max = pb.getMax();
      if (total >= (max - 1)) {
        total = max;
        flag = false;
      }
      int result = total * 100 / max;
      tv.setText("当前进度 :" + result + "%");
      super.handleMessage(msg);
    }
  };
  int total = 0;
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    pb = (ProgressBar) this.findViewById(R.id.pb);
    bt = (Button) this.findViewById(R.id.bt);
    tv = (TextView) this.findViewById(R.id.tv_process);
    et = (EditText) this.findViewById(R.id.et);
    bt.setOnClickListener(this);
  }
  @Override
  public void onClick(View v) {
    switch (v.getId()) {
    case R.id.bt:
      // 创建一个子线程 定期的更新ui
      if("开始下载".equals(bt.getText().toString())){
        bt.setText("暂停");
        stopflag = false; //开始下载
      }
      else {
        bt.setText("开始下载");
        stopflag = true;
      }
        new Thread() {
          @Override
          public void run() {
            super.run();
            while (flag) {
              try {
                sleep(1000);
                // 如果total > = 文件长度
                Message msg = new Message();
                handler.sendMessage(msg);
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
            }
          }
        }.start(); 

        // 开始执行下载的操作
        String path = et.getText().toString().trim();
        if ("".equals(path)) {
          Toast.makeText(this, "路径不能为空", 1).show();
          return;
        }
        try {
          URL url = new URL(path);
          HttpURLConnection conn = (HttpURLConnection) url
              .openConnection();
          conn.setRequestMethod("GET");
          conn.setConnectTimeout(5000);
          conn.setRequestProperty("User-Agent",
              "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
          int code = conn.getResponseCode();
          if (code == 200) {
            int len = conn.getContentLength();
            RandomAccessFile file = new RandomAccessFile(
                "/mnt/sdcard/" + getFilenName(path), "rwd");
            // 1.设置本地文件大小跟服务器的文件大小一致
            file.setLength(len);
            // 设置进度条的最大值
            pb.setMax(len);
            // 2 .假设开启3 个线程
            int threadnumber = 3;
            int blocksize = len / threadnumber;
            /**
             * 线程1 0~ blocksize 线程2 1*bolocksize ~ 2*blocksize 线程3
             * 2*blocksize ~ 文件末尾
             */
            for (int i = 0; i < threadnumber; i++) {
              int startposition = i * blocksize;
              int endpositon = (i + 1) * blocksize;
              if (i == (threadnumber - 1)) {
                // 最后一个线程
                endpositon = len;
              }
              DownLoadTask task = new DownLoadTask(i, path,
                  startposition, endpositon);
              task.start();
            }
          }
        } catch (Exception e) {
          Toast.makeText(this, "下载出现异常", 0).show();
          e.printStackTrace();
        }
      break;
    }
  }
  class DownLoadTask extends Thread {
    int threadid;
    String filepath;
    int startposition;
    int endpositon;
    public DownLoadTask(int threadid, String filepath, int startposition,
        int endpositon) {
      this.threadid = threadid;
      this.filepath = filepath;
      this.startposition = startposition;
      this.endpositon = endpositon;
    }
    @Override
    public void run() {
      try {
        File postionfile = new File("/mnt/sdcard/" + threadid + ".txt");
        URL url = new URL(filepath);
        HttpURLConnection conn = (HttpURLConnection) url
            .openConnection();
        System.out.println("线程" + threadid + "正在下载 " + "开始位置 : "
            + startposition + "结束位置 " + endpositon);
        if (postionfile.exists()) {
          FileInputStream fis = new FileInputStream(postionfile);
          byte[] result = StreamTool.getBytes(fis);
          String str = new String(result);
          if (!"".equals(str)) {
            int newstartposition = Integer.parseInt(str);
            if (newstartposition > startposition) {
              startposition = newstartposition;
            }
          }
        }
        // "Range", "bytes=2097152-4194303")
        conn.setRequestProperty("Range", "bytes=" + startposition + "-"
            + endpositon);
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5000);
        conn.setRequestProperty("User-Agent",
            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
        InputStream is = conn.getInputStream();
        RandomAccessFile file = new RandomAccessFile("/mnt/sdcard/"
            + getFilenName(filepath), "rwd");
        // 设置 数据从文件哪个位置开始写
        file.seek(startposition);
        byte[] buffer = new byte[1024];
        int len = 0;
        // 代表当前读到的服务器数据的位置 ,同时这个值已经存储的文件的位置
        int currentPostion = startposition;
        // 创建一个文件对象 ,记录当前某个文件的下载位置
        while ((len = is.read(buffer)) != -1) {
          if (stopflag) {
            return;
          }
          file.write(buffer, 0, len);
          synchronized (MutiledownloadActivity.this) {
            total += len;
          }
          currentPostion += len;
          // 需要把currentPostion 信息给持久化到存储设备
          String position = currentPostion + "";
          FileOutputStream fos = new FileOutputStream(postionfile);
          fos.write(position.getBytes());
          fos.flush();
          fos.close();
        }
        file.close();
        System.out.println("线程" + threadid + "下载完毕");
        // 当线程下载完毕后 把文件删除掉
        if (postionfile.exists()) {
          postionfile.delete();
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
      super.run();
    }
  }
  public String getFilenName(String path) {
    int start = path.lastIndexOf("/") + 1;
    return path.substring(start, path.length());
  }
}

希望本文所述对大家的Android程序设计有所帮助。

(0)

相关推荐

  • Android原生实现多线程断点下载实例代码

    各位父老乡亲,我单汉三又回来了,今天为大家带来一个用原生的安卓写的多线程断点下载Demo. 通过本文你可以学习到: SQLite的基本使用,数据库的增删改查. Handler的消息处理与更新UI. Service(主要用于下载)的进阶与使用. 原生的json文件解析(多层嵌套). RandomAccessFile的基本使用,可以将文件分段. 基于HttpURLConnection的大文件下载. 上面内容结合,实现多线程,断点下载. Demo是在TV上运行的,图片显示的问题不要纠结了. 文件下载的

  • android多线程断点下载-带进度条和百分比进度显示效果

    android多线程断点下载,带进度条和百分比显示,断点下载的临时数据保存到SD卡的文本文档中,建议可以保存到本地数据库中,这样可以提高存取效率,从而提高系统性能. 效果: 打开软件: 下载中: 下载完毕: 附代码如下: package com.yy.multiDownloadOfBreakPoint; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.R

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

    首先来看一下多线程下载的原理.多线程下载就是将同一个网络上的原始文件根据线程个数分成均等份,然后每个单独的线程下载对应的一部分,然后再将下载好的文件按照原始文件的顺序"拼接"起来就构 成了完整的文件了.这样就大大提高了文件的下载效率.对于文件下载来说,多线程下载是必须要考虑的环节. 多线程下载大致可分为以下几个步骤: 一.获取服务器上的目标文件的大小 显然这一步是需要先访问一下网络,只需要获取到目标文件的总大小即可.目的是为了计算每个线程应该分配的下载任务. 二. 在本地创建一个跟原始

  • Android入门:多线程断点下载详细介绍

    本案例在于实现文件的多线程断点下载,即文件在下载一部分中断后,可继续接着已有进度下载,并通过进度条显示进度.也就是说在文件开始下载的同时,自动创建每个线程的下载进度的本地文件,下载中断后,重新进入应用点击下载,程序检查有没有本地文件的存在,若存在,获取本地文件中的下载进度,继续进行下载.当下载完成后,自动删除本地文件. 一.多线程断点下载介绍 所谓的多线程断点下载就是利用多线程下载,并且可被中断,如果突然没电了,重启手机后可以继续下载,而不需要重新下载: 利用的技术有:SQLite存储各个线程的

  • Android实现多线程断点下载的方法

    本文实例讲述了Android实现多线程断点下载的方法.分享给大家供大家参考.具体实现方法如下: package cn.itcast.download; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputSt

  • Android实现多线程断点下载

    目录 QDownload 1.如何使用 1.1.导入依赖 1.2.初始化下载组件 1.3.核心控制器DownloadManager 1.4.监听下载进度 1.5.下载相关的操作 1.6.应用市场apk下载的一个场景 总结 QDownload QDownload是基于Android平台实现的下载框架.API简洁易上手,只需5分钟即可实现一个多任务.多线程.断点下载的功能 支持功能如下: 支持多个下载任务同时下载单个任务支持开多个线程下载支持断点下载,在断网.进程被划掉可恢复下载自动校验服务器文件服

  • iOS开发网络篇—实现大文件的多线程断点下载

    说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始,创建一个和要下载的文件大小相同的文件(如果要下载的文件为100M,那么就在沙盒中创建一个100M的文件,然后计算每一段的下载量,开启多条线程下载各段的数据,分别写入对应的文件部分). 项目中用到的主要类如下: 完成的实现代码如下: 主控制器中的代码: #import "YYViewController.h" #import

  • Java实现多线程断点下载

    JAVA多线程断点下载原理如图: 代码如下: import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.n

  • Android实现断点下载的方法

    最近做的项目中需要实现断点下载,即用户一次下载可以分多次进行,下载过程可以中断,在目前大多数的带离线缓存的软件都是需要实现这一功能.本文阐述了通过sqlite3简单实现了一个具有断点下载功能的demo.言归正传,开始正文. 设计 数据库表存储元数据 DBHelper.java 用于业务存储的Dao Dao.java 抽象下载信息的Bean LoadInfo.java 呈现下载信息View MainActivity.java 存储下载信息Bean DownloadInfo.java 封装好的下载类

  • Java实现多线程断点下载实例代码(下载过程中可以暂停)

    线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配.不难理解,如果你线程多的话,那下载的越快. 现流行的下载软件都支持多线程,且支持中途暂停下载,再次开始时不会从头开始下载. 两种功能的实现步骤如下: (1)连接到下载资源文件时,首先判断资源文件大小,同步的在本地创建一个大小相同的临时文件用于存储下载数据. (2)根据线程数量确定每个线程所需下载的文

  • iOS NSURLSessionDownloadTask实现文件断点下载的方法

    所谓断点下载:就是实现开始.暂停.继续以及取消等操作.上一篇我们已经谈到了通过设置代理实现文件的连续下载,也就是文件从开始一直到下载完成,中途不中断.这种方式比较适用一些小文件的下载,比如:微信里面的表情包下砸.就算中途因为其他原因中断了下载,我们重新开始下载也不会浪费用户很多流量,用户体验也不会因此变的很差. 在实现断点下载之前:我们需要清楚对什么进行断点下载,是对网络请求NSURLSession还是对任务NSURLSessionDownloadTask.下载文件只会发送一次请求,我们操作应该

随机推荐