多线程下载

1.新建:MultiDownloader\app\src\main\res\xml\network_security_config.xml

配置支持HTTP请求

<?xml version="1.0" encoding="utf-8"?>
<network-security-config><base-config cleartextTrafficPermitted="true" /></network-security-config>

2. AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.glsite.multidownloader"><uses-permission android:name="android.permission.INTERNET"/><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"android:networkSecurityConfig="@xml/network_security_config"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

3.新建MultiDownloader\app\src\main\res\layout\pb.xml

进度条

<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"style="@style/Widget.AppCompat.ProgressBar.Horizontal"android:layout_width="match_parent"android:layout_height="match_parent"></ProgressBar>

4.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><EditTextandroid:id="@+id/et_threadcount"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="8dp"android:layout_marginLeft="8dp"android:layout_marginTop="36dp"android:layout_marginEnd="8dp"android:layout_marginRight="8dp"android:ems="10"android:hint="请输入下载线程的数量"android:inputType="textPersonName"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><EditTextandroid:id="@+id/et_path"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="8dp"android:layout_marginLeft="8dp"android:layout_marginTop="16dp"android:layout_marginEnd="8dp"android:layout_marginRight="8dp"android:ems="10"android:inputType="textPersonName"android:text="http://192.168.1.130:8080/Day10/QQ.exe"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/et_threadcount" /><Buttonandroid:id="@+id/bt_self"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="16dp"android:layout_marginLeft="16dp"android:layout_marginTop="16dp"android:text="自己的下载方式"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/et_path" /><Buttonandroid:id="@+id/bt_other"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="16dp"android:layout_marginEnd="16dp"android:layout_marginRight="16dp"android:text="第三方的下载方式"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintTop_toBottomOf="@+id/et_path" /><LinearLayoutandroid:id="@+id/ll_container"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginStart="8dp"android:layout_marginLeft="8dp"android:layout_marginTop="100dp"android:layout_marginEnd="8dp"android:layout_marginRight="8dp"android:orientation="vertical"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.503"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/et_path"></LinearLayout>
</android.support.constraint.ConstraintLayout>

5.MultiDownloader\lib\src\main\java\com\glsite\lib\MultiDownloader.java

测试:

