Android 多线程断点续传下载

通过HttpURLConnection的setRequestProperty和RandomAccessFile结合使用实现文件多线程下载和断点续传。

xml布局:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:id="@+id/activity_main"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     android:orientation="vertical"
 8     android:paddingBottom="@dimen/activity_vertical_margin"
 9     android:paddingLeft="@dimen/activity_horizontal_margin"
10     android:paddingRight="@dimen/activity_horizontal_margin"
11     android:paddingTop="@dimen/activity_vertical_margin"
12     tools:context="com.zhang.multidown.MainActivity">
13
14     <EditText
15         android:id="@+id/et_fileUrl"
16         android:layout_width="match_parent"
17         android:layout_height="wrap_content"
18         android:inputType="textUri" />
19
20     <ProgressBar
21         android:id="@+id/progressBar"
22         style="@style/Widget.AppCompat.ProgressBar.Horizontal"
23         android:layout_width="match_parent"
24         android:layout_height="wrap_content" />
25
26     <Button
27         android:id="@+id/btn_down"
28         android:layout_width="match_parent"
29         android:layout_height="wrap_content"
30         android:onClick="onClickDown"
31         android:text="下载" />
32 </LinearLayout>
  1 package com.zhang.multidown;
  2
  3 import android.os.Bundle;
  4 import android.os.Environment;
  5 import android.support.v7.app.AppCompatActivity;
  6 import android.view.View;
  7 import android.widget.Button;
  8 import android.widget.EditText;
  9 import android.widget.ProgressBar;
 10 import android.widget.Toast;
 11
 12 import java.io.File;
 13 import java.io.IOException;
 14 import java.io.InputStream;
 15 import java.io.RandomAccessFile;
 16 import java.net.HttpURLConnection;
 17 import java.net.MalformedURLException;
 18 import java.net.URL;
 19 import java.util.ArrayList;
 20 import java.util.HashMap;
 21 import java.util.List;
 22
 23 public class MainActivity extends AppCompatActivity {
 24
 25     private ProgressBar progressBar;
 26     private EditText etUrl;
 27     private Button btnDown;
 28     private int total = 0;
 29     private boolean downloading = false;
 30     private URL url;
 31     private File file;
 32     private List<HashMap<String, Integer>> threadList;
 33     private int length;
 34
 35 //    Handler handler = new Handler(new Handler.Callback() {
 36 //        @Override
 37 //        public boolean handleMessage(Message msg) {
 38 //            if (msg.what == 0) {
 39 //                progressBar.setProgress(msg.arg1);
 40 //                if (msg.arg1 == length) {
 41 //                    Toast.makeText(MainActivity.this, "下载完成!", Toast.LENGTH_SHORT).show();
 42 //                    total = 0;
 43 //                }
 44 //            }
 45 //            return false;
 46 //        }
 47 //    });
 48
 49     @Override
 50     protected void onCreate(Bundle savedInstanceState) {
 51         super.onCreate(savedInstanceState);
 52         setContentView(R.layout.activity_main);
 53
 54         progressBar = (ProgressBar) findViewById(R.id.progressBar);
 55         etUrl = (EditText) findViewById(R.id.et_fileUrl);
 56         btnDown = (Button) findViewById(R.id.btn_down);
 57         threadList = new ArrayList<>();
 58
 59     }
 60
 61     public void onClickDown(View view) {
 62
 63         if (downloading) {
 64             downloading = false;
 65             btnDown.setText("下载");
 66             return;
 67         }
 68         downloading = true;
 69         btnDown.setText("暂停");
 70
 71         if (threadList.size() == 0) {
 72             new Thread(new Runnable() {
 73                 @Override
 74                 public void run() {
 75                     try {
 76                         url = new URL(etUrl.getText().toString());
 77                         HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 78                         connection.setRequestMethod("GET");
 79                         connection.setConnectTimeout(5000);
 80                         connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");
 81                         length = connection.getContentLength();
 82                         progressBar.setMax(length);
 83                         progressBar.setProgress(0);
 84
 85                         if (length < 0) {
 86                             runOnUiThread(new Runnable() {
 87                                 @Override
 88                                 public void run() {
 89                                     Toast.makeText(MainActivity.this, "File not found !", Toast.LENGTH_SHORT).show();
 90                                 }
 91                             });
 92
 93                             return;
 94                         }
 95
 96                         file = new File(Environment.getExternalStorageDirectory(), getFileName(etUrl.getText().toString()));
 97                         RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
 98                         randomAccessFile.setLength(length);
 99
100                         int blockSize = length / 3;
101                         for (int i = 0; i < 3; i++) {
102                             int begin = i * blockSize;
103                             int end = (i + 1) * blockSize - 1;
104                             if (i == 2) {
105                                 end = length;
106                             }
107
108                             HashMap<String, Integer> map = new HashMap<>();
109                             map.put("begin", begin);
110                             map.put("end", end);
111                             map.put("finished", 0);
112                             threadList.add(map);
113
114                             //创建线程 下载文件
115                             new Thread(new DownloadRunnable(begin, end, i, file, url)).start();
116                         }
117
118                     } catch (MalformedURLException e) {
119                         e.printStackTrace();
120                         Toast.makeText(MainActivity.this, "URL Error !", Toast.LENGTH_SHORT).show();
121                     } catch (IOException e) {
122                         e.printStackTrace();
123                     }
124                 }
125             }).start();
126         } else {
127             //恢复下载
128             for (int i = 0; i < threadList.size(); i++) {
129                 HashMap<String, Integer> map = threadList.get(i);
130                 int begin = map.get("begin");
131                 int end = map.get("end");
132                 int finished = map.get("finished");
133                 new Thread(new DownloadRunnable(begin + finished, end, i, file, url)).start();
134             }
135         }
136     }
137
138     private String getFileName(String url) {
139         int index = url.lastIndexOf("/") + 1;
140         return url.substring(index);
141     }
142
143     class DownloadRunnable implements Runnable {
144
145         private int begin;
146         private int end;
147         private int id;
148         private File file;
149         private URL url;
150
151         public DownloadRunnable(int begin, int end, int id, File file, URL url) {
152             this.begin = begin;
153             this.end = end;
154             this.id = id;
155             this.file = file;
156             this.url = url;
157         }
158
159         @Override
160         public void run() {
161             try {
162                 if (begin > end) {
163                     return;
164                 }
165                 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
166                 connection.setRequestMethod("GET");
167                 connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");
168                 connection.setRequestProperty("Range", "bytes=" + begin + "-" + end);
169
170                 InputStream is = connection.getInputStream();
171                 byte[] buf = new byte[1024 * 1024];
172                 RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
173                 randomAccessFile.seek(begin);
174                 int len;
175                 HashMap<String, Integer> map = threadList.get(id);
176                 while ((len = is.read(buf)) != -1 && downloading) {
177                     randomAccessFile.write(buf, 0, len);
178                     updateProgress(len);
179                     map.put("finished", map.get("finished") + len);
180                     System.out.println("Download:" + total);
181                 }
182                 is.close();
183                 randomAccessFile.close();
184
185             } catch (IOException e) {
186                 e.printStackTrace();
187             }
188         }
189     }
190
191     synchronized private void updateProgress(int len) {
192         total += len;
193 //        handler.obtainMessage(0, total, 0).sendToTarget();
194         runOnUiThread(new Runnable() {
195             @Override
196             public void run() {
197                 progressBar.setProgress(total);
198                 if (total == length) {
199                     Toast.makeText(MainActivity.this, "下载完成!", Toast.LENGTH_SHORT).show();
200                     total = 0;
201                     btnDown.setText("完成");
202                 }
203             }
204         });
205     }
206 }

