首先给大家分享多线程下载核心类:

  1. package com.example.urltest;
  2.  
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.RandomAccessFile;
  6. import java.net.HttpURLConnection;
  7. import java.net.MalformedURLException;
  8. import java.net.URL;
  9. import java.net.URLDecoder;
  10.  
  11. public class DownUtil {
  12. private String urlPath;
  13. private String defaultTargetPath;
  14. private int threadNum;
  15. private DownThread[] threads;
  16. private int fileSize = -100;
  17. private String fileName = "未知文件";
  18. private boolean isGetFileInformation = false;
  19.  
  20. public DownUtil(String urlPath, int threadNum) {
  21. this.urlPath = urlPath;
  22. this.defaultTargetPath = "/mnt/sdcard/";
  23. this.threadNum = threadNum;
  24. this.threads = new DownThread[threadNum];
  25. }
  26.  
  27. private HttpURLConnection connection() throws IOException {
  28.  
  29. URL url = new URL(urlPath);
  30. HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  31. connection.setConnectTimeout(5 * 1000);
  32. connection.setRequestMethod("GET");
  33. connection.setRequestProperty(
  34. "Accept",
  35. "image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
  36. + "application/x-shockwave-flash, application/xaml+xml, "
  37. + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
  38. + "application/x-ms-application, application/vnd.ms-excel, "
  39. + "application/vnd.ms-powerpoint, application/msword, */*");
  40. connection.setRequestProperty("Accept-Language", "zh-CN");
  41. connection.setRequestProperty("Charset", "UTF-8");
  42. connection.setRequestProperty("Connection", "Keep-Alive");
  43.  
  44. return connection;
  45. }
  46.  
  47. public void getFileInformation() throws IOException {
  48.  
  49. HttpURLConnection connection = connection();
  50.  
  51. connection.setInstanceFollowRedirects(false);
  52.  
  53. int status = connection.getResponseCode();
  54. if (status != -1) {
  55.  
  56. if (status / 100 == 3) {// 当响应码是302时,说明可以获得重定向的资源地址
  57. // 得到文件名(此方法不能正确的获取所有url的资源文件名)
  58. String name = connection.getHeaderField("Location");
  59. name = URLDecoder.decode(name.substring(name.lastIndexOf('/')), "UTF-8");
  60. this.fileName = name;
  61. }
  62.  
  63. // 得到文件大小
  64. this.fileSize = connection.getContentLength();
  65. if (fileSize <= 0) {
  66. isGetFileInformation = false;
  67. } else {
  68. isGetFileInformation = true;
  69. }
  70. connection.disconnect();
  71.  
  72. } else {
  73.  
  74. connection.disconnect();
  75. isGetFileInformation = false;
  76.  
  77. }
  78.  
  79. }
  80.  
  81. public boolean download(String targetPath, String fileName) throws IOException {
  82.  
  83. if (isGetFileInformation == false) {
  84. getFileInformation();
  85. }
  86.  
  87. if (isGetFileInformation) {
  88.  
  89. String absFilePath = targetPath + fileName;
  90.  
  91. int currentPartSize = (fileSize / threadNum) + 1;// 每一部分需要下载的大小,注意此处加1是为了避免不能整除带来的误差
  92. RandomAccessFile file = new RandomAccessFile(absFilePath, "rw");
  93. file.setLength(fileSize);
  94. file.close();
  95. for (int i = 0; i < threadNum; i++) {
  96. int startPos = i * currentPartSize;
  97. RandomAccessFile currentPart = new RandomAccessFile(absFilePath, "rw");// 打开目标文件
  98. currentPart.seek(startPos);
  99. threads[i] = new DownThread(startPos, currentPartSize, currentPart);
  100. threads[i].start();
  101.  
  102. }
  103.  
  104. return true;
  105. } else {
  106. return false;
  107.  
  108. }
  109. }
  110.  
  111. public boolean download() throws IOException {
  112. if (isGetFileInformation) {
  113.  
  114. return download(this.defaultTargetPath, this.getFileName());
  115.  
  116. } else {
  117. getFileInformation();
  118. return download(this.defaultTargetPath, this.getFileName());
  119.  
  120. }
  121.  
  122. }
  123.  
  124. public double getCompleteRate() {
  125.  
  126. int sumSize = 0;
  127. for (int i = 0; i < threadNum; i++) {
  128.  
  129. sumSize += threads[i].length;
  130. }
  131.  
  132. return sumSize * 1.0 / fileSize;
  133.  
  134. }
  135.  
  136. public String getDefaultTargetPath() {
  137. return defaultTargetPath;
  138. }
  139.  
  140. public int getFileSize() {
  141. return fileSize;
  142. }
  143.  
  144. public String getFileName() {
  145. return fileName;
  146. }
  147.  
  148. public void setFileName(String fileName) {
  149. this.fileName = fileName;
  150. }
  151.  
  152. public boolean isGetFileInformation() {
  153. return isGetFileInformation;
  154. }
  155.  
  156. private class DownThread extends Thread {
  157. private int startPos;
  158. private int currentPartSize;
  159. private RandomAccessFile currentPart;
  160. int length; // 该线程已经下载的字节数
  161.  
  162. public DownThread(int startPos, int currentPartSize, RandomAccessFile currentPart) {
  163.  
  164. this.startPos = startPos;
  165. this.currentPartSize = currentPartSize;
  166. this.currentPart = currentPart;
  167. }
  168.  
  169. @Override
  170. public void run() {
  171.  
  172. try {
  173.  
  174. HttpURLConnection connection = connection();
  175. int endPos = startPos + currentPartSize;
  176. connection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);// 使用http来设置一个文件的下载范围(startPos-endPos)
  177. InputStream inStream = connection.getInputStream();
  178. // inStream.skip(startPos); // skip函数有时候不起作用
  179. byte[] buffer = new byte[1024];
  180. int hasRead = 0;
  181. while (length < currentPartSize && (hasRead = inStream.read(buffer)) > 0) {
  182.  
  183. currentPart.write(buffer, 0, hasRead);
  184. length = length + hasRead;
  185.  
  186. }
  187.  
  188. inStream.close();
  189. currentPart.close();
  190. connection.disconnect();
  191.  
  192. } catch (MalformedURLException e2) {
  193. e2.printStackTrace();
  194. } catch (IOException e) {
  195. e.printStackTrace();
  196. }
  197.  
  198. }
  199.  
  200. }
  201.  
  202. }

