安卓 下载多线程带进度条

当我们学完java中多线程的下载后,可以将它移植到我们的安卓中来,下面是具体实现源码:

DownActivity.java

[java] view
plain
copy

  1. package com.example.downloads;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.RandomAccessFile;
  5. import java.net.HttpURLConnection;
  6. import java.net.MalformedURLException;
  7. import java.net.URL;
  8. import com.example.downloads.utils.DownLoadThread;
  9. import android.os.Bundle;
  10. import android.os.Environment;
  11. import android.os.Handler;
  12. import android.os.Message;
  13. import android.annotation.SuppressLint;
  14. import android.app.Activity;
  15. import android.text.TextUtils;
  16. import android.view.Menu;
  17. import android.view.View;
  18. import android.widget.EditText;
  19. import android.widget.ProgressBar;
  20. import android.widget.TextView;
  21. import android.widget.Toast;
  22. public class DownActivity extends Activity {
  23. // 声明控件
  24. // 路径与线程数量
  25. public EditText et_url, et_num;
  26. // 进度条
  27. public static ProgressBar pb_thread;
  28. // 显示进度的操作
  29. public TextView tv_pb;
  30. // 线程的数量
  31. public static int threadNum = 3;
  32. // 每个线程负责下载的大小
  33. public int blockSize;
  34. public static int threadCount;// 数量
  35. // 访问的path
  36. public String path;
  37. public static boolean flag = true;
  38. // 记录进度条的值
  39. public static int pb_count = 0;
  40. public static Handler handler;
  41. public static final int TEXTVALUE = 1;
  42. public static int pb_num = 0;
  43. public static int size = 0;
  44. @Override
  45. protected void onCreate(Bundle savedInstanceState) {
  46. super.onCreate(savedInstanceState);
  47. setContentView(R.layout.activity_down);
  48. et_url = (EditText) findViewById(R.id.et_path);
  49. et_num = (EditText) findViewById(R.id.et_threadNum);
  50. pb_thread = (ProgressBar) findViewById(R.id.pb_down);
  51. tv_pb = (TextView) findViewById(R.id.tv_pb);
  52. handler = new Handler() {
  53. @SuppressLint("HandlerLeak")
  54. @Override
  55. public void handleMessage(Message msg) {
  56. super.handleMessage(msg);
  57. switch (msg.what) {
  58. case TEXTVALUE:
  59. System.out.println("-------" + DownActivity.pb_count
  60. + "//////" + DownActivity.size);
  61. // 改变TEXTView
  62. pb_num = (DownActivity.pb_count * 100) / DownActivity.size;
  63. tv_pb.setText("当前进度是+" + pb_num + "%");
  64. break;
  65. default:
  66. break;
  67. }
  68. }
  69. };
  70. }
  71. @Override
  72. public boolean onCreateOptionsMenu(Menu menu) {
  73. // Inflate the menu; this adds items to the action bar if it is present.
  74. getMenuInflater().inflate(R.menu.main, menu);
  75. return true;
  76. }
  77. public void downLoad(View v) {
  78. DownActivity.flag = true;
  79. DownActivity.pb_count = 0;
  80. path = et_url.getText().toString();
  81. String threadNum_et = et_num.getText().toString();
  82. if (TextUtils.isEmpty(path) || TextUtils.isEmpty(threadNum_et)) {
  83. Toast.makeText(this, "不能为空", Toast.LENGTH_LONG).show();
  84. return;
  85. }
  86. Toast.makeText(this, "url:" + path + "--" + threadNum_et,
  87. Toast.LENGTH_LONG).show();
  88. // 转换成数字
  89. threadNum = Integer.valueOf(threadNum_et);
  90. new Thread(new Runnable() {
  91. @Override
  92. public void run() {
  93. try {
  94. // 创建出URL对象
  95. URL url = new URL(path);
  96. // 创建出 HttpURLConnection对象
  97. HttpURLConnection httpURLConnection = (HttpURLConnection) url
  98. .openConnection();
  99. // 设置 发请求发送的方式
  100. httpURLConnection.setRequestMethod("GET");
  101. // 设置请求是否超时时间
  102. httpURLConnection.setConnectTimeout(5000);
  103. // 设置
  104. httpURLConnection
  105. .setRequestProperty("User-Agent",
  106. " Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");
  107. // 是否响应成功
  108. if (httpURLConnection.getResponseCode() == 200) {
  109. // 获取文件的大小
  110. size = httpURLConnection.getContentLength();
  111. System.out.println("文件的大小" + size);
  112. // 设置进度条的最大值
  113. pb_thread.setMax(size);
  114. // 创建文件 //保存到SD卡上
  115. // 首先判断是否拥有sdcard
  116. if (Environment.getExternalStorageState().equals(
  117. Environment.MEDIA_MOUNTED)) {
  118. // 获取sdCard文件目录对象
  119. File sdFile = Environment
  120. .getExternalStorageDirectory();
  121. // 创建文件对象
  122. File file = new File(sdFile, "youdao.exe");
  123. RandomAccessFile accessFile = new RandomAccessFile(
  124. file, "rwd");
  125. // 设置文件的大小
  126. accessFile.setLength(size);
  127. // 每个线程下载的大小
  128. blockSize = size / threadNum;
  129. // 开三个线程 操作此文件
  130. for (int i = 1; i <= threadNum; i++) {
  131. // 1 2 3
  132. // 计算出每个线程开始的位置
  133. int startSize = (i - 1) * blockSize;
  134. // 结束位置
  135. int endSize = (i) * blockSize;
  136. // 当线程是最后一个线程的时候
  137. if (i == threadNum) {
  138. // 判断文件的大小是否大于计算出来的结束位置
  139. if (size > endSize) {
  140. // 结束位置 等于 文件的大小
  141. endSize = size;
  142. }
  143. }
  144. // 为每个线程创建一个随机的读取
  145. RandomAccessFile threadAccessFile = new RandomAccessFile(
  146. file, "rwd");
  147. new Thread(new DownLoadThread(i,
  148. threadAccessFile, startSize, endSize,
  149. path)).start();
  150. }
  151. }
  152. }
  153. } catch (MalformedURLException e) {
  154. e.printStackTrace();
  155. } catch (IOException e) {
  156. e.printStackTrace();
  157. }
  158. }
  159. }).start();
  160. }
  161. /**
  162. * 暂停操作
  163. *
  164. * @param v
  165. */
  166. public void downPause(View v) {
  167. Toast.makeText(this, "暂停", Toast.LENGTH_LONG).show();
  168. this.flag = false;
  169. }
  170. }