package com.glsite.lib;import com.sun.jndi.toolkit.url.UrlUtil;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.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Path;public class MultiDownloader {/*** 总共的线程数*/public static final int TOTAL_THREAD_COUNT = 3;/*** 要下载的文件的链接*/public static String path = "http://localhost:8080/Day10/QQ.exe";/*** 运行状态的线程数*/private static int runningThreadCount = 0;public static void main(String[] args) {try {URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");int code = conn.getResponseCode();if (code == 200) {int length = conn.getContentLength();System.out.println("file length:" + length);RandomAccessFile raf = new RandomAccessFile(getDownloadFileName(path), "rw");// 创建一个空的文件并且设置它的文件长度等于服务器上的文件长度raf.setLength(length);raf.close();int blockSize = length / TOTAL_THREAD_COUNT;System.out.println("every block size:" + blockSize);runningThreadCount = TOTAL_THREAD_COUNT;for (int threadId = 0; threadId < TOTAL_THREAD_COUNT; threadId++) {int startPosition = threadId * blockSize;int endPosition = (threadId + 1) * blockSize -1;if (threadId == (TOTAL_THREAD_COUNT - 1 )) {endPosition = length - 1;}new DownloadThread(threadId, startPosition, endPosition).start();}} else {System.out.println("download error, code = " + code);}} catch (Exception e) {e.printStackTrace();}}/*** 从网络路径获取文件名** @param path*          网络路径* @return  文件名*/private static String getDownloadFileName(String path) {return path.substring(path.lastIndexOf("/") + 1);}/*** 下载文件的线程*/private static class DownloadThread extends Thread{/*** 线程id*/private int threadId;/*** 当前现成下载的起始位置*/private int startPosition;/*** 当前线程下载的终止位置*/private int endPosition;public DownloadThread(int threadId, int startPosition, int endPosition) {this.threadId = threadId;this.startPosition = startPosition;this.endPosition = endPosition;}@Overridepublic void run() {System.out.println("thread:" + threadId + "begin working");try {File finfo = new File(TOTAL_THREAD_COUNT + getDownloadFileName(path) + threadId + ".txt");if (finfo.exists() && finfo.length() > 0) {FileInputStream fis = new FileInputStream(finfo);BufferedReader br = new BufferedReader(new InputStreamReader(fis));String lastPosition = br.readLine();startPosition = Integer.parseInt(lastPosition);fis.close();}URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");System.out.println("begin and end:" + threadId + " range of download: " + startPosition + "~~" + endPosition);conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition);int code = conn.getResponseCode();if (code == 206) {InputStream is = conn.getInputStream();RandomAccessFile raf = new RandomAccessFile(getDownloadFileName(path), "rw");raf.seek(startPosition);int len = 0;byte[] buffer = new byte[1024];int total = 0; // downloaded data of current thread in this times;while ((len = is.read(buffer)) != -1) {raf.write(buffer, 0, len);total += len;RandomAccessFile inforaf = new RandomAccessFile(TOTAL_THREAD_COUNT + getDownloadFileName(path) + threadId + ".txt", "rwd");inforaf.write(String.valueOf(startPosition + total).getBytes());inforaf.close();}is.close();raf.close();System.out.println("thread:" + threadId + " download complete...");} else {System.out.println("request download failed.");}} catch (Exception e) {e.printStackTrace();} finally {synchronized (MultiDownloader.class) {runningThreadCount--;if (runningThreadCount <= 0) {System.out.println("multi thread download complete.");for (int i = 0; i < TOTAL_THREAD_COUNT; i++) {File finfo = new File(TOTAL_THREAD_COUNT + getDownloadFileName(path) + i + ".txt");
//                            System.out.println(finfo.delete());}}}}}}}

6.MainActivity.java

package com.glsite.multidownloader;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;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.net.URL;
import java.util.ArrayList;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private EditText mEtPath;private EditText mEtThreadCount;private LinearLayout mLLContainer;private Button mBtSelf;private Button mBtOther;/*** 总共的线程数*/public int totalThreadCount = 3;/*** 要下载的文件的链接*/public String path = "http://192.168.1.130:8080/Day10/QQ.exe";/*** 运行状态的线程数*/private static int runningThreadCount = 0;/*** ProgressBar的集合*/private ArrayList<ProgressBar> mPbs;/*** 当前app的缓存目录*/private String CACHE_DIR;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 1.找到控件// 2.在button点击事件当中下载文件// 3.下载的时候要在界面显示下载的进度mEtPath = findViewById(R.id.et_path);mEtThreadCount = findViewById(R.id.et_threadcount);mLLContainer = findViewById(R.id.ll_container);mBtSelf = findViewById(R.id.bt_self);mBtOther = findViewById(R.id.bt_other);mBtSelf.setOnClickListener(this);mBtOther.setOnClickListener(this);// 初始化缓存目录路径CACHE_DIR = this.getCacheDir().getAbsolutePath() + "/";}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.bt_self:downloadBySelf();break;case R.id.bt_other:break;}}/*** 通过自己自定义的多线程代码去下载网络文件*/private void downloadBySelf() {path =  mEtPath.getText().toString().trim();totalThreadCount = Integer.valueOf(mEtThreadCount.getText().toString().trim());mLLContainer.removeAllViews();mPbs = new ArrayList<>();for (int i = 0; i < totalThreadCount; i++) {// 有几个线程就添加几个progressbarProgressBar pb = (ProgressBar) View.inflate(this, R.layout.pb, null);mLLContainer.addView(pb);mPbs.add(pb);}new Thread() {@Overridepublic void run() {try {URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");int code = conn.getResponseCode();if (code == 200) {int length = conn.getContentLength();System.out.println("file length:" + length);RandomAccessFile raf = new RandomAccessFile(CACHE_DIR + getDownloadFileName(path), "rw");// 创建一个空的文件并且设置它的文件长度等于服务器上的文件长度raf.setLength(length);raf.close();int blockSize = length / totalThreadCount;System.out.println("every block size:" + blockSize);runningThreadCount = totalThreadCount;for (int threadId = 0; threadId < totalThreadCount; threadId++) {int startPosition = threadId * blockSize;int endPosition = (threadId + 1) * blockSize -1;if (threadId == (totalThreadCount - 1 )) {endPosition = length - 1;}new DownloadThread(threadId, startPosition, endPosition).start();}} else {System.out.println("download error, code = " + code);}} catch (Exception e) {e.printStackTrace();}}}.start();}/*** 从网络路径获取文件名** @param path*          网络路径* @return  文件名*/private static String getDownloadFileName(String path) {return path.substring(path.lastIndexOf("/") + 1);}/*** 下载文件的线程*/private class DownloadThread extends Thread{/*** 线程id*/private int threadId;/*** 当前现成下载的起始位置*/private int startPosition;/*** 当前线程下载的终止位置*/private int endPosition;/*** 当前线程需要去下载的总共的字节*/private int threadTotal;/*** 该线程上一次下载了的字节数*/private int lastDownloadTotalSize;public DownloadThread(int threadId, int startPosition, int endPosition) {this.threadId = threadId;this.startPosition = startPosition;this.endPosition = endPosition;this.threadTotal = endPosition - startPosition;mPbs.get(threadId).setMax(threadTotal);}@Overridepublic void run() {System.out.println("thread:" + threadId + "begin working");try {File finfo = new File(CACHE_DIR + totalThreadCount + getDownloadFileName(path) + threadId + ".txt");if (finfo.exists() && finfo.length() > 0) {FileInputStream fis = new FileInputStream(finfo);BufferedReader br = new BufferedReader(new InputStreamReader(fis));String lastPosition = br.readLine();// 这里计算出来的就是表示的上次该线程下载了多少个字节总数lastDownloadTotalSize = Integer.parseInt(lastPosition) - startPosition;startPosition = Integer.parseInt(lastPosition);fis.close();}URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");System.out.println("begin and end:" + threadId + " range of download: " + startPosition + "~~" + endPosition);conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition);int code = conn.getResponseCode();if (code == 206) {InputStream is = conn.getInputStream();RandomAccessFile raf = new RandomAccessFile(CACHE_DIR + getDownloadFileName(path), "rw");raf.seek(startPosition);int len = 0;byte[] buffer = new byte[1024];int total = 0; // downloaded data of current thread in this times;while ((len = is.read(buffer)) != -1) {raf.write(buffer, 0, len);total += len;RandomAccessFile inforaf = new RandomAccessFile(CACHE_DIR + totalThreadCount + getDownloadFileName(path) + threadId + ".txt", "rwd");inforaf.write(String.valueOf(startPosition + total).getBytes());inforaf.close();mPbs.get(threadId).setProgress(total + lastDownloadTotalSize);}is.close();raf.close();System.out.println("thread:" + threadId + " download complete...");} else {System.out.println("request download failed.");}} catch (Exception e) {e.printStackTrace();} finally {synchronized (MainActivity.class) {runningThreadCount--;if (runningThreadCount <= 0) {System.out.println("multi thread download complete.");for (int i = 0; i < totalThreadCount; i++) {File finfo = new File(CACHE_DIR + totalThreadCount + getDownloadFileName(path) + i + ".txt");// System.out.println(finfo.delete());}}}}}}
}

多线程下载Android相关推荐

  1. Android -- 多线程下载

    因为Android应用程序是java写的,基本上很多java写的程序都可以直接照搬到Android上面,移植性非常Good.这里讲一下多线程下载,就是每个线程都下载自己的那部分,那么就需要平均分配分割 ...

  2. android 多线程下载,断点续传,线程池

    android 多线程下载,断点续传,线程池 你可以在这里看到这个demo的源码: https://github.com/onlynight/MultiThreadDownloader 效果图 这张效 ...

  3. Android 模拟多线程下载

    以下是一个多线程下载的例子,见代码: 1.首先是布局文件 1 <?xml version="1.0" encoding="utf-8"?> 2 &l ...

  4. android多线程下载原理,安卓多线程断点续传下载功能(靠谱第三方组件,原理demo)...

    一,原生的DownloadManager 从Android 2.3(API level 9)开始,Android以Service的方式提供了全局的DownloadManager来系统级地优化处理长时间 ...

  5. Android模拟多线程下载

    本DEMO采用Executor框架来实现多线程的下载. Executor原理:任务拆分为一些列的小任务,即Runnable,然后在提交给一个Executor执行,Executor.execute(Ru ...

  6. 【Android】多线程下载加断点续传

    http://blog.csdn.net/smbroe/article/details/42270573 文件下载在App应用中也用到很多,一般版本更新时多要用的文件下载来进行处理,以前也有看过很多大 ...

  7. Android 开发工具类 27_多线程下载大文件

    多线程下载大文件时序图 FileDownloader.java 1 package com.wangjialin.internet.service.downloader; 2 3 import jav ...

  8. Android中多线程下载方面的知识点

    1.多线程下载 //取得下载文件大小,并构建随机访问文件 HttpURLConnectionn.getConnectionLength(); RandomAccessFile file = new R ...

  9. *Android 多线程下载 仿下载助手(改进版)

    首先声明一点: 这里的多线程下载 并不是指的 多个线程下载一个 文件,而是 每个线程 负责一个文件.真正的多线程 希望后面能给大家带来.  -------------  欢迎 爱学习的小伙伴 加群   ...

最新文章

  1. 多媒体课程设计android,基于Android的多媒体播放器(课程设计)报告.doc
  2. mySql 的常用命令
  3. 算法-----------猜数字大小
  4. 1073 多选题常见计分法 (20 分)
  5. Docker 网络命名空间
  6. 《从零开始学Swift》学习笔记(Day 40)——析构函数
  7. 【英语学习】【Daily English】U02 Daily Routine L02 I go to the gym every other day
  8. SQL SERVER 2012/2014 链接到 SQL SERVER 2000的各种坑
  9. c++语言怎么实现字符串拼接,C++ string类和字符串的访问和拼接操作
  10. 459.重复的子字符串
  11. iis php环境安装包下载,php5 环境集成安装包 for IIS6
  12. 2022年计算机视觉3大趋势
  13. 记实现多racecar仿真过程中遇到的问题(一)
  14. 【无限互联】SDWebImage图片缓存流程分析
  15. VMware导入vmdk格式的文件 踩了一堆坑~~~
  16. 如何将Word文档导入Google文档
  17. Keil5 点击Debug Setting 软件崩溃解决方法
  18. MySQL 查询学生的总成绩并进行排名_MySQL查询各科成绩前三名的记录及排名(不考虑成绩并列情况)...
  19. 2015物联网安全年报
  20. 别让用户发呆—设计中的防呆的6个策略

热门文章

  1. 错误3:系统找不到指定的路径
  2. java string equal 与==的区别
  3. 一生要做的九十九件事
  4. 网络拓扑发现原理研究
  5. 手写token解析器、语法解析器、LLVM IR生成器(GO语言)
  6. Yii2学习笔记002---Yii2的控制器和视图
  7. 用java网络编程中的TCP方式上传文本文件及出现的小问题
  8. HTML5:一个拖拽网页元素的例子
  9. Android 笔记
  10. Windows下Apache Tomcat 8安装配置