下面是界面的逻辑代码:

  1. package com.example.urltest;
  2.  
  3. import android.app.Activity;
  4. import android.app.AlertDialog;
  5. import android.app.ProgressDialog;
  6. import android.content.DialogInterface;
  7. import android.os.Bundle;
  8. import android.os.Message;
  9. import android.view.View;
  10. import android.view.View.OnClickListener;
  11. import android.widget.Button;
  12. import android.widget.EditText;
  13. import android.widget.ProgressBar;
  14. import android.widget.TextView;
  15. import android.widget.Toast;
  16.  
  17. import java.io.IOException;
  18. import java.util.Timer;
  19. import java.util.TimerTask;
  20.  
  21. public class MultiThreadDown extends Activity {
  22. EditText url, target;
  23. Button downButton;
  24. ProgressBar bar;
  25. ProgressDialog progressDialog;
  26. View downView;
  27. DownUtil downUtil;
  28. private int mDownStatus;
  29. private int threadNum = 6; // 默认的线程数
  30. android.os.Handler handler = new android.os.Handler() {
  31.  
  32. @Override
  33. public void handleMessage(Message msg) {
  34. if (msg.what == 0x123) {
  35. bar.setProgress(mDownStatus);
  36. if (mDownStatus >= 100) {
  37. Toast.makeText(MultiThreadDown.this, "下载完成", Toast.LENGTH_SHORT).show();
  38. }
  39. // Log.i("csx", "" + mDownStatus);
  40.  
  41. }
  42. }
  43.  
  44. };
  45.  
  46. @Override
  47. protected void onCreate(Bundle savedInstanceState) {
  48.  
  49. super.onCreate(savedInstanceState);
  50. setContentView(R.layout.layout_down);
  51. url = (EditText) findViewById(R.id.url);
  52.  
  53. downButton = (Button) findViewById(R.id.down);
  54. bar = (ProgressBar) findViewById(R.id.bar);
  55. progressDialog = new ProgressDialog(this);
  56. progressDialog.setTitle("尝试连接");
  57. progressDialog.setMessage("正在连接...");
  58. downButton.setOnClickListener(new DownButtonOnClickListener());
  59.  
  60. }
  61.  
  62. private class DownButtonOnClickListener implements OnClickListener {
  63.  
  64. EditText targetFilePath, fileName;
  65. TextView fileSize;
  66. Thread connectionThread;
  67.  
  68. public Thread instanceOfConnectionThread() {
  69. return new Thread() {
  70.  
  71. @Override
  72. public void run() {
  73. try {
  74. downUtil.getFileInformation();
  75.  
  76. } catch (IOException e1) {
  77. e1.printStackTrace();
  78. }
  79.  
  80. }
  81.  
  82. };
  83. }
  84.  
  85. @Override
  86. public void onClick(View v) {
  87.  
  88. String urlPath = url.getText().toString();
  89. if (urlPath == null || urlPath.equals("")) {
  90. return;
  91. }
  92. progressDialog.show();
  93. downUtil = new DownUtil(urlPath, threadNum);
  94. connectionThread = instanceOfConnectionThread();
  95. connectionThread.start();
  96.  
  97. int connectionNum = 3;
  98. while (!downUtil.isGetFileInformation() && connectionNum > 0) {// 循环请求连接,如果3次之后还没有连接成功,就退出
  99. if (!connectionThread.isAlive()) {
  100. connectionThread = null;
  101. connectionThread = instanceOfConnectionThread();
  102. connectionThread.start();
  103. connectionNum--;
  104. }
  105.  
  106. }
  107.  
  108. progressDialog.cancel();
  109. if (!downUtil.isGetFileInformation()) {
  110. Toast.makeText(MultiThreadDown.this, "请求失败!", Toast.LENGTH_SHORT).show();
  111. return;
  112. }
  113. downView = getLayoutInflater().inflate(R.layout.layout_download_view, null);
  114. targetFilePath = (EditText) downView.findViewById(R.id.editText_target_path);
  115. fileName = (EditText) downView.findViewById(R.id.editText_file_name);
  116. fileSize = (TextView) downView.findViewById(R.id.textView_file_size);
  117. targetFilePath.setText(downUtil.getDefaultTargetPath());
  118. fileName.setText(downUtil.getFileName());
  119. fileSize.append("" + ((double) downUtil.getFileSize()) / 1024 + "k");
  120.  
  121. new AlertDialog.Builder(MultiThreadDown.this).setView(downView)
  122. .setPositiveButton("确定", new DialogInterface.OnClickListener() {
  123.  
  124. @Override
  125. public void onClick(DialogInterface dialog, int which) {
  126. if (!downUtil.isGetFileInformation()) {
  127. dialog.dismiss();
  128. return;
  129. }
  130. final String path = targetFilePath.getText().toString();
  131. final String name = fileName.getText().toString();
  132.  
  133. new Thread() {
  134.  
  135. @Override
  136. public void run() {
  137. try {
  138. downUtil.download(path, name);
  139. } catch (IOException e) {
  140. // TODO Auto-generated catch block
  141. e.printStackTrace();
  142. }
  143.  
  144. final Timer timer = new Timer();
  145. TimerTask task = new TimerTask() {
  146.  
  147. @Override
  148. public void run() {
  149.  
  150. mDownStatus = (int) (downUtil.getCompleteRate() * 100);
  151. handler.sendEmptyMessage(0x123);
  152. if (mDownStatus >= 100) {
  153. timer.cancel();
  154. }
  155.  
  156. }
  157. };
  158. timer.schedule(task, 0, 100);
  159.  
  160. }
  161.  
  162. }.start();
  163.  
  164. }
  165. }).setNegativeButton("取消", null)
  166. .setTitle(downUtil.isGetFileInformation() ? "链接可用" : "链接不可用").show();
  167.  
  168. }
  169. }
  170.  
  171. }