DownLoadThread.java

[java] view
plain
copy

  1. package com.example.downloads.utils;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.io.RandomAccessFile;
  8. import java.net.HttpURLConnection;
  9. import java.net.MalformedURLException;
  10. import java.net.URL;
  11. import com.example.downloads.DownActivity;
  12. import android.os.Environment;
  13. public class DownLoadThread implements Runnable {
  14. public RandomAccessFile accessFile; // 每个线程 都拥有一个accessFile的文件对象 线程1 线程2 线程3
  15. // 线程下载文件的起始位置
  16. public int startSize;
  17. public int endSize;
  18. // 文件下载的path路径
  19. public String path;
  20. public int threadId; // 线程的标识
  21. public DownLoadThread(int threadId, RandomAccessFile accessFile,
  22. int startSize, int endSize, String path) {
  23. this.threadId = threadId;
  24. this.accessFile = accessFile;
  25. this.startSize = startSize;
  26. this.endSize = endSize;
  27. this.path = path;
  28. }
  29. @Override
  30. public void run() {
  31. // 执行run方法
  32. try {
  33. // 创建文件到SD卡上去
  34. // 首先判断是否拥有sdcard
  35. if (Environment.getExternalStorageState().equals(
  36. Environment.MEDIA_MOUNTED)) {
  37. // 获取sdCard文件目录对象
  38. File sdFile = Environment.getExternalStorageDirectory();
  39. File threadFile = new File(sdFile, threadId + ".txt");
  40. if (threadFile.exists()) {
  41. // 读取该文件的内容
  42. // 创建文件的输入流对象
  43. FileInputStream fis = new FileInputStream(threadFile);
  44. // 采用工具类读取
  45. byte data[] = StreamTools.isToData(fis);
  46. // 转化成字符串
  47. String threadLen = new String(data);
  48. if ((threadLen != null) && (!"".equals(threadLen))) {
  49. startSize = Integer.valueOf(threadLen);
  50. // 解决 416bug的错误
  51. if (startSize > endSize) {
  52. startSize = endSize - 1;
  53. }
  54. }
  55. }
  56. // 创建文件
  57. // 创建URL对象
  58. URL url = new URL(path);
  59. // 创建HttpURLConnection对象
  60. HttpURLConnection httpURLConnection = (HttpURLConnection) url
  61. .openConnection();
  62. // 设置请求的头
  63. httpURLConnection.setRequestMethod("GET");
  64. // 设置请求是否超时时间
  65. httpURLConnection.setConnectTimeout(5000);
  66. // 设置
  67. httpURLConnection
  68. .setRequestProperty("User-Agent",
  69. " Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");
  70. // 关键的设置
  71. httpURLConnection.setRequestProperty("Range", "bytes="
  72. + startSize + "-" + endSize);
  73. // 输出当前线程
  74. System.out.println("当前线程" + threadId + " 下载开始位置:" + startSize
  75. + " 下载结束位置:" + endSize);
  76. // 响应成功
  77. // 设置随机读取文件的 开始位置
  78. accessFile.seek(startSize);
  79. // 获取相应流对象
  80. InputStream is = httpURLConnection.getInputStream();
  81. // 创建输出流对象
  82. byte buffer[] = new byte[1024];
  83. int len = 0;
  84. int threadTotal = 0;// 每个线程下载后保存记录 /
  85. while ((len = is.read(buffer)) != -1) {
  86. accessFile.write(buffer, 0, len);
  87. threadTotal += len;// 记录你写入的长度 //xml文件
  88. //改变进度条:
  89. setProgressBar(len);
  90. // 通过文件记录文件下载的长度
  91. FileOutputStream fos = new FileOutputStream(threadFile);
  92. fos.write((threadTotal + "").getBytes());
  93. fos.flush();
  94. fos.close();
  95. //发送handler消息
  96. DownActivity.handler.sendEmptyMessage(DownActivity.TEXTVALUE);
  97. if(!DownActivity.flag){
  98. return;
  99. }
  100. }
  101. accessFile.close();
  102. is.close();
  103. System.out.println(threadId + "线程执行完毕");
  104. // 线程操作
  105. synchronized (DownActivity.class) {
  106. DownActivity.threadCount++;
  107. if (DownActivity.threadCount >= DownActivity.threadNum) {
  108. for (int i = 1; i <= DownActivity.threadNum; i++) {
  109. // 获取sdCard上的文件
  110. File deleteFile = new File(sdFile, i + ".txt");
  111. if (deleteFile.exists()) {
  112. // 文件删除
  113. deleteFile.delete();
  114. }
  115. }
  116. }
  117. }
  118. }
  119. } catch (MalformedURLException e) {
  120. // TODO Auto-generated catch block
  121. e.printStackTrace();
  122. } catch (IOException e) {
  123. // TODO Auto-generated catch block
  124. e.printStackTrace();
  125. }
  126. }
  127. public synchronized void setProgressBar(int len){
  128. DownActivity.pb_count+=len;
  129. DownActivity.pb_thread.setProgress(DownActivity.pb_count);
  130. }
  131. }

