首页 > 代码库 > 安卓 下载多线程带进度条
安卓 下载多线程带进度条
当我们学完java中多线程的下载后,可以将它移植到我们的安卓中来,下面是具体实现源码:
DownActivity.java
[java] view plaincopy
- package com.example.downloads;
- import java.io.File;
- import java.io.IOException;
- import java.io.RandomAccessFile;
- import java.net.HttpURLConnection;
- import java.net.MalformedURLException;
- import java.net.URL;
- import com.example.downloads.utils.DownLoadThread;
- import android.os.Bundle;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.Message;
- import android.annotation.SuppressLint;
- import android.app.Activity;
- import android.text.TextUtils;
- import android.view.Menu;
- import android.view.View;
- import android.widget.EditText;
- import android.widget.ProgressBar;
- import android.widget.TextView;
- import android.widget.Toast;
- public class DownActivity extends Activity {
- // 声明控件
- // 路径与线程数量
- public EditText et_url, et_num;
- // 进度条
- public static ProgressBar pb_thread;
- // 显示进度的操作
- public TextView tv_pb;
- // 线程的数量
- public static int threadNum = 3;
- // 每个线程负责下载的大小
- public int blockSize;
- public static int threadCount;// 数量
- // 访问的path
- public String path;
- public static boolean flag = true;
- // 记录进度条的值
- public static int pb_count = 0;
- public static Handler handler;
- public static final int TEXTVALUE = 1;
- public static int pb_num = 0;
- public static int size = 0;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_down);
- et_url = (EditText) findViewById(R.id.et_path);
- et_num = (EditText) findViewById(R.id.et_threadNum);
- pb_thread = (ProgressBar) findViewById(R.id.pb_down);
- tv_pb = (TextView) findViewById(R.id.tv_pb);
- handler = new Handler() {
- @SuppressLint("HandlerLeak")
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- switch (msg.what) {
- case TEXTVALUE:
- System.out.println("-------" + DownActivity.pb_count
- + "//////" + DownActivity.size);
- // 改变TEXTView
- pb_num = (DownActivity.pb_count * 100) / DownActivity.size;
- tv_pb.setText("当前进度是+" + pb_num + "%");
- break;
- default:
- break;
- }
- }
- };
- }
- @Override
- public 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;
- }
- public void downLoad(View v) {
- DownActivity.flag = true;
- DownActivity.pb_count = 0;
- path = et_url.getText().toString();
- String threadNum_et = et_num.getText().toString();
- if (TextUtils.isEmpty(path) || TextUtils.isEmpty(threadNum_et)) {
- Toast.makeText(this, "不能为空", Toast.LENGTH_LONG).show();
- return;
- }
- Toast.makeText(this, "url:" + path + "--" + threadNum_et,
- Toast.LENGTH_LONG).show();
- // 转换成数字
- threadNum = Integer.valueOf(threadNum_et);
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- // 创建出URL对象
- URL url = new URL(path);
- // 创建出 HttpURLConnection对象
- HttpURLConnection httpURLConnection = (HttpURLConnection) url
- .openConnection();
- // 设置 发请求发送的方式
- httpURLConnection.setRequestMethod("GET");
- // 设置请求是否超时时间
- httpURLConnection.setConnectTimeout(5000);
- // 设置
- httpURLConnection
- .setRequestProperty("User-Agent",
- " Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");
- // 是否响应成功
- if (httpURLConnection.getResponseCode() == 200) {
- // 获取文件的大小
- size = httpURLConnection.getContentLength();
- System.out.println("文件的大小" + size);
- // 设置进度条的最大值
- pb_thread.setMax(size);
- // 创建文件 //保存到SD卡上
- // 首先判断是否拥有sdcard
- if (Environment.getExternalStorageState().equals(
- Environment.MEDIA_MOUNTED)) {
- // 获取sdCard文件目录对象
- File sdFile = Environment
- .getExternalStorageDirectory();
- // 创建文件对象
- File file = new File(sdFile, "youdao.exe");
- RandomAccessFile accessFile = new RandomAccessFile(
- file, "rwd");
- // 设置文件的大小
- accessFile.setLength(size);
- // 每个线程下载的大小
- blockSize = size / threadNum;
- // 开三个线程 操作此文件
- for (int i = 1; i <= threadNum; i++) {
- // 1 2 3
- // 计算出每个线程开始的位置
- int startSize = (i - 1) * blockSize;
- // 结束位置
- int endSize = (i) * blockSize;
- // 当线程是最后一个线程的时候
- if (i == threadNum) {
- // 判断文件的大小是否大于计算出来的结束位置
- if (size > endSize) {
- // 结束位置 等于 文件的大小
- endSize = size;
- }
- }
- // 为每个线程创建一个随机的读取
- RandomAccessFile threadAccessFile = new RandomAccessFile(
- file, "rwd");
- new Thread(new DownLoadThread(i,
- threadAccessFile, startSize, endSize,
- path)).start();
- }
- }
- }
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }).start();
- }
- /**
- * 暂停操作
- *
- * @param v
- */
- public void downPause(View v) {
- Toast.makeText(this, "暂停", Toast.LENGTH_LONG).show();
- this.flag = false;
- }
- }
DownLoadThread.java
[java] view plaincopy
- package com.example.downloads.utils;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.RandomAccessFile;
- import java.net.HttpURLConnection;
- import java.net.MalformedURLException;
- import java.net.URL;
- import com.example.downloads.DownActivity;
- import android.os.Environment;
- public class DownLoadThread implements Runnable {
- public RandomAccessFile accessFile; // 每个线程 都拥有一个accessFile的文件对象 线程1 线程2 线程3
- // 线程下载文件的起始位置
- public int startSize;
- public int endSize;
- // 文件下载的path路径
- public String path;
- public int threadId; // 线程的标识
- public DownLoadThread(int threadId, RandomAccessFile accessFile,
- int startSize, int endSize, String path) {
- this.threadId = threadId;
- this.accessFile = accessFile;
- this.startSize = startSize;
- this.endSize = endSize;
- this.path = path;
- }
- @Override
- public void run() {
- // 执行run方法
- try {
- // 创建文件到SD卡上去
- // 首先判断是否拥有sdcard
- if (Environment.getExternalStorageState().equals(
- Environment.MEDIA_MOUNTED)) {
- // 获取sdCard文件目录对象
- File sdFile = Environment.getExternalStorageDirectory();
- File threadFile = new File(sdFile, threadId + ".txt");
- if (threadFile.exists()) {
- // 读取该文件的内容
- // 创建文件的输入流对象
- FileInputStream fis = new FileInputStream(threadFile);
- // 采用工具类读取
- byte data[] = StreamTools.isToData(fis);
- // 转化成字符串
- String threadLen = new String(data);
- if ((threadLen != null) && (!"".equals(threadLen))) {
- startSize = Integer.valueOf(threadLen);
- // 解决 416bug的错误
- if (startSize > endSize) {
- startSize = endSize - 1;
- }
- }
- }
- // 创建文件
- // 创建URL对象
- URL url = new URL(path);
- // 创建HttpURLConnection对象
- HttpURLConnection httpURLConnection = (HttpURLConnection) url
- .openConnection();
- // 设置请求的头
- httpURLConnection.setRequestMethod("GET");
- // 设置请求是否超时时间
- httpURLConnection.setConnectTimeout(5000);
- // 设置
- httpURLConnection
- .setRequestProperty("User-Agent",
- " Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");
- // 关键的设置
- httpURLConnection.setRequestProperty("Range", "bytes="
- + startSize + "-" + endSize);
- // 输出当前线程
- System.out.println("当前线程" + threadId + " 下载开始位置:" + startSize
- + " 下载结束位置:" + endSize);
- // 响应成功
- // 设置随机读取文件的 开始位置
- accessFile.seek(startSize);
- // 获取相应流对象
- InputStream is = httpURLConnection.getInputStream();
- // 创建输出流对象
- byte buffer[] = new byte[1024];
- int len = 0;
- int threadTotal = 0;// 每个线程下载后保存记录 /
- while ((len = is.read(buffer)) != -1) {
- accessFile.write(buffer, 0, len);
- threadTotal += len;// 记录你写入的长度 //xml文件
- //改变进度条:
- setProgressBar(len);
- // 通过文件记录文件下载的长度
- FileOutputStream fos = new FileOutputStream(threadFile);
- fos.write((threadTotal + "").getBytes());
- fos.flush();
- fos.close();
- //发送handler消息
- DownActivity.handler.sendEmptyMessage(DownActivity.TEXTVALUE);
- if(!DownActivity.flag){
- return;
- }
- }
- accessFile.close();
- is.close();
- System.out.println(threadId + "线程执行完毕");
- // 线程操作
- synchronized (DownActivity.class) {
- DownActivity.threadCount++;
- if (DownActivity.threadCount >= DownActivity.threadNum) {
- for (int i = 1; i <= DownActivity.threadNum; i++) {
- // 获取sdCard上的文件
- File deleteFile = new File(sdFile, i + ".txt");
- if (deleteFile.exists()) {
- // 文件删除
- deleteFile.delete();
- }
- }
- }
- }
- }
- } catch (MalformedURLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- public synchronized void setProgressBar(int len){
- DownActivity.pb_count+=len;
- DownActivity.pb_thread.setProgress(DownActivity.pb_count);
- }
- }
StreamTools.java
[java] view plaincopy
- package com.example.downloads.utils;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- public class StreamTools {
- public static byte[] isToData(InputStream is) throws IOException{
- // 字节输出流
- ByteArrayOutputStream bops = new ByteArrayOutputStream();
- // 读取数据的缓存区
- byte buffer[] = new byte[1024];
- // 读取长度的记录
- int len = 0;
- // 循环读取
- while ((len = is.read(buffer)) != -1) {
- bops.write(buffer, 0, len);
- }
- // 把读取的内容转换成byte数组
- byte data[] = bops.toByteArray();
- bops.flush();
- bops.close();
- is.close();
- return data;
- }
- }
strings.xml
[html] view plaincopy
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <string name="app_name">downloads</string>
- <string name="action_settings">Settings</string>
- <string name="tv_down">文件下载的地址</string>
- <string name="tv_threadNum">线程数量</string>
- <string name="tv_num">0%</string>
- <string name="btn_text">下载</string>
- <string name="btn_pause">暂停</string>
- <string name="et_path">http://172.22.64.8:8080/doudou/youdao.exe</string>
- <string name="et_threadNum">3</string>
- </resources>
布局文件:
[html] view plaincopy
- <RelativeLayout 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=".DownActivity" >
- <TextView
- android:id="@+id/textView1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:text="@string/tv_down" />
- <EditText
- android:id="@+id/et_path"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentRight="true"
- android:layout_below="@+id/textView1"
- android:ems="10"
- android:inputType="none"
- android:text="@string/et_path" >
- <requestFocus />
- </EditText>
- <TextView
- android:id="@+id/textView2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_below="@+id/et_path"
- android:text="@string/tv_threadNum" />
- <EditText
- android:id="@+id/et_threadNum"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignLeft="@+id/textView2"
- android:layout_alignRight="@+id/et_path"
- android:layout_below="@+id/textView2"
- android:ems="10"
- android:inputType="number"
- android:text="@string/et_threadNum" />
- <ProgressBar
- android:id="@+id/pb_down"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignLeft="@+id/et_threadNum"
- android:layout_alignRight="@+id/et_threadNum"
- android:layout_below="@+id/et_threadNum"
- android:layout_marginTop="14dp" />
- <TextView
- android:id="@+id/tv_pb"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignRight="@+id/textView1"
- android:layout_below="@+id/pb_down"
- android:layout_marginTop="24dp"
- android:text="@string/tv_num" />
- <Button
- android:id="@+id/btn_down"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignLeft="@+id/pb_down"
- android:layout_below="@+id/tv_pb"
- android:layout_marginTop="32dp"
- android:onClick="downLoad"
- android:text="@string/btn_text" />
- <Button
- android:id="@+id/button1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignLeft="@+id/btn_down"
- android:layout_below="@+id/btn_down"
- android:layout_marginTop="16dp"
- android:onClick="downPause"
- android:text="@string/btn_pause" />
- </RelativeLayout>
效果如下:
最后要注意的是别忘了在项目清单文件中加入权限:
[html] view plaincopy
- <!-- SDCard权限 -->
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <!-- 访问网络的权限 -->
- <uses-permission android:name="android.permission.INTERNET" />
- http://blog.csdn.net/sgx425021234/article/details/9191963
安卓 下载多线程带进度条
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。