下面是主页面布局:layout_down.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical" >
  6.  
  7. <ScrollView
  8. android:id="@+id/scrollView1"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content" >
  11.  
  12. <LinearLayout
  13. android:layout_width="match_parent"
  14. android:layout_height="match_parent"
  15. android:orientation="vertical" >
  16.  
  17. <TextView
  18. android:layout_width="match_parent"
  19. android:layout_height="wrap_content"
  20. android:text="要下载的资源的URL:" />
  21.  
  22. <EditText
  23. android:id="@+id/url"
  24. android:layout_width="match_parent"
  25. android:layout_height="wrap_content"
  26. android:text="在在这里输入URL" />
  27.  
  28. <Button
  29. android:id="@+id/down"
  30. android:layout_width="match_parent"
  31. android:layout_height="wrap_content"
  32. android:text="下载" />
  33. <!-- 定义一个水平进度条,用于显示下载进度 -->
  34.  
  35. <ProgressBar
  36. android:id="@+id/bar"
  37. style="?android:attr/progressBarStyleHorizontal"
  38. android:layout_width="match_parent"
  39. android:layout_height="wrap_content"
  40. android:max="100" />
  41. </LinearLayout>
  42. </ScrollView>
  43.  
  44. </LinearLayout>

下面是下载选项dialog布局:layout_download_view.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical" >
  6.  
  7. <TextView
  8. android:id="@+id/textView1"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:text="下载路径:" />
  12.  
  13. <EditText
  14. android:id="@+id/editText_target_path"
  15. android:layout_width="match_parent"
  16. android:layout_height="wrap_content"
  17. android:ems="10" >
  18.  
  19. <requestFocus />
  20. </EditText>
  21.  
  22. <TextView
  23. android:id="@+id/textView2"
  24. android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"
  26. android:text="文件名:" />
  27.  
  28. <EditText
  29. android:id="@+id/editText_file_name"
  30. android:layout_width="match_parent"
  31. android:layout_height="wrap_content"
  32. android:maxLines="1"
  33. android:ems="10" />
  34.  
  35. <TextView
  36. android:id="@+id/textView_file_size"
  37. android:layout_width="wrap_content"
  38. android:layout_height="wrap_content"
  39. android:text="文件大小:" />
  40.  
  41. </LinearLayout>