manifest需要添加网络权限和文件写入权限。

时间: 2024-08-11 07:42:59

Android 多线程断点续传下载的相关文章

Android多线程断点续传下载

这个月接到一个项目,要写一个像360助手一样的对于软件管理的APP:其中,遇到了一个问题:多线程断点下载 这个 ,由于之前没有写过这方面的应用功能.所以,不免要自学了.然后就在各个昂站上收索并整理了一下.跟大家分享一下,也能加深我在这方面的理解. 什么是多线程下载? 多线程下载其实就是迅雷,BT一些下载原理,通过多个线程同时和服务器连接,那么你就可以榨取到较高的带宽了,大致做法是将文件切割成N块,每块交给单独一个线程去下载,各自下载完成后将文件块组合成一个文件,程序上要完成做切割和组装的小算法

android 多线程断点续传下载 四 - 仿下载助手

我们先一起简单回顾下它的基本原理. http://blog.csdn.net/shimiso/article/details/6763664  android 多线程断点续传下载 一 http://blog.csdn.net/shimiso/article/details/6763986  android 多线程断点续传下载 二 http://blog.csdn.net/shimiso/article/details/8448544  android 多线程断点续传下载 三 界面效果 线程池 T

Android多线程断点续传下载原理及实现

这段时间看了看工作室的工具库的下载组件,发现其存在一些问题: 1.下载核心逻辑有 bug,在暂停下载或下载失败等情况时有概率无法顺利完成下载.2.虽然原来的设计是采用多线程断点续传的设计,但打了一下日志发现其实下载任务都是在同一个线程下串行执行,并没有起到加快下载速度的作用. 考虑到原来的代码并不复杂,因此对这部分下载组件进行了重写.这里记录一下里面的多线程断点续传功能的实现. 请查看完整的PDF版(更多完整项目下载.未完待续.源码.图文知识后续上传github.)可以点击关于我联系我获取完整P

