【实战】android的多线程下载
来源:互联网 发布:基金投资组合 知乎 编辑:程序博客网 时间:2024/05/22 12:01
MainActivity.java
package com.itheima.multithreaddownload;import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;import android.app.Activity;import android.os.Bundle;import android.os.Environment;import android.view.View;import android.widget.EditText;public class MainActivity extends Activity {private EditText ed_path;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ed_path = (EditText) findViewById(R.id.ed_path);}private static int threadCount = 3;private static int currentRunningThread = 3;String path;public void download(View v){path = ed_path.getText().toString().trim();new Thread(){public void run() {// 1. 服务器 发送 请求, 拿到 要下载的文件的 长度是多少try {URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setConnectTimeout(5000);conn.setRequestMethod("GET");int code = conn.getResponseCode();if (code == 200) {// 拿到文件的长度 大小int length = conn.getContentLength();// ff.exe= getFileName(path)// /mnt/sdcard/ff.exeFile file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+getFileName(path));RandomAccessFile raf = new RandomAccessFile(file, "rw");raf.setLength(length);raf.close();// 启动线程去下载文件了// 每块 线程 下载的平均的大小int blockSize = length / threadCount;// threadId :线程的id号// threadCount : 开几条线程 下载for (int threadId = 0; threadId < threadCount; threadId++) {int startIndex = threadId * blockSize;int endIndex = (threadId + 1) * blockSize - 1;if (threadId == (threadCount - 1)) {endIndex = length - 1;}new DownloadFilePartThread(threadId, startIndex, endIndex).start();}}} catch (Exception e) {e.printStackTrace();}};}.start();}private class DownloadFilePartThread extends Thread {// 线程的 id 号private int threadId;// 线程的 下载的开始 位置private int startIndex;// 线程的 下载的结束 位置private int endIndex;// 当前线程 下载到的位置private int currentPostion;public DownloadFilePartThread(int threadId, int startIndex, int endIndex) {this.threadId = threadId;this.startIndex = startIndex;this.endIndex = endIndex;currentPostion = startIndex;}@Overridepublic void run() {System.out.println("第 " + threadId + "线程开始 下载了 : 下载 从 "+ startIndex + "~ " + endIndex);// 去干 下载的 事儿 -- 要下载 目标 部分的数据// 需要 连接上 服务器try {URL url = new URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setConnectTimeout(5000);conn.setRequestMethod("GET");// 在多线 程 下载的时候 , 每条线程 只需要 目标 文件的 一部分的数据// 需要 告诉 服务器, 只需要 那一段的数据// 通过 设置 http的 请求头 可以去实现 , 告诉 服务器, 只需要目标 段的数据// startIndex ---- endIndexconn.setRequestProperty("range", "bytes=" + startIndex + "-"+ endIndex);// 获得 服务器返回的目标段的数据File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+getFileName(path));RandomAccessFile raf = new RandomAccessFile(file, "rw");File ilf = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+threadId + ".position");if (ilf.exists() && ilf.length() > 0) {BufferedReader br = new BufferedReader(new FileReader(ilf));String vl = br.readLine();int alreadyWritePosition = Integer.parseInt(vl);// 告诉 服务器要数据的时候 ,从这个位置 开始 要conn.setRequestProperty("range", "bytes="+ alreadyWritePosition + "-" + endIndex);// 要 告诉 从哪个位置开始写raf.seek(alreadyWritePosition);System.out.println("表示 之前下载过 ");} else {System.out.println("表示 之前 没有 下载过 ");conn.setRequestProperty("range", "bytes=" + startIndex+ "-" + endIndex);// 要 告诉 从哪个位置开始写raf.seek(startIndex);}// 206 ---int code = conn.getResponseCode();if (code == 206) {// 拿到 数据InputStream in = conn.getInputStream();int len = 0;byte[] buf = new byte[1024];while ((len = in.read(buf)) > 0) {raf.write(buf, 0, len);// 将 实时的位置 给 记录了 下载了, 记录了之后, 方便 下面紧接着 去 往 文件中去写currentPostion = currentPostion + len;File info = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+threadId + ".position");RandomAccessFile rf = new RandomAccessFile(info, "rwd");// 硬盘设备 : 机械硬盘(小马达 ) , 固态硬盘(没有 所谓的马达 , ssd ) // 达到一定的次数 就会报废 // out.write((currentPostion+"").getBytes());rf.write(String.valueOf(currentPostion).getBytes());rf.close();}in.close();raf.close();}System.out.println("第 " + threadId + "线程 下载 结束 了 ");// 等着 所有的线程 都下载完成后 再去 删 文件// 弄一个 计数器, 记住 总共有 多少条线程 正在下载, 每当一条线程 下载完成, 走到 了这里的时候, 就将计数器-1// 一下,// 当发现 计数器 小于 或者 等于0 的时候, 说明没有线程正在下载了, 所以 这个时候, 再去删 记录了下载位置的文件File fff = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+threadId + ".position");fff.renameTo(new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+threadId + ".position.finish"));synchronized (MainActivity.class) {currentRunningThread--;if (currentRunningThread <= 0) {// 将记录下载位置的文件给删掉for (threadId = 0; threadId < threadCount; threadId++) {File fll = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+threadId + ".position.finish");fll.delete();}}}} catch (Exception e) {e.printStackTrace();}}}public String getFileName(String path) {int index = path.lastIndexOf("/");return path.substring(index + 1);}}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <EditText android:id="@+id/ed_path" android:text="http://172.17.2.116:8080/ff.exe" android:layout_width="fill_parent" android:layout_height="wrap_content" /><Button android:onClick="download" android:layout_width="fill_parent" android:layout_height="wrap_content" /></LinearLayout>AndroidMainfest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.INTERNET"/>
阅读全文
0 0
- 【实战】android的多线程下载
- Android实战:多线程断点续传下载器实现
- 【实战】android多线程下载(框架)
- Android实战开发租赁管理软件(适配UI,数据的存储,多线程下载)课程分享
- android多线程下载的实现
- android简单的多线程下载
- 简单的android多线程下载
- 第八部分 多线程下载实战
- Android中多线程下载方面的知识点
- android的AsyncTask使用方法-多线程下载
- Android多线程断点续传下载的实现
- Android 支持断点续传的多线程批量下载
- android 多线程下载文件大小不对的问题
- Android多线程断点续传下载的实现
- Android模拟多线程的断点下载
- Android多线程断点下载的实现示例
- Android 多线程断点下载的实现方法
- Android -- 多线程下载, 断点下载
- Css-基础
- Deeplearning-吴恩达-卷积神经网络-第二周作业01-Convolution Networks(keras)
- Python学习笔记(基础学习)
- Android PopupWindow实现带背景阴影的下滑选择框
- Spark 读取CSV 解析单元格多行数值问题
- 【实战】android的多线程下载
- android 路由框架搭建
- Spring整合ElasticJob 关闭Tomcat容器时内存泄漏
- Hdu 6240 01分数规划
- JSONObject类之解析json
- Mysql语句注意事项
- 调用函数求数组中的元素和,并统计数组中奇数的个数
- CentOS5.5使用yum时报错Error: Cannot find a valid baseurl for repo: addons
- 字体图标