StreamTools.java

[java] view
plain
copy

  1. package com.example.downloads.utils;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. public class StreamTools {
  6. public static byte[] isToData(InputStream is) throws IOException{
  7. // 字节输出流
  8. ByteArrayOutputStream bops = new ByteArrayOutputStream();
  9. // 读取数据的缓存区
  10. byte buffer[] = new byte[1024];
  11. // 读取长度的记录
  12. int len = 0;
  13. // 循环读取
  14. while ((len = is.read(buffer)) != -1) {
  15. bops.write(buffer, 0, len);
  16. }
  17. // 把读取的内容转换成byte数组
  18. byte data[] = bops.toByteArray();
  19. bops.flush();
  20. bops.close();
  21. is.close();
  22. return data;
  23. }
  24. }

strings.xml

[html] view
plain
copy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <string name="app_name">downloads</string>
  4. <string name="action_settings">Settings</string>
  5. <string name="tv_down">文件下载的地址</string>
  6. <string name="tv_threadNum">线程数量</string>
  7. <string name="tv_num">0%</string>
  8. <string name="btn_text">下载</string>
  9. <string name="btn_pause">暂停</string>
  10. <string name="et_path">http://172.22.64.8:8080/doudou/youdao.exe</string>
  11. <string name="et_threadNum">3</string>
  12. </resources>

