国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

Android下載進(jìn)度監(jiān)聽(tīng)和通知的處理詳解

2019-10-22 18:30:49
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本文實(shí)例為大家分享了Android下載進(jìn)度監(jiān)聽(tīng)和通知的具體代碼,供大家參考,具體內(nèi)容如下

下載管理器

關(guān)于下載進(jìn)度的監(jiān)聽(tīng),這個(gè)比較簡(jiǎn)單,以apk文件下載為例,需要處理3個(gè)回調(diào)函數(shù),分別是:

1.下載中
2.下載成功
3.下載失敗

因此對(duì)應(yīng)的回調(diào)接口就有了:

public interface DownloadCallback {  /**   * 下載成功   * @param file 目標(biāo)文件   */  void onComplete(File file);  /**   * 下載失敗   * @param e   */  void onError(Exception e);  /**   * 下載中   * @param count 總大小   * @param current 當(dāng)前下載的進(jìn)度   */  void onLoading(long count, long current);}

接下來(lái)就是線程池的管理了,當(dāng)然你也可以直接使用Executors工具類(lèi)中提供的幾個(gè)靜態(tài)方法來(lái)創(chuàng)建線程池,這里我是手動(dòng)創(chuàng)建線程池的,代碼如下:

public class ThreadManager {  private static ThreadPool mThreadPool;  /**   * 獲取線程池   *   * @return   */  public static ThreadPool getThreadPool() {    if (null == mThreadPool) {      synchronized (ThreadManager.class) {        if (null == mThreadPool) {          // cpu個(gè)數(shù)          int cpuNum = Runtime.getRuntime().availableProcessors();          //線程個(gè)數(shù)          int count = cpuNum * 2 + 1;          mThreadPool = new ThreadPool(count, count, 0);        }      }    }    return mThreadPool;  }  public static class ThreadPool {    int corePoolSize;// 核心線程數(shù)    int maximumPoolSize;// 最大線程數(shù)    long keepAliveTime;// 保持活躍時(shí)間(休息時(shí)間)    private ThreadPoolExecutor executor;    /**     * 構(gòu)造方法初始化     *     * @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());      }    };    /**     * 執(zhí)行線程任務(wù)     *     * @param r     */    public void execute(Runnable r) {      //參1:核心線程數(shù);參2:最大線程數(shù);參3:保持活躍時(shí)間(休息時(shí)間);參4:活躍時(shí)間單位;參5:線程隊(duì)列;參6:線程工廠;參7:異常處理策略      if (null == executor) {        executor = new ThreadPoolExecutor(corePoolSize,            maximumPoolSize,            keepAliveTime,            TimeUnit.SECONDS,            new LinkedBlockingQueue<Runnable>(),            sThreadFactory/*Executors.defaultThreadFactory()*/,            new ThreadPoolExecutor.AbortPolicy());      }      // 將當(dāng)前Runnable對(duì)象放在線程池中執(zhí)行      executor.execute(r);    }    /**     * 從線程池的任務(wù)隊(duì)列中移除一個(gè)任務(wù)     * 如果當(dāng)前任務(wù)已經(jīng)是運(yùn)行狀態(tài)了,那么就表示不在任務(wù)隊(duì)列中了,也就移除失敗.     */    public void cancle(Runnable r) {      if (null != executor && null != r) {        executor.getQueue().remove(r);      }    }    /**     * 是否關(guān)閉了線程池     * @return     */    public boolean isShutdown(){      return executor.isShutdown();    }    /**     * 關(guān)閉線程池     */    public void shutdown() {      executor.shutdown();    }  }}

接下來(lái)就是一個(gè)下載管理器的封裝了.

public class DownloadManager {  private DownloadCallback callback;  private Context context;  private String url;  private String fileName;  /**   * 初始化   * @param context 上下文   * @param url 目標(biāo)文件url   * @param fileName 下載保存的文件名   * @param callback 下載回調(diào)函數(shù)   */  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;  }  /**   * 開(kāi)始下載   */  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();          }        }      }    });  }}

