Android下载进度监听和通知的处理详解

Android下载进度监听和通知的处理详解,第1张

概述本文实例为大家分享了Android下载进度监听和通知的具体代码,供大家参考,具体内容如下

本文实例为大家分享了AndroID下载进度监听和通知的具体代码,供大家参考,具体内容如下

下载管理器

关于下载进度的监听,这个比较简单,以apk文件下载为例,需要处理3个回调函数,分别是:

1.下载中
2.下载成功
3.下载失败

因此对应的回调接口就有了:

public interface DownloadCallback {  /**   * 下载成功   * @param file 目标文件   */  voID onComplete(file file);  /**   * 下载失败   * @param e   */  voID onError(Exception e);  /**   * 下载中   * @param count 总大小   * @param current 当前下载的进度   */  voID onLoading(long count,long current);}

接下来就是线程池的管理了,当然你也可以直接使用Executors工具类中提供的几个静态方法来创建线程池,这里我是手动创建线程池的,代码如下:

public class ThreadManager {  private static ThreadPool mThreadPool;  /**   * 获取线程池   *   * @return   */  public static ThreadPool getThreadPool() {    if (null == mThreadPool) {      synchronized (ThreadManager.class) {        if (null == mThreadPool) {          // cpu个数          int cpuNum = Runtime.getRuntime().availableProcessors();          //线程个数          int count = cpuNum * 2 + 1;          mThreadPool = new ThreadPool(count,count,0);        }      }    }    return mThreadPool;  }  public static class ThreadPool {    int corePoolSize;// 核心线程数    int maximumPoolSize;// 最大线程数    long keepAliveTime;// 保持活跃时间(休息时间)    private ThreadPoolExecutor executor;    /**     * 构造方法初始化     *     * @param corePoolSize     * @param maximumPoolSize     * @param keepAliveTime     */    private ThreadPool(int corePoolSize,int maximumPoolSize,long keepAliveTime) {      this.corePoolSize = corePoolSize;      this.maximumPoolSize = maximumPoolSize;      this.keepAliveTime = keepAliveTime;    }    private static final ThreadFactory sThreadFactory = new ThreadFactory() {      private final AtomicInteger mCount = new AtomicInteger(1);      public Thread newThread(Runnable r) {        return new Thread(r,"ThreadManager #" + mCount.getAndIncrement());      }    };    /**     * 执行线程任务     *     * @param r     */    public voID execute(Runnable r) {      //参1:核心线程数;参2:最大线程数;参3:保持活跃时间(休息时间);参4:活跃时间单位;参5:线程队列;参6:线程工厂;参7:异常处理策略      if (null == executor) {        executor = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,TimeUnit.SECONDS,new linkedBlockingQueue<Runnable>(),sThreadFactory/*Executors.defaultThreadFactory()*/,new ThreadPoolExecutor.AbortPolicy());      }      // 将当前Runnable对象放在线程池中执行      executor.execute(r);    }    /**     * 从线程池的任务队列中移除一个任务     * 如果当前任务已经是运行状态了,那么就表示不在任务队列中了,也就移除失败.     */    public voID cancle(Runnable r) {      if (null != executor && null != r) {        executor.getQueue().remove(r);      }    }    /**     * 是否关闭了线程池     * @return     */    public boolean isShutdown(){      return executor.isShutdown();    }    /**     * 关闭线程池     */    public voID shutdown() {      executor.shutdown();    }  }}

接下来就是一个下载管理器的封装了.

public class DownloadManager {  private DownloadCallback callback;  private Context context;  private String url;  private String filename;  /**   * 初始化   * @param context 上下文   * @param url 目标文件url   * @param filename 下载保存的文件名   * @param callback 下载回调函数   */  public DownloadManager(final Context context,final String url,final String filename,DownloadCallback callback) {    this.context = context;    this.url = url;    this.filename = filename;    this.callback = callback;  }  /**   * 开始下载   */  public voID startDownload() {    if (null == callback) return;    ThreadManager.getThreadPool().execute(new Runnable() {      @OverrIDe      public voID run() {        httpURLConnection conn = null;        try {          conn = (httpURLConnection) new URL(url).openConnection();          conn.setRequestMethod("GET");          conn.setReadTimeout(5000);          conn.setConnectTimeout(10000);          long total = conn.getContentLength();          long curr = 0;          file file = new file(PathUtils.getDirectory(context,"apk"),filename);          if (!file.exists()) {            file.createNewfile();          } else {            file.delete();          }          fileOutputStream fos = new fileOutputStream(file);          if (200 == conn.getResponseCode()) {            inputStream in = conn.getinputStream();            byte[] buff = new byte[1024];            int len = 0;            while ((len = in.read(buff)) != -1) {              fos.write(buff,len);              curr += len;              callback.onLoading(total,curr);            }            in.close();            fos.close();            if (curr == total) {              callback.onComplete(file);            } else {              throw new Exception("curr != total");            }          } else {            throw new Exception("" + conn.getResponseCode());          }        } catch (Exception e) {          e.printstacktrace();          callback.onError(e);        } finally {          if (null != conn) {            conn.disconnect();          }        }      }    });  }}

涉及的工具类如下:
PathUtils

public class PathUtils {  /**   * 获取cache目录下的rootDir目录   *   * @param context   * @param rootDir   * @return   */  public static file getDirectory(Context context,String rootDir) {    String cachePath = context.getApplicationContext().getCacheDir().getabsolutePath();    if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())        || !Environment.isExternalStorageRemovable()) {      if (Build.VERSION.SDK_INT <= 8) {        cachePath = Environment.getExternalStorageDirectory().getabsolutePath();      } else if (context.getApplicationContext().getExternalCacheDir() != null) {        cachePath = context.getApplicationContext().getExternalCacheDir().getabsolutePath();      }    }    file rootF = new file(cachePath + file.separator + rootDir);    if (!rootF.exists()) {      rootF.mkdirs();    }    //修改目录权限可读可写可执行    String cmd = "chmod 777 -R " + rootF.getPath();    CmdUtils.execCmd(cmd);    return rootF;  }}

CmdUtils

public class CmdUtils {  public static voID execCmd(String cmd) {    try {      Runtime.getRuntime().exec(cmd);    } catch (IOException e) {      e.printstacktrace();    }  }}

下载通知服务

同样以apk下载为例,要实现下载通知服务的话,就用到了Notification和Service,Notification用来通知下载进度并显示给用户看,Service用于后台默默的下载文件,这里我用到了IntentService,它的好处在于任务执行完毕后会自动关闭服务.同时程序用如果其他地方还想监听到下载的进度,那么可以在IntentService下载服务中通过发送广播告知进度.

ok,下面的代码可以直接用户实现apk的升级更新的 *** 作.

public class UpdateService extends IntentService {  private file apkfile;  private String url;  private String filename;  private NotificationCompat.Builder builderNotification;  private notificationmanager updatenotificationmanager;  private int appnameID;  private int iconID;  private PendingIntent updatePendingIntent;  private boolean isUpdating;  public static final String ACTION_UPDATE_PROGRESS = "blog.csdn.net.mchenys.mobilesafe.ACTION_UPDATE_PROGRESS";  private Handler updateHandler = new Handler() {    public voID handleMessage(Message msg) {      switch (msg.what) {        case 0:          UpdateService.this.onFailNotification();          break;        case 1:          UpdateService.this.downComplete();          break;      }      super.handleMessage(msg);    }  };  public UpdateService() {    super("UpdateService");  }  /**   * 开始更新   *   * @param context   * @param url   更新的url   * @param filename 下载保存apk的文件名称   */  public static voID startUpdate(Context context,String url,String filename) {    Intent intent = new Intent(context,UpdateService.class);    intent.putExtra("url",url);    intent.putExtra("filename",filename);    context.startService(intent);  }  @OverrIDe  protected voID onHandleIntent(Intent intent) {    //WorkerThread    if (!this.isUpdating && intent != null) {      initData(intent);      initNotification();      downloadfile(true);    }  }  /**   * 初始数据   *   * @param intent   */  private voID initData(Intent intent) {    this.isUpdating = true;    this.url = intent.getStringExtra("url");    this.filename = intent.getStringExtra("filename");    this.apkfile = new file(PathUtils.getDirectory(getApplicationContext(),"mobilesafe"),filename);    if (!this.apkfile.exists()) {      try {        this.apkfile.createNewfile();      } catch (IOException e) {        e.printstacktrace();      }    } else {      this.apkfile.delete();    }    this.appnameID = R.string.app_name;    this.iconID = R.mipmap.ic_logo;  }  /**   * 初始化通知   */  private voID initNotification() {    Intent updateCompletingIntent = new Intent();    updateCompletingIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_top);    updateCompletingIntent.setClass(this.getApplication().getApplicationContext(),UpdateService.class);    this.updatePendingIntent = PendingIntent.getActivity(this,this.appnameID,updateCompletingIntent,PendingIntent.FLAG_CANCEL_CURRENT);    this.updatenotificationmanager = (notificationmanager) this.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);    this.builderNotification = new NotificationCompat.Builder(this.getApplicationContext());    this.builderNotification.setSmallicon(this.iconID).        setContentTitle(this.getResources().getString(this.appnameID)).        setContentIntent(updatePendingIntent).        setautoCancel(true).        setTicker("开始更新").        setDefaults(1).        setProgress(100,false).        setContentText("下载进度").        build();    this.updatenotificationmanager.notify(this.iconID,this.builderNotification.build());  }  /**   * 开始下载apk   *   * @param append 是否支持断点续传   */  private voID downloadfile(final boolean append) {    final Message message = updateHandler.obtainMessage();    int currentSize = 0; //上次下载的大小    long readSize = 0L;//已下载的总大小    long contentLength = 0;//服务器返回的数据长度    if (append) {      fileinputStream fis = null;      try {        fis = new fileinputStream(UpdateService.this.apkfile);        currentSize = fis.available();//获取上次下载的大小,断点续传可用      } catch (IOException e) {        e.printstacktrace();      } finally {        if (fis != null) {          try {            fis.close();          } catch (IOException e) {            e.printstacktrace();          }        }      }    }    httpURLConnection conn = null;    inputStream is = null;    fileOutputStream fos = null;    try {      conn = (httpURLConnection) new URL(UpdateService.this.url).openConnection();      conn.setRequestProperty("User-Agent","AndroID");      if (currentSize > 0) {        conn.setRequestProperty("RANGE","bytes=" + currentSize + "-");      }      conn.setConnectTimeout(10000);      conn.setReadTimeout(20000);      contentLength = conn.getContentLength();      if (conn.getResponseCode() == 404) {        throw new Exception("Cannot find remote file:" + UpdateService.this.url);      }      is = conn.getinputStream();      fos = new fileOutputStream(UpdateService.this.apkfile,append);      //实时更新通知      UpdateService.this.builderNotification.setSmallicon(iconID).          setContentTitle(UpdateService.this.getResources().getString(UpdateService.this.appnameID)).          setContentIntent(updatePendingIntent).          setautoCancel(true).          setTicker("正在更新").          setDefaults(0).          setContentText("下载进度").          build();      byte[] buffer = new byte[8*1024];      int len = 0;      while ((len = is.read(buffer)) != -1) {        fos.write(buffer,len);        readSize += len;//累加已下载的大小        int progress = (int) (readSize * 100 / contentLength);        Log.d("UpdateService",(readSize * 100 / contentLength)+"");        if (progress % 8 == 0) {          UpdateService.this.builderNotification.setProgress(100,progress,false);          UpdateService.this.updatenotificationmanager.notify(iconID,UpdateService.this.builderNotification.build());          //发送广播,通知外界下载进度          sendUpdateProgress(progress);        }      }      if (readSize == 0L) {        message.what = 0;      } else if (readSize == contentLength) {        message.what = 1;        sendUpdateProgress(100);      }    } catch (Exception e) {      e.printstacktrace();      message.what = 0;    } finally {      if (conn != null) {        conn.disconnect();      }      IoUtils.close(is);      IoUtils.close(fos);      updateHandler.sendMessage(message);    }  }  /**   * 发送更新进度   *   * @param progress   */  private voID sendUpdateProgress(int progress) {    Intent intent = new Intent(ACTION_UPDATE_PROGRESS);    intent.putExtra("progress",progress);    sendbroadcast(intent);  }  /**   * 下载失败通知用户重新下载   */  private voID onFailNotification() {    this.builderNotification.setSmallicon(iconID).        setContentTitle("更新失败,请重新下载").        setContentIntent(updatePendingIntent).        setautoCancel(true).        setTicker("更新失败").        setDefaults(1).        setProgress(100,false).        setContentText("下载进度").        build();    this.updatenotificationmanager.notify(iconID,this.builderNotification.build());  }  /**   * 下载完毕,后通知用户点击安装   */  private voID downComplete() {    UpdateService.this.isUpdating = false;    String cmd = "chmod 777 " + this.apkfile.getPath();    CmdUtils.execCmd(cmd);    Uri uri = Uri.fromfile(this.apkfile);    Intent updateCompleteIntent = new Intent("androID.intent.action.VIEW");    updateCompleteIntent.addcategory("androID.intent.category.DEFAulT");    updateCompleteIntent.setDataAndType(uri,"application/vnd.androID.package-archive");    this.updatePendingIntent = PendingIntent.getActivity(this,updateCompleteIntent,PendingIntent.FLAG_UPDATE_CURRENT);    this.builderNotification.setSmallicon(this.iconID).        setContentTitle(this.getResources().getString(this.appnameID)).        setContentIntent(this.updatePendingIntent).        setautoCancel(true).        setTicker("更新完成").        setDefaults(1).        setProgress(0,false).        setContentText("更新完成,点击安装").        build();    this.updatenotificationmanager.notify(this.iconID,this.builderNotification.build());  }}

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

总结

以上是内存溢出为你收集整理的Android下载进度监听和通知的处理详解全部内容,希望文章能够帮你解决Android下载进度监听和通知的处理详解所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1144854.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存