Android实现简单断点续传和下载到本地功能

本文实例为大家分享了Android实现断点续传和下载的具体代码,供大家参考,具体内容如下

效果展示

导入依赖与权限

依赖

compile 'com.loopj.android:android-async-http:1.4.9'

权限

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

主MainActivity(布局)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/activity_main"
 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.lv.mama.test004.MainActivity">

 <ProgressBar
  style="?android:attr/progressBarStyleHorizontal"
  android:layout_width="match_parent"
  android:layout_height="20dp"
  android:layout_marginTop="15dp"
  android:id="@+id/pb"
  android:layout_alignParentTop="true"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true"
  />

 <TextView
  android:text="TextView"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_below="@+id/pb"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true"
  android:layout_marginLeft="20dp"
  android:layout_marginStart="20dp"
  android:layout_marginTop="13dp"
  android:id="@+id/tv_info" />

 <Button
  android:text="暂停"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginTop="17dp"
  android:id="@+id/bt_pause"
  android:onClick="pause"
  android:layout_below="@+id/tv_info"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true"
  android:layout_marginLeft="11dp"
  android:layout_marginStart="11dp" />

 <Button
  android:text="开始"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginRight="24dp"
  android:layout_marginEnd="24dp"
  android:id="@+id/bt_download"
  android:onClick="download"
  android:layout_alignBaseline="@+id/bt_pause"
  android:layout_alignBottom="@+id/bt_pause"
  android:layout_alignParentRight="true"
  android:layout_alignParentEnd="true" />
</RelativeLayout>

主MainActivity

public class MainActivity extends AppCompatActivity {
 protected static final String TAG = "OtherActivity";

 //下载线程的数量
 private final static int threadsize = 3;

 protected static final int SET_MAX = 0;
 public static final int UPDATE_VIEW = 1;

 private ProgressBar pb;
 private Button bt_download;

 private Button bt_pause;
 private TextView tv_info;
 //显示进度和更新进度
 private Handler mHandler = new Handler() {
  public void handleMessage(android.os.Message msg) {
   switch (msg.what) {
    case SET_MAX://设置进度条的最大值
     int filelength = msg.arg1;
     pb.setMax(filelength);
     break;
    case UPDATE_VIEW://更新进度条 和 下载的比率
     int len = msg.arg1;//新下载的长度
     pb.setProgress(pb.getProgress() + len);//设置进度条的刻度

     int max = pb.getMax();//获取进度的最大值
     int progress = pb.getProgress();//获取已经下载的数据量
     // 下载:30 总:100
     int result = (progress * 100) / max;

     tv_info.setText("下载:" + result + "%");

     break;

    default:
     break;
   }
  }

  ;
 };

 String uri = "http://c.hiphotos.baidu.com/image/pic/item/b90e7bec54e736d1e51217c292504fc2d46269f3.jpg";

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  //找到控件
  pb = (ProgressBar) findViewById(R.id.pb);
  tv_info = (TextView) findViewById(R.id.tv_info);

  bt_download = (Button) findViewById(R.id.bt_download);
  bt_pause = (Button) findViewById(R.id.bt_pause);

