栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

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

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

下载管理器

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

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

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

public interface DownloadCallback {
  
  void onComplete(File file);

  
  void onError(Exception e);

  
  void onLoading(long count, long current);
}

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

public class ThreadManager {

  private static ThreadPool mThreadPool;

  
  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;

    
    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());
      }
    };
    
    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(),
     sThreadFactory,
     new ThreadPoolExecutor.AbortPolicy());
      }
      // 将当前Runnable对象放在线程池中执行
      executor.execute(r);
    }

    
    public void cancle(Runnable r) {
      if (null != executor && null != r) {
 executor.getQueue().remove(r);
      }
    }

    
    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;

  
  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, 0, 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 {
  
  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");
  }

  
  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);
    }
  }

  
  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, 0, false).
 setContentText("下载进度").
 build();
    this.updateNotificationManager.notify(this.iconID, this.builderNotification.build());
  }

  
  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, 0, 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);
    }
  }

  
  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, 0, 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, this.appNameID, 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, 0, false).
 setContentText("更新完成,点击安装").
 build();
    this.updateNotificationManager.notify(this.iconID, this.builderNotification.build());

  }
}

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/158194.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号