>>分享Android开发相关的技术 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 19510 个阅读者 刷新本主题
 * 贴子主题:  Android多线程断点续传 回复文章 点赞(0)  收藏  
作者:mary    发表时间:2020-03-31 20:49:58     消息  查看  搜索  好友  邮件  复制  引用

         在Android下面的断点续传和java下面没有太大的冲突,就是在配置文件里面加上一些特定的访问权限就可以了

         如下式在AndroidManifest.xml加入的权限
                   <!--    访问 internet 权限  -->

                  <uses-permission android:name="android.permission.INTERNET" />

                  <!--    在 SDCard 中创建与删除文件权限 -->

                  <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

                  <!--    往 SDCard 写入数据权限 -->

                  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

         这个准备工作做好了就可以直接编码了

         第一步创建multiThreaddownload.java

         package com.cn.download;

         import java.io.File;

         import java.io.FileInputStream;

         import java.io.InputStream;

         import java.io.RandomAccessFile;

         import java.net.URL;

         import java.net.URLConnection;

         import com.cn.coocaa.download.FileDownloadThread;

         public class MultiThreadDownload extends Thread {

                 //定义的一些常量变量,看名字就知道什么意思了

           private static final int BUFFER_SIZE = 1024;

           private int blockSize;

           private int threadNum = 5;

           private int fileSize;

           private int downloadedSize;

           String urlStr, threadNo, fileName;

           private String savePath;

           private int downloadPercent = 0 , downloadSpeed = 0, usedTime=0;

           private long startTime,curTime;

           private boolean completed = false;

                 //用URL,保存路径,保存名称来构造。

           public MultiThreadDownload(String URL, String savePath, String fileName) {

           this.urlStr = URL;

           this.savePath = savePath;

           this.fileName = fileName;

           }

                @Override

           public void run() {

           FileDownloadThread[] fds = new FileDownloadThread;

           try {

           URL url = new URL(urlStr);

           URLConnection conn = url.openConnection();

           fileSize = conn.getContentLength();

           blockSize = fileSize / threadNum;

           File file[] = new File;

                                                //根据默认的线程数,或者自己修改设置的线程数来分块,创建分块后的文件块

           for (int i = 0; i < threadNum; i++) {

           file[i] = new File(savePath + fileName + ".part"

           + String.valueOf(i));

                                                                 //将分块的文件交给每个线程处理,最后一块应该大于等于平均块,因为可能有余数

           FileDownloadThread fdt = new FileDownloadThread(url, file[i], i

           * blockSize, (i + 1) != threadNum ? ((i + 1)

           * blockSize - 1) : fileSize);

           fdt.setName("Thread" + i);

           fdt.start();

           fds[i] = fdt;

           }

           startTime = System.currentTimeMillis();

                                                //获取起始下载的时间,用次来计算速度。

           boolean finished = false;

           while (!finished) {

           downloadedSize = 0;

           finished = true;

           for (int i = 0; i < fds.length; i++) {

           downloadedSize += fds[i].getDownloadSize();

           if (!fds[i].isFinished()) {

           finished = false;

           }

           }

                                                                 //计算下载的百分比

           downloadPercent = (downloadedSize*100)/fileSize;

                                                                //获取当前时间,计算平均下载速度

           curTime = System.currentTimeMillis();

           usedTime =(int)((curTime-startTime)/1000);

           if(usedTime==0)

           usedTime =1;

           downloadSpeed = (downloadedSize/usedTime)/1024;

           sleep(1000);

           }

                                                //这个是分块下载完成的标志

           completed = true;

                                                //进行模块整合

           RandomAccessFile raf = new RandomAccessFile(savePath + fileName,

           "rw");

           byte[] tempbytes = new byte[BUFFER_SIZE];

           InputStream in = null;

           int byteread = 0;

           for (int i = 0; i < threadNum; i++) {

           in = new FileInputStream(file[i]);

           while ((byteread = in.read(tempbytes)) != -1)

           {

           raf.write(tempbytes, 0, byteread);

           }

                                                                //每次整合完一块就删除一块。

           in.close();

           file[i].delete();

           }

           raf.close();

                             } catch (Exception e) {

           // TODO: handle exception

           }

           }

                //获取下载百分比

           public int getDownloadPercent(){

           return this.downloadPercent;

           }

                //获取下载速度

           public int getDownloadSpeed(){

           return this.downloadSpeed;

           }

                //修改默认线程数

           public void setThreadNum(int threadNum){

           this.threadNum = threadNum;

           }

                 //分块下载完成的标志

           public boolean isCompleted(){

           return this.completed;

           }

         }

     第二步 创建filedownloadthread.java