涉及的工具類(lèi)如下:
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();    }    //修改目錄權(quán)限可讀可寫(xiě)可執(zhí)行    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();    }  }}

下載通知服務(wù)

同樣以apk下載為例,要實(shí)現(xiàn)下載通知服務(wù)的話,就用到了Notification和Service,Notification用來(lái)通知下載進(jìn)度并顯示給用戶(hù)看,Service用于后臺(tái)默默的下載文件,這里我用到了IntentService,它的好處在于任務(wù)執(zhí)行完畢后會(huì)自動(dòng)關(guān)閉服務(wù).同時(shí)程序用如果其他地方還想監(jiān)聽(tīng)到下載的進(jìn)度,那么可以在IntentService下載服務(wù)中通過(guò)發(fā)送廣播告知進(jìn)度.

ok,下面的代碼可以直接用戶(hù)實(shí)現(xiàn)apk的升級(jí)更新的操作.

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");  }  /**   * 開(kāi)始更新   *   * @param context   * @param url   更新的url   * @param fileName 下載保存apk的文件名稱(chēng)   */  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);    }  }  /**   * 初始數(shù)據(jù)   *   * @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("開(kāi)始更新").        setDefaults(1).        setProgress(100, 0, false).        setContentText("下載進(jìn)度").        build();    this.updateNotificationManager.notify(this.iconID, this.builderNotification.build());  }  /**   * 開(kāi)始下載apk   *   * @param append 是否支持?jǐn)帱c(diǎn)續(xù)傳   */  private void downloadFile(final boolean append) {    final Message message = updateHandler.obtainMessage();    int currentSize = 0; //上次下載的大小    long readSize = 0L;//已下載的總大小    long contentLength = 0;//服務(wù)器返回的數(shù)據(jù)長(zhǎng)度    if (append) {      FileInputStream fis = null;      try {        fis = new FileInputStream(UpdateService.this.apkFile);        currentSize = fis.available();//獲取上次下載的大小,斷點(diǎn)續(xù)傳可用      } 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);      //實(shí)時(shí)更新通知      UpdateService.this.builderNotification.setSmallIcon(iconID).          setContentTitle(UpdateService.this.getResources().getString(UpdateService.this.appNameID)).          setContentIntent(updatePendingIntent).          setAutoCancel(true).          setTicker("正在更新").          setDefaults(0).          setContentText("下載進(jìn)度").          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());          //發(fā)送廣播,通知外界下載進(jìn)度          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);    }  }  /**   * 發(fā)送更新進(jìn)度   *   * @param progress   */  private void sendUpdateProgress(int progress) {    Intent intent = new Intent(ACTION_UPDATE_PROGRESS);    intent.putExtra("progress", progress);    sendBroadcast(intent);  }  /**   * 下載失敗通知用戶(hù)重新下載   */  private void onFailNotification() {    this.builderNotification.setSmallIcon(iconID).        setContentTitle("更新失敗,請(qǐng)重新下載").        setContentIntent(updatePendingIntent).        setAutoCancel(true).        setTicker("更新失敗").        setDefaults(1).        setProgress(100, 0, false).        setContentText("下載進(jìn)度").        build();    this.updateNotificationManager.notify(iconID, this.builderNotification.build());  }  /**   * 下載完畢,后通知用戶(hù)點(diǎn)擊安裝   */  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("更新完成,點(diǎn)擊安裝").        build();    this.updateNotificationManager.notify(this.iconID, this.builderNotification.build());  }}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到Android開(kāi)發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 怀安县| 东阿县| 桃园市| 台东市| 仁化县| 美姑县| 尼玛县| 宣城市| 浦东新区| 高雄市| 梧州市| 茂名市| 巫山县| 凌源市| 德保县| 松原市| 麻城市| 平昌县| 游戏| 嵊泗县| 栖霞市| 广德县| 杨浦区| 清原| 达孜县| 蚌埠市| 山西省| 工布江达县| 瑞金市| 霍州市| 安乡县| 杂多县| 开原市| 韶山市| 易门县| 西盟| 台南县| 宾阳县| 清苑县| 淳化县| 长乐市|