软件编程
位置:首页>> 软件编程>> Android编程>> android多线程断点下载-带进度条和百分比进度显示效果

android多线程断点下载-带进度条和百分比进度显示效果

作者:jingxian  发布时间:2022-03-20 14:30:43 

标签:android,多线程断点下载,进度条,百分比进度

android多线程断点下载,带进度条和百分比显示,断点下载的临时数据保存到SD卡的文本文档中,建议可以保存到本地数据库中,这样可以提高存取效率,从而提高系统性能。

效果:

打开软件:

android多线程断点下载-带进度条和百分比进度显示效果

下载中:

android多线程断点下载-带进度条和百分比进度显示效果

下载完毕:

android多线程断点下载-带进度条和百分比进度显示效果

附代码如下:


package com.yy.multiDownloadOfBreakPoint;

import java.io.File;
import java.io.FileInputStream;
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.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
/**
* 多线程断点下载实例
* @author YUANYUAN
*
*/
public class MainActivity extends Activity {
 //下载所使用的线程数
 protected static final int threadCount = 3;
 //下载完毕的标记
 public static final int downloadOver = 1;
 //更新下载进度标记
 public static final int UPDATE_PROGRESS = 0;
 //下载资源的路径输入框
 private EditText et_path;
 //下载的进度条
 private ProgressBar pb;
 //进度显示
 private TextView tv_pb;
 //当前累计下载的数据
 int curDownCount=0;
 //当前活动的下载线程数
 protected static int activeThread;
 //加入消息处理机制
 private Handler handler=new Handler(){
   @Override
   public void handleMessage(Message msg) {
     switch (msg.what) {
     case downloadOver:
       Toast.makeText(MainActivity.this, "文件已下载完毕!", Toast.LENGTH_LONG).show();
       tv_pb.setText("下载完成");
       break;
     case UPDATE_PROGRESS:
       //更新进度显示
       tv_pb.setText("当前进度:"+(pb.getProgress()*100/pb.getMax())+"%");
       break;
     default:
       break;
     }
   }
 };

@Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   et_path=(EditText) findViewById(R.id.et_path);
   et_path.setText("http://192.168.2.114:8080/sqlite.exe");
   pb=(ProgressBar) findViewById(R.id.pb);
   tv_pb=(TextView) findViewById(R.id.tv_pb);
 }