布局文件:

[html] view
plain
copy

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:paddingBottom="@dimen/activity_vertical_margin"
  6. android:paddingLeft="@dimen/activity_horizontal_margin"
  7. android:paddingRight="@dimen/activity_horizontal_margin"
  8. android:paddingTop="@dimen/activity_vertical_margin"
  9. tools:context=".DownActivity" >
  10. <TextView
  11. android:id="@+id/textView1"
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:layout_alignParentLeft="true"
  15. android:layout_alignParentTop="true"
  16. android:text="@string/tv_down" />
  17. <EditText
  18. android:id="@+id/et_path"
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"
  21. android:layout_alignParentLeft="true"
  22. android:layout_alignParentRight="true"
  23. android:layout_below="@+id/textView1"
  24. android:ems="10"
  25. android:inputType="none"
  26. android:text="@string/et_path" >
  27. <requestFocus />
  28. </EditText>
  29. <TextView
  30. android:id="@+id/textView2"
  31. android:layout_width="wrap_content"
  32. android:layout_height="wrap_content"
  33. android:layout_alignParentLeft="true"
  34. android:layout_below="@+id/et_path"
  35. android:text="@string/tv_threadNum" />
  36. <EditText
  37. android:id="@+id/et_threadNum"
  38. android:layout_width="wrap_content"
  39. android:layout_height="wrap_content"
  40. android:layout_alignLeft="@+id/textView2"
  41. android:layout_alignRight="@+id/et_path"
  42. android:layout_below="@+id/textView2"
  43. android:ems="10"
  44. android:inputType="number"
  45. android:text="@string/et_threadNum" />
  46. <ProgressBar
  47. android:id="@+id/pb_down"
  48. style="?android:attr/progressBarStyleHorizontal"
  49. android:layout_width="wrap_content"
  50. android:layout_height="wrap_content"
  51. android:layout_alignLeft="@+id/et_threadNum"
  52. android:layout_alignRight="@+id/et_threadNum"
  53. android:layout_below="@+id/et_threadNum"
  54. android:layout_marginTop="14dp" />
  55. <TextView
  56. android:id="@+id/tv_pb"
  57. android:layout_width="wrap_content"
  58. android:layout_height="wrap_content"
  59. android:layout_alignRight="@+id/textView1"
  60. android:layout_below="@+id/pb_down"
  61. android:layout_marginTop="24dp"
  62. android:text="@string/tv_num" />
  63. <Button
  64. android:id="@+id/btn_down"
  65. android:layout_width="wrap_content"
  66. android:layout_height="wrap_content"
  67. android:layout_alignLeft="@+id/pb_down"
  68. android:layout_below="@+id/tv_pb"
  69. android:layout_marginTop="32dp"
  70. android:onClick="downLoad"
  71. android:text="@string/btn_text" />
  72. <Button
  73. android:id="@+id/button1"
  74. android:layout_width="wrap_content"
  75. android:layout_height="wrap_content"
  76. android:layout_alignLeft="@+id/btn_down"
  77. android:layout_below="@+id/btn_down"
  78. android:layout_marginTop="16dp"
  79. android:onClick="downPause"
  80. android:text="@string/btn_pause" />
  81. </RelativeLayout>

效果如下:

最后要注意的是别忘了在项目清单文件中加入权限:

[html] view
plain
copy

  1. <!-- SDCard权限 -->
  2. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
  3. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  4. <!-- 访问网络的权限 -->
  5. <uses-permission android:name="android.permission.INTERNET" />
  1. http://blog.csdn.net/sgx425021234/article/details/9191963