package com.cn.download;

import java.io.BufferedInputStream;

import java.io.File;

import java.io.IOException;

import java.io.RandomAccessFile;

import java.net.URL;

import java.net.URLConnection;

public class FileDownloadThread extends Thread {

   private static final int BUFFER_SIZE = 1024;

   private URL url;

   private File file;

   private int startPosition;

   private int endPosition;

   private int curPosition;

   private boolean finished = false;

   private int downloadSize = 0;

                //分块构造函数

   public FileDownloadThread(URL url, File file, int startPosition,

   int endPosition) {

   this.url = url;

   this.file = file;

   this.startPosition = startPosition;

   this.curPosition = startPosition;

   this.endPosition = endPosition;

   }

             public void run() {

                     BufferedInputStream bis = null;

   RandomAccessFile fos = null;

   byte[] buf = new byte[BUFFER_SIZE];

   URLConnection con = null;

   try {

                                                //打开URL连接

   con = url.openConnection();

   con.setAllowUserInteraction(true);

                                               //判断是否该文件存在,如果存在且下载完成,直接返回。

   if ((file.length() + startPosition) == endPosition) {

   this.finished = true;

   }

                                               //文件未下载完成,获取到当前指针位置,继续下载。

                                              else {

   con.setRequestProperty("Range", "bytes="

   + (startPosition + file.length()) + "-" + endPosition);

   fos = new RandomAccessFile(file, "rw");

   fos.seek(file.length());

   bis = new BufferedInputStream(con.getInputStream());

   while (curPosition < endPosition) {

   int len = bis.read(buf, 0, BUFFER_SIZE);

   if (len == -1) {

   break;

   }

   fos.write(buf, 0, len);

   curPosition = curPosition + len;

   if (curPosition > endPosition) {

   downloadSize += len - (curPosition - endPosition) + 1;

   } else {

   downloadSize += len;

   }

   }

   this.finished = true;

   bis.close();

   fos.close();

   }

   } catch (IOException e) {

   System.out.println(getName() + " Error:" + e.getMessage());

   }

   }

             public boolean isFinished() {

   return finished;

   }

             public int getDownloadSize() {

   return downloadSize;

   }

}

上述两个文件就完成了多线程断点续传。

          无需使用任何配置文件或者数据库,就可以接上次的断点进行续传操作。

           原理流程:

          1、获取文件大小

          2、将文件按照所设定的线程数进行分块请求。

          3、检查是否存在断点情况,如果有断点情况则进行断点查找,然后再请求。

          4、分块下载。

          5、下载完成后文件整合,将分块文件删除掉。

          6、好了,你需要下载的文件就可以完成了。

            总之了,在这里也是一种实现无需配置文件的方式吧,我提供的只是一个外部调用包,所以这个配置文件或者数据库记录的东西有很大的局限性,所以就切割了,

           如果有什么更好的想法,希望能相互交流交流。

           转载请注明:http://alloxa.blog.51cto.com/

                                                  

----------------------------
原文链接:https://blog.51cto.com/alloxa/477043

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-04-08 09:09:22 重新编辑]
网站系统异常


系统异常信息
Request URL: http://www.javathinker.net/WEB-INF/lybbs/jsp/topic.jsp?postID=3083

java.lang.NullPointerException

如果你不知道错误发生的原因,请把上面完整的信息提交给本站管理人员