Android实现网络多线程断点续传下载(转)

本示例介绍在Android平台下通过HTTP协议实现断点续传下载. 我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多线程断点需要什么功能? 1.多线程下载, 2.支持断点. 使用多线程的好处:使用多线程下载会提升文件下载的速度.那么多线程下载文件的过程是:  (1)首先获得下载文件的长度,然后设置本地文件的长度. HttpURLConnection.getContentLength();//获取下载文件的长度 R

Android实现网络多线程断点续传下载

本示例介绍在Android平台下通过HTTP协议实现断点续传下载. 我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多线程断点需要什么功能? 1.多线程下载, 2.支持断点. 使用多线程的好处:使用多线程下载会提升文件下载的速度.那么多线程下载文件的过程是: (1)首先获得下载文件的长度,然后设置本地文件的长度. HttpURLConnection.getContentLength();//获取下载文件的长度 Ra

Android 多线程多任务下载框架的实现(一)

什么是多线程多任务下载框架: Android 多线程多任务下载框架 封装了一个下载工具类,该下载工具支持多线程下载,下载任务队列,下载进度更新,取消下载等.可用于应用市场app的下载,音乐下载等. 为什么需要多线程多任务下载框架: 我们在开发Android 应用市场的时候需要下载apk,这个时候用户希望能同时下载多个apk并且显示正确的进度条信息,且下载速度快,那么我们就需要多线程多任务下载框架来支持这些功能,来达到很好的用户体验. 怎么实现多线程多任务下载框架: 涉及到的知识点: 1.线程操作

Android 多线程断点下载源码

源码下载地址   http://download.csdn.net/detail/kiduo08/7709391 Android 多线程断点下载源码

Android 多线程断点续传同时下载多个大文件

最近学习在Android环境中一些网络请求方面的知识,其中有一部分是关于网络下载方面的知识.在这里解析一下自己写的demo,总结一下自己所学的知识.下图为demo的效果图,仿照一些应用下载商城在ListView中列出加载项,然后可以可以下载和停止. 1.概述 这里有几个比较重要的类DownloadManager.DownloadService.DownloadTask.ThreadDAOImpl.主要的下载流程如下. (1) DownloadManager 负责下载任务的调配,以及下载服务Dow

基于ibcurl的跨平台多线程断点续传下载库

之前写过一个多线程断点续传的下载库,不过那个是基于一个linux的下载程序.windows下运行还好,android下就各种问题,调试起来还麻烦.后面开发游戏的时候,一方面对下载要求不高,另一方面也精力有限,所以就没有继续研究. 趁现在有时间,我希望实现一个自己满意的下载库,满足以下需求: 1.多线程下载,根据文件大小和下载的文件数目进行调度.一般情况下是一个文件一个文件按照顺序下载,如果文件比较多的情况下可以多个文件同时下载,这个是可以设置的. 2.断点续传.下载进度记录到一个配置文件中,要求