Androidx学习笔记(44)--- 多线程断点续传(Android项目)
2016-02-03 22:07
651 查看
手机版的断点续传多线程下载器
把刚才的代码直接粘贴过来就能用,记得在访问文件时的路径要改成Android的目录,添加访问网络和外部存储的路径测试代码
/** * 注意:没有判断SD卡是否存在,剩余空间 */ public class MainActivity extends ActionBarActivity { static int ThreadCount = 3; // 下载线程的数量 static int finishedThread = 0; // 记录关闭线程的数量 用于删除临时文件 // 确定下载地址 String path = "http://192.168.1.101:8080/a/b.exe"; String fileName = null; String fileType = null ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获取文件名和后缀名 File file = new File(path); fileName = file.getName(); fileType = fileName.substring(fileName.lastIndexOf(".") ,fileName.length()); //String fileType = fileName.substring(fileName.lastIndexOf(".") +1,fileName.length()); } public void click(View v) { Thread thread = new Thread() { public void run() { // 发送get请求,请求这个地址的资源 try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); if (conn.getResponseCode() == 200) { // 拿到所请求资源文件的长度 int length = conn.getContentLength(); File file = new File(Environment.getExternalStorageDirectory(), fileName+fileType); // 生成临时文件 RandomAccessFile raf = new RandomAccessFile(file, "rwd"); // 设置临时文件的大小 raf.setLength(length); raf.close(); // 计算出每个线程应该下载多少字节 int size = length / ThreadCount; for (int i = 0; i < ThreadCount; i++) { // 计算线程下载的开始位置和结束位置 int startIndex = i * size; int endIndex = (i + 1) * size - 1; // 如果是最后一个线程,那么结束位置写死 if (i == ThreadCount - 1) { endIndex = length - 1; } // System.out.println("线程" + i + "的下载区间是:" + startIndex + // "---" + endIndex); new DownLoadThread(startIndex, endIndex, i).start(); } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }; }; thread.start(); } class DownLoadThread extends Thread { int startIndex; int endIndex; int threadId; public DownLoadThread(int startIndex, int endIndex, int threadId) { super(); this.startIndex = startIndex; this.endIndex = endIndex; this.threadId = threadId; } @Override public void run() { // 再次发送http请求,下载原文件 try { // 生成一个专门用来记录下载进度的临时文件 File progressFile = new File(Environment.getExternalStorageDirectory(),threadId + ".txt"); // 判断进度临时文件是否存在 if (progressFile.exists()) { FileInputStream fis = new FileInputStream(progressFile); BufferedReader br = new BufferedReader(new InputStreamReader( fis)); // 从进度临时文件中读取出上一次下载的总进度,然后与原本的开始位置相加,得到新的开始位置 startIndex += Integer.parseInt(br.readLine()); fis.close(); } HttpURLConnection conn; URL url = new URL(path); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); // 设置本次http请求所请求的数据的区间 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); // 请求部分数据,相应码是206 if (conn.getResponseCode() == 206) { // 流里此时只有1/3原文件的数据 InputStream is = conn.getInputStream(); byte[] b = new byte[1024]; int len = 0; int total = 0; // 拿到临时文件的输出流 File file = new File(Environment.getExternalStorageDirectory(), fileName+fileType); RandomAccessFile raf = new RandomAccessFile(file, "rwd"); // 把文件的写入位置移动至startIndex raf.seek(startIndex); while ((len = is.read(b)) != -1) { // 每次读取流里数据之后,同步把数据写入临时文件 raf.write(b, 0, len); total += len; System.out.println("线程" + threadId + "下载了" + total); RandomAccessFile progressRaf = new RandomAccessFile( progressFile, "rwd"); // 每次读取流里数据之后,同步把当前线程下载的总进度写入进度临时文件中 progressRaf.write((total + "").getBytes()); progressRaf.close(); } System.out .println("线程" + threadId + "下载完毕-------------------!"); raf.close(); // 线程下载完成自加 MainActivity.finishedThread++; // 在同步语句块中 删除所有的临时文件 synchronized ( path) { if (MainActivity.finishedThread == MainActivity.ThreadCount) { for (int i = 0; i < MainActivity.ThreadCount; i++) { File f = new File(Environment.getExternalStorageDirectory(),i + ".txt"); f.delete(); } // 线程下载数量重置 MainActivity.finishedThread = 0; } } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
相关文章推荐
- 预览Android layouts, custom views和animations的插件
- Android Studio 安装genymotion 和VCS
- Android 5.0五大安全特性
- Android获取唯一设备号
- 解决 RecyclerView 在Android Studio已经导入情况下还无法实例引用问题
- Android studio 插件----android中xml tools属性详解
- Android manifest
- Android 自定义属性
- Android高手进阶——Adapter深入理解与优化
- Android 框架练成 教你打造高效的图片加载框架(转)
- android 单元测试简单方法及错误处理
- Android中System.currentTimeMillis()
- android 改变全局字体样式(第三方字体包)
- android 论编码的简洁规范
- Android:监听应用前后台切换及思考
- Android常用开源项目库
- Android的消息机制
- Android 使用自定义Marker 在谷歌地图API
- [ 转] [Android]多式样ProgressBar
- Android属性动画(二)之插值器与估值器