android_36_多线程断点续传
来源:互联网 发布:java中获取当前时间 编辑:程序博客网 时间:2024/06/06 02:59
效果图:
原理图:
清单:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.sg31.multiplethreaddownload" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> // 注意权限 <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
布局:
<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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.sg31.multiplethreaddownload.MainActivity" android:orientation="vertical" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="开始下载" android:onClick="downloadBtnClicked" /><ProgressBar android:id="@+id/progressBar" android:layout_width="match_parent" android:layout_height="wrap_content" style="@android:style/Widget.ProgressBar.Horizontal" /><TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" /></LinearLayout>
代码:
package com.sg31.multiplethreaddownload;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 android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.ProgressBar;import android.widget.TextView;public class MainActivity extends ActionBarActivity {static int ThreadCount = 3;static int finishedThread = 0;int currentProgress;String fileName = "NEXT_TO_YOU.mp3";// 确定下载地址String path = "http://1od8vj43og.bkt.clouddn.com/" + fileName;private ProgressBar progressBar;TextView tv;Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {// 把变量改成long,在long下运算tv.setText((long) progressBar.getProgress() * 100/ progressBar.getMax() + "%");}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 控件progressBar = (ProgressBar) findViewById(R.id.progressBar);tv = (TextView) findViewById(R.id.tv);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// Handle action bar item clicks here. The action bar will// automatically handle clicks on the Home/Up button, so long// as you specify a parent activity in AndroidManifest.xml.int id = item.getItemId();if (id == R.id.action_settings) {return true;}return super.onOptionsItemSelected(item);}public void downloadBtnClicked(View v) {Thread t = new Thread() {@Overridepublic 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();// 设置进度条的最大值就是原文件的总长度progressBar.setMax(length);File file = new File(Environment.getExternalStorageDirectory(),fileName);// 生成临时文件,rwd表示实时写入底层设备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 blocke.printStackTrace();}}};t.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;}@Overridepublic 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));// 从进度临时文件中读取出上一次下载的总进度,然后与原本的开始位置相加,得到新的开始位置int lastProgress = Integer.parseInt(br.readLine());startIndex += lastProgress;// 把上次下载的进度显示至进度条currentProgress += lastProgress;progressBar.setProgress(currentProgress);// 发送消息,让主线程刷新文本进度handler.sendEmptyMessage(1);fis.close();}System.out.println("线程" + threadId + "的下载区间是:" + startIndex+ "---" + endIndex);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);// 请求部分数据,相应码是206if (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);RandomAccessFile raf = new RandomAccessFile(file, "rwd");// 核心代码:把文件的写入位置移动至startIndexraf.seek(startIndex);while ((len = is.read(b)) != -1) {// 每次读取流里数据之后,同步把数据写入临时文件raf.write(b, 0, len);total += len;System.out.println("线程" + threadId + "下载了" + total);// 每次读取流里数据之后,把本次读取的数据的长度显示至进度条currentProgress += len;progressBar.setProgress(currentProgress);// 发送消息,让主线程刷新文本进度handler.sendEmptyMessage(1);// 生成一个专门用来记录下载进度的临时文件RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd");// 每次读取流里数据之后,同步把当前线程下载的总进度写入进度临时文件中progressRaf.write((total + "").getBytes());progressRaf.close();}System.out.println("线程" + threadId+ "下载完毕-------------------sg31.com");raf.close();finishedThread++;synchronized (path) {if (finishedThread == ThreadCount) {for (int i = 0; i < ThreadCount; i++) {File f = new File(Environment.getExternalStorageDirectory(),i + ".txt");f.delete();}finishedThread = 0;}}}} catch (Exception e) {e.printStackTrace();}}}}
0 0
- android_36_多线程断点续传
- 多线程断点续传
- 多线程断点续传
- 多线程断点续传
- 多线程断点续传
- 多线程断点续传
- 多线程断点续传
- 多线程+断点续传
- 多线程断点续传
- 多线程断点续传研究之一
- 多线程断点续传研究之一
- 多线程断点续传的实现
- Ftp多线程与断点续传
- vc++ 实现多线程断点续传
- 模拟多线程断点续传
- Ftp多线程与断点续传
- 多线程断点续传实践
- Ftp多线程与断点续传
- 函数function
- Oracle 存储过程的学习
- Linux 中无法使用 root 用户通过 SSH 远程登录解决方法
- android_35_adb
- 欢迎使用CSDN-markdown编辑器
- android_36_多线程断点续传
- Tv开发中Actionbar焦点问题
- Class和ClassLoader的getResourceAsStream区别
- ClassLoader.getResourceAsStream(name);获取配置文件的方法
- Pattern Recognition and Machine Learning 第四章 线性分类模型
- 13.总线设备驱动模型(2)-平台总线设备设计
- 【李木华】栈
- android studio工程调用aar库运行时出现class no found exception
- list-style