/**
  * 开始下载
  * @param view
  */
 public void down(View view){
   //获取下载资源的路径
   final String path=et_path.getText().toString().trim();
   //判断资源路径是否为空
   if (TextUtils.isEmpty(path)) {
     Toast.makeText(this, "请输入下载资源的路径", Toast.LENGTH_LONG).show();
     return;
   }
   //开启一个线程进行下载
   new Thread(){
     public void run() {
       try {
         //构造URL地址
         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();
           //设置进度条的最大值
           pb.setMax(length);
           //在客户端创建一个跟服务器文件大小相同的临时文件
           RandomAccessFile raf=new RandomAccessFile("sdcard/setup.exe", "rwd");
           //指定临时文件的长度
           raf.setLength(length);
           raf.close();
           //假设3个线程去下载资源
           //平均每一个线程要下载的文件的大小
           int blockSize=length/threadCount;
           for (int threadId = 1; threadId <= threadCount; threadId++) {
             //当前线程下载数据的开始位置
             int startIndex=blockSize*(threadId-1);
             //当前线程下载数据的结束位置
             int endIndex=blockSize*threadId-1;
             //确定最后一个线程要下载数据的最大位置
             if (threadId==threadCount) {
               endIndex=length;
             }
             //显示下载数据的区间
             System.out.println("线程【"+threadId+"】开始下载:"+startIndex+"---->"+endIndex);
             //开启下载的子线程
             new DownloadThread(path, threadId, startIndex, endIndex).start();
             //当前下载活动的线程数加1
             activeThread++;
             System.out.println("当前活动的线程数:"+activeThread);
           }

}else{//请求失败
           System.out.println("服务器异常,下载失败!");
         }
       } catch (Exception e) {
         e.printStackTrace();
         System.out.println("服务器异常,下载失败!");
       }
     };
   }.start();

}
 /**
  * 下载文件的子线程 每一个文件都下载对应的数据
  * @author YUANYUAN
  *
  */
 public class DownloadThread extends Thread{
   private String path;
   private int threadId;
   private int startIndex;
   private int endIndex;

/**
    * 构造方法
    * @param path 下载文件的路径
    * @param threadId 下载文件的线程
    * @param startIndex 下载文件开始的位置
    * @param endIndex 下载文件结束的位置
    */
   public DownloadThread(String path, int threadId, int startIndex,
       int endIndex) {
     this.path = path;
     this.threadId = threadId;
     this.startIndex = startIndex;
     this.endIndex = endIndex;
   }

@Override
   public void run() {
     //构造URL地址
     try {

File tempFile=new File("sdcard/"+threadId+".txt");
       //检查记录是否存在,如果存在读取数据,设置真实下载开始的位置
       if (tempFile.exists()) {
         FileInputStream fis=new FileInputStream(tempFile);
         byte[] temp=new byte[1024];
         int length=fis.read(temp);
         //读取到已经下载的位置
         int downloadNewIndex=Integer.parseInt(new String(temp, 0, length));
         //计算出已经下载的数据长度
         int areadyDown=downloadNewIndex-startIndex;
         //累加已经下载的数据量
         curDownCount+=areadyDown;
         //设置进度条已经下载的数据量
         pb.setProgress(curDownCount);
         //设置重新开始下载的开始位置
         startIndex=downloadNewIndex;
         fis.close();
         //显示真实下载数据的区间
         System.out.println("线程【"+threadId+"】真实开始下载数据区间:"+startIndex+"---->"+endIndex);
       }

URL url = new URL(path);
       HttpURLConnection conn=(HttpURLConnection) url.openConnection();
       conn.setConnectTimeout(5000);
       conn.setRequestMethod("GET");
       //设置请求属性,请求部分资源
       conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
       int code=conn.getResponseCode();
       if (code==206) {//下载部分资源,正常返回的状态码为206
         InputStream is=conn.getInputStream();//已经设置了请求的位置,所以返回的是对应的部分资源
         //构建随机访问文件
         RandomAccessFile raf=new RandomAccessFile("sdcard/setup.exe", "rwd");
         //设置 每一个线程随机写文件开始的位置
         raf.seek(startIndex);
         //开始写文件
         int len=0;
         byte[] buffer=new byte[1024];
         //该线程已经下载数据的长度
         int total=0;

while((len=is.read(buffer))!=-1){//读取输入流
           //记录当前线程已下载数据的长度
           RandomAccessFile file=new RandomAccessFile("sdcard/"+threadId+".txt","rwd");
           raf.write(buffer,0,len);//写文件
           total+=len;//更新该线程已下载数据的总长度
           System.out.println("线程【"+threadId+"】已下载数据:"+(total+startIndex));
           //将已下载数据的位置记录写入到文件
           file.write((startIndex+total+"").getBytes());
           //累加已经下载的数据量
           curDownCount+=len;
           //更新进度条【进度条的更新可以在非UI线程直接更新,具体见底层源代码】
           pb.setProgress(curDownCount);

//更新下载进度
           Message msg=Message.obtain();
           msg.what=UPDATE_PROGRESS;
           handler.sendMessage(msg);

file.close();
         }
         is.close();
         raf.close();
         //提示下载完毕
         System.out.println("线程【"+threadId+"】下载完毕");
       }
     } catch (Exception e) {
       e.printStackTrace();
       System.out.println("线程【"+threadId+"】下载出现异常!!");
     }finally{
       //活动的线程数减少
       activeThread--;
       if (activeThread==0) {
         for (int i = 1; i <= threadCount; i++) {
           File tempFile=new File("sdcard/"+i+".txt");
           tempFile.delete();
         }
         System.out.println("下载完毕,已清除全部临时文件");
         //界面消息提示下载完毕
         Message msg=new Message();
         msg.what=downloadOver;
         handler.sendMessage(msg);
       }
     }

}
 }
}
0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com