时间: 2024-08-11 21:38:14

安卓 下载多线程带进度条的相关文章

Python实现下载界面(带进度条,断点续传,多线程多任务下载等)

开发环境: Windows 7 64位,Python 3.6.2 实现功能: 进度条,下载速度和下载进度的显示,断点续传(暂停继续下载功能),取消下载等功能下载界面,如图所示点击'新建任务',弹出输入下载链接的窗口,如图所示点击'开始下载',可以自动获取下载文件名和选择存储路径,如图所示: 关键代码: 因为断点续传是在之前的文件继续追加,所以open(filename,'ab')这里打开文件的模式要为ab实现断点续传的代码如下: headers={'Range': 'bytes=%d-' %os

webclient下载文件 带进度条

private void button1_Click(object sender, EventArgs e) { doDownload(textBox1.Text.Trim()); } private DateTime StartTime; private void doDownload(string url,string fileName="") { label1.Text = "正在下载:" + url;//label框提示下载文件 if (fileName.L

C# .net实现下载,带进度条

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms; namespace WinShowDown{    public partial class FrmMain : Form    {       

UrlDownloadFile, 线程下载文件, 带进度条

unit FileDownLoadThread; interface uses Classes, SysUtils, Windows, ActiveX, UrlMon; const S_ABORT = HRESULT($80004004); type TFileDownLoadThread = class; TDownLoadProcessEvent = procedure(Sender: TFileDownLoadThread; Progress, ProgressMax: Cardinal)

赵雅智_android多线程下载带进度条

progressBar说明 在某些操作的进度中的可视指示器,为用户呈现操作的进度,还它有一个次要的进度条,用来显示中间进度,如在流媒体播放的缓冲区的进度.一个进度条也可不确定其进度.在不确定模式下,进度条显示循环动画.这种模式常用于应用程序使用任务的长度是未知的. XML重要属性 android:progressBarStyle:默认进度条样式 android:progressBarStyleHorizontal:水平样式 progressBar重要方法 getMax():返回这个进度条的范围的

android:异步任务asyncTask介绍及异步任务下载图片(带进度条)

为什么要用异步任务? 在android中只有在主线程才能对ui进行更新操作,而其它线程不能直接对ui进行操作 android本身是一个多线程的操作系统,我们不能把所有的操作都放在主线程中操作 ,比如一些耗时操作.如果放在主线程中 会造成阻塞 而当阻塞事件过长时 系统会抛出anr异常.所以我们要使用异步任务.android为我们提供了一个封装好的组件asynctask. AsyncTask可以在子线程中更新ui,封装简化了异步操作.适用于简单的异步处理.如果多个后台任务时就要使用Handler了

Delphi下载指定网址(URL)的文件,带进度条显示

Delphi下载指定网址(URL)的文件,带进度条显示 发布于: 2012-12-26 11:21:04   |  发布在: Delphi文章   |  点击:626 主要使用的是Delphi自带的TIdhttp控件.一.界面设置在窗体上放置两个TEdit控件,一个用于输入要下载的文件URL,一个用于输入要保存到本地的文件路径:放置两个TLabel控件,一个显示文件总大小,一个显示当前已下载大小:放置一个按钮TButton,一个TIdhttp控件(在Indy Clients面板)和一个TIdAn

C# 下载带进度条代码(普通进度条)

<span style="font-size:14px;"> </span><pre name="code" class="csharp"><span style="font-size:14px;"> /// <summary> /// 下载带进度条代码(普通进度条) /// </summary> /// <param name="URL&

带进度条的文件上传

Ajax技术——带进度条的文件上传 1.概述 在实际的Web应该开发或网站开发过程中,经常需要实现文件上传的功能.在文件上传过程中,经常需要用户进行长时间的等待,为了让用户及时了解上传进度,可以在上传文件的同时,显示文件的上传进度条.运行本实例,如图1所示,访问文件上传页面,单击“浏览”按钮选择要上传的文件,注意文件不能超过50MB,否则系统将给出错误提示.选择完要上传的文件后,单击“提交”按钮,将会上传文件并显示上传进度. 2.技术要点 主要是应用开源的Common-FileUpload组件来