android使用AsyncTask实现多线程下载实例

AsyncTask不仅方便我们在子线程中对UI进行更新操作,还可以借助其本身的线程池来实现多线程任务。下面是一个使用AsyncTask来实现的多线程下载例子。

01 效果图

02 核心类 - DownloadTask.class

public class DownloadTask extends AsyncTask<String, Integer, Integer> {
  public static final int TYPE_SUCCESS = 0;
  public static final int TYPE_FAILURE = 1;
  public static final int TYPE_PAUSE = 2;
  public static final int TYPE_CANCEL = 3;

  public int positionDownload;

  private boolean isPaused = false;
  private boolean isCancelled = false;

  private DownloadListener downloadListener;
  private int lastProgress;

  public DownloadTask(DownloadListener downloadListener){
    this.downloadListener = downloadListener;
  }

  public void setDownloadListener(DownloadListener downloadListener){
    this.downloadListener = downloadListener;
  }

  @Override
  protected Integer doInBackground(String... params) {
    InputStream is = null;
    RandomAccessFile savedFile = null;
    File file = null;

    long downloadLength = 0;
    String downloadUrl = params[0];
    positionDownload = Integer.parseInt(params[1]);
    String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));
    String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
    file = new File(directory + fileName);

    if(file.exists()){
      downloadLength = file.length();
    }

    long contentLength = getContentLength(downloadUrl);
    if(contentLength == 0){
      return TYPE_FAILURE;
    } else if(contentLength == downloadLength){
      return TYPE_SUCCESS;
    }

    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
                  .addHeader("RANGE", "bytes="+downloadLength+"-")
                  .url(downloadUrl)
                  .build();
    try {
      Response response = client.newCall(request).execute();
      if(response != null){
        is = response.body().byteStream();
        savedFile = new RandomAccessFile(file, "rw");
        savedFile.seek(downloadLength);
        byte[] buffer = new byte[1024];
        int total = 0;
        int length;

        while((length = is.read(buffer)) != -1){
          if(isCancelled){
            response.body().close();
            return TYPE_CANCEL;
          } else if(isPaused) {
            response.body().close();
            return TYPE_PAUSE;
          }

          total += length;
          savedFile.write(buffer, 0, length);

          int progress = (int) ((total + downloadLength) * 100 / contentLength);
          int currentDownload = (int) (total + downloadLength);
          publishProgress(positionDownload, progress, currentDownload, (int) contentLength);
        }

        response.body().close();
        return TYPE_SUCCESS;
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if(is != null) is.close();
        if(savedFile != null) savedFile.close();
        if(isCancelled && file != null) file.delete();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

    return TYPE_FAILURE;
  }

  @Override
  protected void onProgressUpdate(Integer... values) {
    int progress = values[1];
    if(progress > lastProgress){
      downloadListener.onProgress(values[0], progress, values[2], values[3]);
      lastProgress = progress;
    }
  }

  @Override
  protected void onPostExecute(Integer status) {
    switch (status){
      case TYPE_SUCCESS:
        downloadListener.onSuccess(positionDownload);
        break;
      case TYPE_FAILURE:
        downloadListener.onFailure();
        break;
      case TYPE_PAUSE:
        downloadListener.onPause();
        break;
      case TYPE_CANCEL:
        downloadListener.onCancel();
        break;
    }
  }

  public void pauseDownload(){
    isPaused = true;
  }

  public void cancelDownload(){
    isCancelled = true;
  }

  private long getContentLength(String downloadUrl) {
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
                  .url(downloadUrl)
                  .build();
    Response response = null;
    try {
      response = client.newCall(request).execute();
      if(response != null && response.isSuccessful()){
        long contentLength = response.body().contentLength();
        response.body().close();
        return contentLength;
      }
    } catch (IOException e) {
      e.printStackTrace();
    }

    return 0;
  }
}

03 核心类 - DownloadService.class

public class DownloadService extends Service {
  private Map<String, DownloadTask> downloadTaskMap = new HashMap<>();

  private DownloadBinder mBinder = new DownloadBinder();

  @Override
  public IBinder onBind(Intent intent) {
    return mBinder;
  }