  //数据的回显
  //确定下载的文件
  String name = getFileName(uri);
  File file = new File(Environment.getExternalStorageDirectory(), name);
  if (file.exists()) {//文件存在回显
   //获取文件的大小
   int filelength = (int) file.length();
   pb.setMax(filelength);
   try {
    //统计原来所有的下载量
    int count = 0;
    //读取下载记录文件
    for (int threadid = 0; threadid < threadsize; threadid++) {
     //获取原来指定线程的下载记录
     int existDownloadLength = readDownloadInfo(threadid);
     count = count + existDownloadLength;
    }
    //设置进度条的刻度
    pb.setProgress(count);

    //计算比率
    int result = (count * 100) / filelength;
    tv_info.setText("下载:" + result + "%");
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
 }
 //暂停
 private boolean flag = false;//是否在下载

 public void pause(View v){
  flag = false;
  bt_download.setEnabled(true);
  bt_pause.setEnabled(false);
 }
 //下载
 public void download(View v){
  flag = true; //是在下载
  bt_download.setEnabled(false);//一点击变成不可点击
  bt_pause.setEnabled(true);//一点击变成可点击
  new Thread(){//子线程
   public void run() {
    try {
     //获取服务器上文件的大小
     HttpClient client = new DefaultHttpClient();
     HttpHead request = new HttpHead(uri);
     HttpResponse response = client.execute(request);
     //response 只有响应头 没有响应体
     if(response.getStatusLine().getStatusCode() == 200){
      Header[] headers = response.getHeaders("Content-Length");
      String value = headers[0].getValue();
      //文件大小
      int filelength = Integer.parseInt(value);
      Log.i(TAG, "filelength:"+filelength);

      //设置进度条的最大值
      Message msg_setmax = Message.obtain(mHandler, SET_MAX, filelength, 0);
      msg_setmax.sendToTarget();

      //处理下载记录文件
      for(int threadid=0;threadid<threadsize;threadid++){
       //对应的下载记录文件
       File file = new File(Environment.getExternalStorageDirectory(),threadid+".txt");
       //判断文件是否存在
       if(!file.exists()){
        //创建文件
        file.createNewFile();
       }
      }

      //在sdcard创建和服务器大小一样的文件
      String name = getFileName(uri);
      File file = new File(Environment.getExternalStorageDirectory(),name);
      //随机访问文件
      RandomAccessFile raf = new RandomAccessFile(file, "rwd");
      //设置文件的大小
      raf.setLength(filelength);
      //关闭
      raf.close();

      //计算每条线程的下载量
      int block = (filelength%threadsize == 0)?(filelength/threadsize):(filelength/threadsize+1);

      //开启三条线程执行下载
      for(int threadid=0;threadid<threadsize;threadid++){
       new DownloadThread(threadid, uri, file, block).start();
      }

     }
    } catch (Exception e) {
     e.printStackTrace();
    }
   };
  }.start();
 }
 //线程下载类
 private class DownloadThread extends Thread {
  private int threadid;//线程的id
  private String uri;//下载的地址
  private File file;//下载文件
  private int block;//下载的块
  private int start;
  private int end;

  public DownloadThread(int threadid, String uri, File file, int block) {
   super();
   this.threadid = threadid;
   this.uri = uri;
   this.file = file;
   this.block = block;
   //计算下载的开始位置和结束位置
   start = threadid * block;
   end = (threadid + 1) * block - 1;

   try {
    //读取该条线程原来的下载记录
    int existDownloadLength = readDownloadInfo(threadid);

    //修改下载的开始位置 从新下载
    start = start + existDownloadLength;
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
  //下载 状态码:200是普通的下载  206是分段下载  Range:范围
  @Override
  public void run() {
   super.run();
   try {
    RandomAccessFile raf = new RandomAccessFile(file, "rwd");
    //跳转到起始位置
    raf.seek(start);

    //分段下载
    HttpClient client = new DefaultHttpClient();
    HttpGet request = new HttpGet(uri);
    request.addHeader("Range", "bytes:"+start+"-"+end);//添加请求头
    HttpResponse response = client.execute(request);
    if(response.getStatusLine().getStatusCode() == 200){
     InputStream inputStream = response.getEntity().getContent();
     //把流写入到文件
     byte[] buffer = new byte[1024];
     int len = 0;
     while((len = inputStream.read(buffer)) != -1){
      //如果暂停下载 点击暂停 false 就直接return 点击下载true接着下载
      if(!flag){
       return;//标准线程结束
      }
      //写数据
      raf.write(buffer, 0, len);

      //读取原来下载的数据量 这里读取是为了更新下载记录
      int existDownloadLength = readDownloadInfo(threadid);//原来下载的数据量

      //计算最新的下载
      int newDownloadLength = existDownloadLength + len;

      //更新下载记录 从新记录最新下载位置
      updateDownloadInfo(threadid, newDownloadLength);

      //更新进度条的显示 下载的百分比
      Message update_msg = Message.obtain(mHandler, UPDATE_VIEW, len, 0);
      update_msg.sendToTarget();
      //模拟 看到进度条动的效果
      SystemClock.sleep(50);
     }
     inputStream.close();
     raf.close();
     Log.i(TAG, "第"+threadid+"条线程下载完成");
    }

   } catch (Exception e) {
    e.printStackTrace();
   }
  }
 }
 /**
  * 读取指定线程的下载数据量
  * @param threadid 线程的id
  * @return
  * @throws Exception
  */
 public int readDownloadInfo(int threadid) throws Exception{
  //下载记录文件
  File file = new File(Environment.getExternalStorageDirectory(),threadid+".txt");
  BufferedReader br = new BufferedReader(new FileReader(file));
  //读取一行数据
  String content = br.readLine();

  int downlength = 0;
  //如果该文件第一次创建去执行读取操作 文件里面的内容是 null
  if(!TextUtils.isEmpty(content)){
   downlength = Integer.parseInt(content);
  }
  //关闭流
  br.close();
  return downlength;
 }
 /**
  * 更新下载记录
  * @param threadid
  * @param newDownloadLength
  */
 public void updateDownloadInfo(int threadid,int newDownloadLength) throws Exception{
  //下载记录文件
  File file = new File(Environment.getExternalStorageDirectory(),threadid+".txt");
  FileWriter fw = new FileWriter(file);
  fw.write(newDownloadLength+"");
  fw.close();
 }

 /**
  * 获取文件的名称
  * @param uri
  * @return
  */
 private String getFileName(String uri){
  return uri.substring(uri.lastIndexOf("/")+1);
 }

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android 断点续传的原理剖析与实例讲解

    本文所要讲的是Android断点续传的内容,以实例的形式进行了详细介绍.   一.断点续传的原理 其实断点续传的原理很简单,就是在http的请求上和一般的下载有所不同而已. 打个比方,浏览器请求服务器上的一个文时,所发出的请求如下: 假设服务器域名为www.jizhuomi.com/android,文件名为down.zip. get /down.zip http/1.1 accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, ap

  • Android实现网络多线程断点续传下载实例

    我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多线程断点需要什么功能? 1.多线程下载, 2.支持断点. 使用多线程的好处:使用多线程下载会提升文件下载的速度.那么多线程下载文件的过程是: (1)首先获得下载文件的长度,然后设置本地文件的长度. HttpURLConnection.getContentLength();//获取下载文件的长度 RandomAccessFile file = new RandomAc

  • android使用OkHttp实现下载的进度监听和断点续传

    1. 导入依赖包 // retrofit, 基于Okhttp,考虑到项目中经常会用到retrofit,就导入这个了. compile 'com.squareup.retrofit2:retrofit:2.1.0' // ButterKnife compile 'com.jakewharton:butterknife:7.0.1' // rxjava 本例中线程切换要用到,代替handler compile 'io.reactivex:rxjava:1.1.6' compile 'io.react

  • Android 断点续传原理以及实现

    Android 断点续传原理以及实现 0.  前言 在Android开发中,断点续传听起来挺容易,在下载一个文件时点击暂停任务暂停,点击开始会继续下载文件.但是真正实现起来知识点还是蛮多的,因此今天有时间实现了一下,并进行记录. 1.  断点续传原理 在本地下载过程中要使用数据库实时存储到底存储到文件的哪个位置了,这样点击开始继续传递时,才能通过HTTP的GET请求中的setRequestProperty()方法可以告诉服务器,数据从哪里开始,到哪里结束.同时在本地的文件写入时,RandomAc

  • Android多线程断点续传下载功能实现代码

    原理 其实断点续传的原理很简单,从字面上理解,所谓断点续传就是从停止的地方重新下载. 断点:线程停止的位置. 续传:从停止的位置重新下载. 用代码解析就是: 断点:当前线程已经下载完成的数据长度. 续传:向服务器请求上次线程停止位置之后的数据. 原理知道了,功能实现起来也简单.每当线程停止时就把已下载的数据长度写入记录文件,当重新下载时,从记录文件读取已经下载了的长度.而这个长度就是所需要的断点. 续传的实现也简单,可以通过设置网络请求参数,请求服务器从指定的位置开始读取数据. 而要实现这两个功

  • android实现多线程下载文件(支持暂停、取消、断点续传)

    多线程下载文件(支持暂停.取消.断点续传) 多线程同时下载文件即:在同一时间内通过多个线程对同一个请求地址发起多个请求,将需要下载的数据分割成多个部分,同时下载,每个线程只负责下载其中的一部分,最后将每一个线程下载的部分组装起来即可. 涉及的知识及问题 请求的数据如何分段 分段完成后如何下载和下载完成后如何组装到一起 暂停下载和继续下载的实现(wait().notifyAll().synchronized的使用) 取消下载和断点续传的实现 一.请求的数据如何分段 首先通过HttpURLConne

  • Android断点续传下载器JarvisDownloader的示例

    JarvisDownloader 熟悉漫威电影的人都知道Jarvis,他是钢铁侠的智能管家,帮助钢铁侠制造装甲.分析大量数据.协助建模等各种智能工作,可惜在复联2中,Jarvis与灵魂宝石共同结合成Vision,钢铁侠失去了这位如亲人一般的智能AI,后来Tony用F.R.I.D.A.Y代替了Jarvis的工作,但从钢铁侠与Friday的互动来看,他只把Friday当做一般的AI,并没有投入如对待Jarvis的感情. 最近复联3上映,中国没有同步上映,真的太可惜了,五一本来还想过去香港看,但想到到

  • Android编程开发实现多线程断点续传下载器实例

    本文实例讲述了Android编程开发实现多线程断点续传下载器.分享给大家供大家参考,具体如下: 使用多线程断点续传下载器在下载的时候多个线程并发可以占用服务器端更多资源,从而加快下载速度,在下载过程中记录每个线程已拷贝数据的数量,如果下载中断,比如无信号断线.电量不足等情况下,这就需要使用到断点续传功能,下次启动时从记录位置继续下载,可避免重复部分的下载.这里采用数据库来记录下载的进度. 效果图:   断点续传 1.断点续传需要在下载过程中记录每条线程的下载进度 2.每次下载开始之前先读取数据库

  • Android实现网络多线程断点续传下载功能

    我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多线程断点需要什么功能? 1.多线程下载 2.支持断点 使用多线程的好处:使用多线程下载会提升文件下载的速度 原理 多线程下载的原理就是将要下载的文件分成若干份,其中每份都使用一个单独的线程进行下载,这样对于文件的下载速度自然就提高了许多. 既然要分成若干部分分工下载,自然要知道各个线程自己要下载的起始位置,与要下载的大小.所以我们要解决线程的分配与各个线程定位到下载

  • Android实现简单断点续传和下载到本地功能

    本文实例为大家分享了Android实现断点续传和下载的具体代码,供大家参考,具体内容如下 效果展示 导入依赖与权限 依赖 compile 'com.loopj.android:android-async-http:1.4.9' 权限 <uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name=&quo

  • 关于Android实现简单的微信朋友圈分享功能

    1.先下载微信分享的jar包放在lib目录下,并且添加依赖, 清单文件添加 <activity android:name=".wxapi.WXEntryActivity" android:exported="true">//产生回调 </activity> 2.在工程下新建如图所示的包和Activity Activity里面的内容主要是创建微信api并且注册返回回调值 private final String APP_ID= "wx

  • Android FTP 多线程断点续传下载\上传的实例

    最近在给我的开源下载框架Aria增加FTP断点续传下载和上传功能,在此过程中,爬了FTP的不少坑,终于将功能实现了,在此把一些核心功能点记录下载. FTP下载原理 FTP单线程断点续传 FTP和传统的HTTP协议有所不同,由于FTP没有所谓的头文件,因此我们不能像HTTP那样通过设置header向服务器指定下载区间. 但是FTP协议提供了一个更好用的命令REST用于从指定位置恢复任务,同时FTP协议也提供了一个命令SIZE用于获取下载的文件大小,有了这两个命令,FTP断点续传也就没有什么问题.

  • Android多线程+单线程+断点续传+进度条显示下载功能

    效果图 白话分析: 多线程:肯定是多个线程咯 断点:线程停止下载的位置 续传:线程从停止下载的位置上继续下载,直到完成任务为止. 核心分析: 断点: 当前线程已经下载的数据长度 续传: 向服务器请求上次线程停止下载位置的数据 con.setRequestProperty("Range", "bytes=" + start + "-" + end); 分配线程: int currentPartSize = fileSize / mThreadNum

  • Android中Glide实现超简单的图片下载功能

    本文介绍了Glide实现超简单的图片下载功能,具体步骤如下: 添加依赖 compile 'com.github.bumptech.glide:glide:3.7.0' 添加权限 <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/&

  • Android开发实现加载网络图片并下载至本地SdCard的方法

    本文实例讲述了Android开发实现加载网络图片并下载至本地SdCard的方法.分享给大家供大家参考,具体如下: package com.example.myimagedemo; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; imp

  • 详解Android中的多线程断点下载

    首先来看一下多线程下载的原理.多线程下载就是将同一个网络上的原始文件根据线程个数分成均等份,然后每个单独的线程下载对应的一部分,然后再将下载好的文件按照原始文件的顺序"拼接"起来就构 成了完整的文件了.这样就大大提高了文件的下载效率.对于文件下载来说,多线程下载是必须要考虑的环节. 多线程下载大致可分为以下几个步骤: 一.获取服务器上的目标文件的大小 显然这一步是需要先访问一下网络,只需要获取到目标文件的总大小即可.目的是为了计算每个线程应该分配的下载任务. 二. 在本地创建一个跟原始

  • Android开发之自带下载器DownloadManager的使用示例代码

    Android 开发中,经常有从服务器下载数据的需求出现,尤其是在线更新App的情形.其基本思路是根据本地的App版本号和服务器的版本号进行比较,如果服务器版本较新,再进行提示然后下载Apk最后进行安装.这种需求解决方案有很多,第三方的网络框架基本都有这个功能. Android自带的DownloadManager是一个很好的下载文件的工具.该类在API level 9之后出现,它已经帮我们处理了下载失败.重新下载等功能,整个下载过程全部交给系统负责,不需要我们过多的处理,非常的nice.关键的是

  • android实现多线程断点续传功能

    本文实例为大家分享了android实现多线程断点续传的具体代码,供大家参考,具体内容如下 布局: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools&qu

  • Android实现pdf在线预览或本地预览的方法

    最近项目中需要使用在线预览pdf,并要能实现自动播放,我想这样的需求无论如何来说都是很操蛋的 由于本人水平有限,最后讨论将项目需求改成将pdf下载到本地再实现自动播放. 接下来总结下目前能够实现pdf阅读的方案,开发当中需要根据实际需求去选择相应的方案. 1.使用Google doc支持来展示word,excel,pdf,txt(WebView方式在线预览): <span style="font-size:18px;">WebView urlWebView = (WebVi

随机推荐