效果图如下:输入URL,点击下载弹出对话框,输入路径和文件名 点击确定开始下载

Android版多线程下载器核心代码分享的更多相关文章

  1. 教你如何在 Android 使用多线程下载文件

    # 教你如何在 Android 使用多线程下载文件 前言 在 Android 日常开发中,我们会经常遇到下载文件需求,这里我们也可以用系统自带的 api DownloadManager 来解决这个问题 ...

  2. Android中多线程下载列表的封装实现(含进度反馈)

    来源:http://blog.csdn.net/u011638883/article/details/17347015 实现了一下Android中的文件多线程下载模块,支持自定义线程数.断点续传.下载 ...

  3. <基于Qt与POSIX线程>多线程下载器的简易搭建

    原创博客,转载请联系博主! 本项目已托管到本人Git远程库:https://github.com/yue9944882/Snow 项目目标  Major Functionality 开发环境:  Ce ...

  4. python10min系列之多线程下载器

    今天群里看到有人问关于python多线程写文件的问题,联想到这是reboot的架构师班的入学题,我想了一下,感觉坑和考察的点还挺多,可以当成一个面试题来问,简单说一下我的想法和思路吧,涉及的代码和注释 ...

  5. 图解:HTTP 范围请求,助力断点续传、多线程下载的核心原理

    题图:by Charles Loyer 一.序 Hi,大家好,我是承香墨影! HTTP 协议在网络知识中占据了重要的地位,HTTP 协议最基础的就是请求和响应的报文,而报文又是由报文头(Header) ...

  6. Android之——多线程下载演示样例

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46883927 一.概述 说到Android中的文件下载.Android API中明 ...

  7. 06-python进阶-多线程下载器练手

    我们需要用python 写一个多线程的下载器 我们要先获取这个文件的大小 然后将其分片 然后启动多线程 分别去下载 然后将其拼接起来 #!/usr/bin/env python#coding:utf- ...

  8. Java多线程下载器FileDownloader(支持断点续传、代理等功能)

    前言 在我的任务清单中,很早就有了一个文件下载器,但一直忙着没空去写.最近刚好放假,便抽了些时间完成了下文中的这个下载器. 介绍 同样的,还是先上效果图吧. Jar包地址位于 FileDownload ...

  9. java编写的Http协议的多线程下载器

    断点下载器还在实现中...... //////////////////////////////////界面/////////////////////////////////////////// pac ...