  private Notification getNotification(String title, int progress) {
    Intent intent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
    builder.setSmallIcon(R.mipmap.ic_launcher);
    builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
    builder.setContentIntent(pendingIntent);
    builder.setContentTitle(title);
    if(progress > 0){
      builder.setContentText(progress + "%");
      builder.setProgress(100, progress, false);
    }

    return builder.build();
  }

  private NotificationManager getNotificationManager() {
    return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
  }

  class DownloadBinder extends Binder {
    public void startDownload(String url, int position, DownloadListener listener){
      if(!downloadTaskMap.containsKey(url)){
        DownloadTask downloadTask = new DownloadTask(listener);
        downloadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url, position+"");
        downloadTaskMap.put(url, downloadTask);
        if(downloadTaskMap.size() == 1){
          startForeground(1, getNotification("正在下载" + downloadTaskMap.size(), -1));
        } else{
          getNotificationManager().notify(1, getNotification("正在下载" + downloadTaskMap.size(), -1));
        }
      }
    }

    public void updateDownload(String url, DownloadListener listener){
      if(downloadTaskMap.containsKey(url)){
        DownloadTask downloadTask = downloadTaskMap.get(url);
        if(downloadTask != null){
          downloadTask.setDownloadListener(listener);
        }
      }

    }

    public void pauseDownload(String url){
      if(downloadTaskMap.containsKey(url)){
        DownloadTask downloadTask = downloadTaskMap.get(url);
        if(downloadTask != null){
          downloadTask.pauseDownload();
        }

        downloadTaskMap.remove(url);

        if(downloadTaskMap.size() > 0){
          getNotificationManager().notify(1, getNotification("正在下载" + downloadTaskMap.size(), -1));
        } else {
          stopForeground(true);
          getNotificationManager().notify(1, getNotification("全部暂停下载", -1));
        }
      }
    }

    public void downloadSuccess(String url){
      if(downloadTaskMap.containsKey(url)){
        DownloadTask downloadTask = downloadTaskMap.get(url);
        downloadTaskMap.remove(url);
        if(downloadTask != null){
          downloadTask = null;
        }

        if(downloadTaskMap.size() > 0){
          getNotificationManager().notify(1, getNotification("正在下载" + downloadTaskMap.size(), -1));
        } else {
          stopForeground(true);
          getNotificationManager().notify(1, getNotification("下载成功", -1));
        }

      }
    }

    public boolean isDownloading(String url){
      if(downloadTaskMap.containsKey(url)){
        return true;
      }

      return false;
    }

    public void cancelDownload(String url){
      if(downloadTaskMap.containsKey(url)){
        DownloadTask downloadTask = downloadTaskMap.get(url);
        if(downloadTask != null){
          downloadTask.cancelDownload();
        }
        downloadTaskMap.remove(url);

        if(downloadTaskMap.size() > 0){
          getNotificationManager().notify(1, getNotification("正在下载" + downloadTaskMap.size(), -1));
        } else {
          stopForeground(true);
          getNotificationManager().notify(1, getNotification("全部取消下载", -1));
        }
      }

      if(url != null){
        String fileName = url.substring(url.lastIndexOf("/"));
        String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
        File file = new File(directory + fileName);

        if(file.exists()){
          file.delete();
          Toast.makeText(DownloadService.this, "Deleted", Toast.LENGTH_SHORT).show();
        }
      }
    }
  }
}

04 源码

下载地址

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

(0)