随机推荐

  1. PC-如何提高计算机的启动和关机的速度?

    如何提高计算机的启动和关机的速度? 一.bios的优化设置 在bios设置的首页我们进入"advanced bios features"选项,将光标移到"frist bo ...

  2. [delphi技术]Delphi常见图象格式转换技术

    TJPEGScale = (jsFullSize, jsHalf, jsQuarter, jsEighth);//图片大小(全部,1/2,1/4,1/8)TBitmap.pixelFormat:=pf ...

  3. java实现下载文件到本地

    代码如下: URL url = new URL("http://www.cnblogs.com/images/logo_small.gif"); URLConnection con ...

  4. POJ#2065. SETI

    题目描述 For some years, quite a lot of work has been put into listening to electromagnetic radio signal ...

  5. Delphi- 调用存储过程的方法

    Delphi控件里拉一个TADOStoredProc,配置好相关链系,具体的操作列子如下: procedure TForm1.btnFirstClick(Sender: TObject); begin ...

  6. SVN版本控制安装配置说明

    版本控制好工具有SVN.CVS.VSS等多种,他们的优劣在此不说明,请网络参阅. SVN支持多种平台,此文仅描述Windows平台下使用说明. SVN客户包含客户端和服务端.Windows平台下客户端 ...

  7. [置顶] linux 解压版安装

    1:下载mysql解压版包去官网下载www.mysq.com 下载.下载linux通用版本就好了 2.基本配置 首先,我们准备好Linux环境,我们使用CentOS 5.8进行试验安装.第一步,我们需 ...

  8. ubuntu14.04源代码安装postgresql 9.1

    项目须要使用gisgraphy,怎奈gisgraphy3.0仅仅支持postgis1.5.因此仅仅能安装老版本号的posgresql和postgis了.从postgis的support matrix图 ...

  9. ubuntu 远程 ubuntu

    一:被远程端ubuntu配置 參考windows远程ubuntu这篇文章里面的ubuntu配置 二:远程端ubuntu配置 1:打开Remmina Remote Desktop Client软件,例如 ...

  10. MP3的频率、比特率、码率与音质的关系

    想知道MP3的频率.比特率.码率与音质的关系,是不是频率越高,码率越高,音质就越好.好像MP3大多数的频率都是44100HZ的.码率有128,192等等. 这里所说的频率是採样率,一般都是44100K ...