相关推荐

  • Android多线程AsyncTask详解

    本篇随笔将讲解一下Android的多线程的知识,以及如何通过AsyncTask机制来实现线程之间的通信. 一.android当中的多线程 在Android当中,当一个应用程序的组件启动的时候,并且没有其他的应用程序组件在运行时,Android系统就会为该应用程序组件开辟一个新的线程来执行.默认的情况下,在一个相同Android应用程序当中,其里面的组件都是运行在同一个线程里面的,这个线程我们称之为Main线程.当我们通过某个组件来启动另一个组件的时候,这个时候默认都是在同一个线程当中完成的.当然

  • Android开发笔记之:深入理解多线程AsyncTask

    Understanding AsyncTaskAsyncTask是Android 1.5 Cubake加入的用于实现异步操作的一个类,在此之前只能用Java SE库中的Thread来实现多线程异步,AsyncTask是Android平台自己的异步工具,融入了Android平台的特性,让异步操作更加的安全,方便和实用.实质上它也是对Java SE库中Thread的一个封装,加上了平台相关的特性,所以对于所有的多线程异步都强烈推荐使用AsyncTask,因为它考虑,也融入了Android平台的特性,

  • Android使用AsyncTask实现多线程下载的方法

    本文实例讲述了Android使用AsyncTask实现多线程下载的方法.分享给大家供大家参考,具体如下: public class MainActivity extends Activity implements OnClickListener { private Button btn1, btn2, btn3; private ProgressBar progressBar1, progressBar2, progressBar3; private ImageView img1, img2,

  • android使用AsyncTask实现多线程下载实例

    AsyncTask不仅方便我们在子线程中对UI进行更新操作,还可以借助其本身的线程池来实现多线程任务.下面是一个使用AsyncTask来实现的多线程下载例子. 01 效果图 02 核心类 - DownloadTask.class public class DownloadTask extends AsyncTask<String, Integer, Integer> { public static final int TYPE_SUCCESS = 0; public static final

  • Android 使用AsyncTask实现多线程断点续传

    前面一篇博客<AsyncTask实现断点续传>讲解了如何实现单线程下的断点续传,也就是一个文件只有一个线程进行下载.    对于大文件而言,使用多线程下载就会比单线程下载要快一些.多线程下载相比单线程下载要稍微复杂一点,本博文将详细讲解如何使用AsyncTask来实现多线程的断点续传下载. 一.实现原理 多线程下载首先要通过每个文件总的下载线程数(我这里设定5个)来确定每个线程所负责下载的起止位置. long blockLength = mFileLength / DEFAULT_POOL_S

  • Android应用程序更新并下载实例

    整理文档,搜刮出一个Android应用程序更新并下载实例的代码,稍微整理精简一下做下分享. 创建一个新类,名为UpdateManager,代码如下: import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader;

  • Android中AsyncTask与handler用法实例分析

    本文实例讲述了Android中AsyncTask与handler用法.分享给大家供大家参考,具体如下: 首先,我们得明确下一个概念,什么是UI线程.顾名思义,ui线程就是管理着用户界面的那个线程! android的ui线程操作并不是安全的,并且和用户直接进行界面交互的操作都必须在ui线程中进行才可以.这种模式叫做单线程模式. 我们在单线程模式下编程一定要注意:不要阻塞ui线程.确保只在ui线程中访问ui组件 当我们要执行一个复杂耗时的算法并且最终要将计算结果反映到ui上时,我们会发现,我们根本没

  • java多线程下载实例详解

    本文实例讲述了java多线程下载.分享给大家供大家参考,具体如下: 使用多线程下载文件可以更快完成文件的下载,多线程下载文件之所以快,是因为其抢占的服务器资源多.如:假设服务器同时最多服务100个用户,在服务器中一条线程对应一个用户,100条线程在计算机中并非并发执行,而是由CPU划分时间片轮流执行,如果A应用使用了99条线程下载文件,那么相当于占用了99个用户的资源,假设一秒内CPU分配给每条线程的平均执行时间是10ms,A应用在服务器中一秒内就得到了990ms的执行时间,而其他应用在一秒内只

  • python基于queue和threading实现多线程下载实例

    本文实例讲述了python基于queue和threading实现多线程下载的方法,分享给大家供大家参考.具体方法如下: 主代码如下: #download worker queue_download = Queue.Queue(0) DOWNLOAD_WORKERS = 20 for i in range(DOWNLOAD_WORKERS): DownloadWorker(queue_download).start() #start a download worker for md5 in MD5

  • android中多线程下载实例

    复制代码 代码如下: public class MainActivity extends Activity { // 声明控件 // 路径与线程数量 private EditText et_url, et_num; // 进度条 public static ProgressBar pb_thread; // 显示进度的操作 private TextView tv_pb; // 线程的数量 public static int threadNum = 3; // 每个线程负责下载的大小 public

  • Android编程开发实现带进度条和百分比的多线程下载

    本文实例讲述了Android编程开发实现带进度条和百分比的多线程下载.分享给大家供大家参考,具体如下: 继上一篇<java多线程下载实例详解>之后,可以将它移植到我们的安卓中来,下面是具体实现源码: DownActivity.java: package com.example.downloads; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.net.H

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

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

随机推荐