最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

android中DownloadManager實(shí)現(xiàn)版本更新,監(jiān)聽(tīng)下載進(jìn)度實(shí)例

 更新時(shí)間:2017年03月11日 15:50:11   作者:PhoenixGuan  
本篇文章主要介紹了android中DownloadManager實(shí)現(xiàn)版本更新,監(jiān)聽(tīng)下載進(jìn)度實(shí)例。具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。

DownloadManager簡(jiǎn)介

DownloadManager是Android 2.3(API level 9)用系統(tǒng)服務(wù)(Service)的方式提供了DownloadManager來(lái)處理長(zhǎng)時(shí)間的下載操作。它包含兩個(gè)靜態(tài)內(nèi)部類DownloadManager.Query(用來(lái)查詢下載信息)和DownloadManager.Request(用來(lái)請(qǐng)求一個(gè)下載)。

DownloadManager主要提供了下面幾個(gè)方法:

public long enqueue(Request request)把任務(wù)加入下載隊(duì)列并返回downloadId,以便后面用于查詢下載信息。若網(wǎng)絡(luò)不滿足條件、Sdcard掛載中、超過(guò)最大并發(fā)數(shù)等異常會(huì)等待下載,正常則直接下載。

public int remove(long… ids)刪除下載,若取消下載,會(huì)同時(shí)刪除下載文件和記錄。

public Cursor query(Query query)查詢下載信息,包括下載文件總大小,已經(jīng)下載的大小以及下載狀態(tài)等。

ContentObserver簡(jiǎn)介

public void ContentObserver(Handler handler) 所有ContentObserver的派生類都需要調(diào)用該構(gòu)造方法,參數(shù):handler Handler對(duì)象用于在主線程中修改UI。

public void onChange(boolean selfChange)當(dāng)觀察到的Uri中內(nèi)容發(fā)生變化時(shí),就會(huì)回調(diào)該方法。所有ContentObserver的派生類都需要重載該方法去處理邏輯。

觀察特定Uri的步驟如下:

1、創(chuàng)建我們特定的ContentObserver派生類,必須重載父類構(gòu)造方法,必須重載onChange()方法去處理回調(diào)后的功能實(shí)現(xiàn)。

2、為指定的Uri注冊(cè)一個(gè)ContentObserver派生類實(shí)例,當(dāng)給定的Uri發(fā)生改變時(shí),回調(diào)該實(shí)例對(duì)象去處理,調(diào)用registerContentObserver()方法去注冊(cè)內(nèi)容觀察者。

3、由于ContentObserver的生命周期不同步于Activity和Service等。因此,在不需要時(shí),需要手動(dòng)的調(diào)用unregisterContentObserver()注銷內(nèi)容觀察者。

效果圖:

一:執(zhí)行下載

下載配置

downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
downloadObserver = new DownloadChangeObserver();
//在執(zhí)行下載前注冊(cè)內(nèi)容監(jiān)聽(tīng)者
registerContentObserver();
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
/**設(shè)置用于下載時(shí)的網(wǎng)絡(luò)狀態(tài)*/
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
/**設(shè)置通知欄是否可見(jiàn)*/
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
/**設(shè)置漫游狀態(tài)下是否可以下載*/
request.setAllowedOverRoaming(false);
/**如果我們希望下載的文件可以被系統(tǒng)的Downloads應(yīng)用掃描到并管理,
我們需要調(diào)用Request對(duì)象的setVisibleInDownloadsUi方法,傳遞參數(shù)true.*/
request.setVisibleInDownloadsUi(true);
/**設(shè)置文件保存路徑*/
request.setDestinationInExternalFilesDir(getApplicationContext(), "phoenix", "phoenix.apk");
/**將下載請(qǐng)求放入隊(duì)列, return下載任務(wù)的ID*/
downloadId = downloadManager.enqueue(request);
//執(zhí)行下載任務(wù)時(shí)注冊(cè)廣播監(jiān)聽(tīng)下載成功狀態(tài)
registerBroadcast();

添加權(quán)限

<!--網(wǎng)絡(luò)通信權(quán)限-->
<uses-permission android:name="android.permission.INTERNET"/>
<!--SD卡寫(xiě)入數(shù)據(jù)權(quán)限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--SD卡創(chuàng)建與刪除權(quán)限-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--VISIBILITY_HIDDEN表示不顯示任何通知欄提示的權(quán)限-->
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>
<!--DownloadManager-->
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
在清單文件中注冊(cè)Service
<!--版本更新服務(wù)-->
<service android:name="com.github.phoenix.service.DownloadService"></service>

二:監(jiān)聽(tīng)下載進(jìn)度

注冊(cè)ContentObserver

三個(gè)參數(shù)分別是所要監(jiān)聽(tīng)的Uri、false表示精確匹配此Uri,true表示可以匹配其派生的Uri、ContentObserver的派生類實(shí)例。

/**
* 注冊(cè)ContentObserver
*/
private void registerContentObserver() {
 /** observer download change **/
 if (downloadObserver != null) {
   getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"), true, downloadObserver);
 }
}

查詢已下載數(shù)據(jù)大小

為了提高性能,在這里開(kāi)啟定時(shí)任務(wù),每2秒去查詢數(shù)據(jù)大小并發(fā)送到handle中更新UI。

/**
* 監(jiān)聽(tīng)下載進(jìn)度
*/
private class DownloadChangeObserver extends ContentObserver {

 public DownloadChangeObserver() {
   super(downLoadHandler);
   scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
 }

 /**
  * 當(dāng)所監(jiān)聽(tīng)的Uri發(fā)生改變時(shí),就會(huì)回調(diào)此方法
  *
  * @param selfChange 此值意義不大, 一般情況下該回調(diào)值false
  */
 @Override
 public void onChange(boolean selfChange) {
   scheduledExecutorService.scheduleAtFixedRate(progressRunnable, 0, 2, TimeUnit.SECONDS);
 }
}
/**
* 通過(guò)query查詢下載狀態(tài),包括已下載數(shù)據(jù)大小,總大小,下載狀態(tài)
*
* @param downloadId
* @return
*/
private int[] getBytesAndStatus(long downloadId) {
 int[] bytesAndStatus = new int[]{
     -1, -1, 0
 };
 DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId);
 Cursor cursor = null;
 try {
   cursor = downloadManager.query(query);
   if (cursor != null && cursor.moveToFirst()) {
     //已經(jīng)下載文件大小
     bytesAndStatus[0] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
     //下載文件的總大小
     bytesAndStatus[1] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
     //下載狀態(tài)
     bytesAndStatus[2] = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
   }
 } finally {
   if (cursor != null) {
     cursor.close();
   }
 }
 return bytesAndStatus;
}

Activity與Service通信

既然我們要在Activity中實(shí)時(shí)更新下載進(jìn)度,那么就需要Activity綁定Service建立通信。

在Service中提供一個(gè)接口實(shí)時(shí)回調(diào)進(jìn)度值。用isBindService來(lái)標(biāo)識(shí)Activity是否綁定過(guò)Service,在調(diào)用bindService(ServiceConnection conn)方法時(shí),如果綁定成功會(huì)返回true,否則返回false,只有返回true時(shí)才可以進(jìn)行解綁,否則報(bào)錯(cuò)。

private ServiceConnection conn = new ServiceConnection() {

 @Override
 public void onServiceConnected(ComponentName name, IBinder service) {
   DownloadService.DownloadBinder binder = (DownloadService.DownloadBinder) service;
   DownloadService downloadService = binder.getService();

   //接口回調(diào),下載進(jìn)度
   downloadService.setOnProgressListener(new DownloadService.OnProgressListener() {
     @Override
     public void onProgress(float fraction) {
       LogUtil.i(TAG, "下載進(jìn)度:" + fraction);
       bnp.setProgress((int)(fraction * 100));

       //判斷是否真的下載完成進(jìn)行安裝了,以及是否注冊(cè)綁定過(guò)服務(wù)
       if (fraction == DownloadService.UNBIND_SERVICE && isBindService) {
         unbindService(conn);
         isBindService = false;
         MToast.shortToast("下載完成!");
       }
     }
   });
 }

 @Override
 public void onServiceDisconnected(ComponentName name) {

 }
};

三:廣播監(jiān)聽(tīng)下載成功

下載完成,自動(dòng)安裝,記錄APK存儲(chǔ)路徑

在下載成功后把APK存儲(chǔ)路徑保存到SP中,同時(shí)關(guān)閉定時(shí)器,開(kāi)啟apk安裝界面。

/**
* 安裝APK
* @param context
* @param apkPath 安裝包的路徑
*/
public static void installApk(Context context, Uri apkPath) {
 Intent intent = new Intent();
 intent.setAction(Intent.ACTION_VIEW);
 //此處因?yàn)樯舷挛氖荂ontext,所以要加此Flag,不然會(huì)報(bào)錯(cuò)
 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 intent.setDataAndType(apkPath, "application/vnd.android.package-archive");
 context.startActivity(intent);
}

四:善后處理

1、關(guān)閉定時(shí)器,線程

當(dāng)收到下載完成的廣播時(shí)立即停掉定時(shí)器,取消線程。

2、解綁Service,注銷廣播,注銷ContentObserver

當(dāng)Service解綁的時(shí)候,要把監(jiān)聽(tīng)下載完成的廣播和監(jiān)聽(tīng)下載進(jìn)度的ContentObserver注銷。

3、刪除APK

當(dāng)應(yīng)用安裝成功后,再次啟動(dòng)就執(zhí)行刪除Apk操作。

/**
* 刪除上次更新存儲(chǔ)在本地的apk
*/
private void removeOldApk() {
 //獲取老APK的存儲(chǔ)路徑
 File fileName = new File(SPUtil.getString(Constant.SP_DOWNLOAD_PATH, ""));
 LogUtil.i(TAG, "老APK的存儲(chǔ)路徑 =" + SPUtil.getString(Constant.SP_DOWNLOAD_PATH, ""));

 if (fileName != null && fileName.exists() && fileName.isFile()) {
   fileName.delete();
   LogUtil.i(TAG, "存儲(chǔ)器內(nèi)存在老APK,進(jìn)行刪除操作");
 }
}

五:具體應(yīng)用

首先上傳當(dāng)前應(yīng)用版本號(hào)給服務(wù)器,讓服務(wù)器檢查是否可以進(jìn)行版本更新;如果可以進(jìn)行版本更新,則綁定Service,開(kāi)始下載APK,下載完成直接彈出安裝界面,同時(shí)記錄APK存儲(chǔ)路徑;待下次啟動(dòng)時(shí),檢查刪除APK。

源碼:DownloadManager_jb51.rar

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

相關(guān)文章

  • Android進(jìn)階手寫(xiě)IPC通信框架告別繁瑣AIDL

    Android進(jìn)階手寫(xiě)IPC通信框架告別繁瑣AIDL

    這篇文章主要為大家介紹了Android進(jìn)階手寫(xiě)IPC通信框架告別繁瑣AIDL實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • android studio 4.0 新建類沒(méi)有修飾符的方法

    android studio 4.0 新建類沒(méi)有修飾符的方法

    這篇文章主要介紹了android studio 4.0 新建類沒(méi)有修飾符的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 使用Android Studio 開(kāi)發(fā)自己的SDK教程

    使用Android Studio 開(kāi)發(fā)自己的SDK教程

    很多時(shí)候我們要將自己開(kāi)發(fā)一個(gè)類庫(kù)打包成jar包以供他調(diào)用,這個(gè)jar包也叫你自己的SDK或者叫l(wèi)ibrary。android studio生成jar包的方法與eclipse有所不同。在studio中l(wèi)ibrary其實(shí)是module的概念。
    2017-10-10
  • Android 通過(guò)jni返回Mat數(shù)據(jù)類型方法

    Android 通過(guò)jni返回Mat數(shù)據(jù)類型方法

    今天小編就為大家分享一篇Android 通過(guò)jni返回Mat數(shù)據(jù)類型方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Android App數(shù)據(jù)格式Json解析方法和常見(jiàn)問(wèn)題

    Android App數(shù)據(jù)格式Json解析方法和常見(jiàn)問(wèn)題

    JSON數(shù)據(jù)格式,在Android中被廣泛運(yùn)用于客戶端和網(wǎng)絡(luò)(或者說(shuō)服務(wù)器)通信,非常有必要系統(tǒng)的了解學(xué)習(xí)。恰逢本人最近對(duì)json做了一個(gè)簡(jiǎn)單的學(xué)習(xí),特此總結(jié)一下,以饗各位
    2014-03-03
  • 基于Android引入IjkPlayer無(wú)法播放mkv格式視頻的解決方法

    基于Android引入IjkPlayer無(wú)法播放mkv格式視頻的解決方法

    下面小編就為大家分享一篇基于Android引入IjkPlayer無(wú)法播放mkv格式視頻的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • 查看apk簽名信息方法

    查看apk簽名信息方法

    用shell寫(xiě)了一個(gè)查看apk簽名的腳本,下面與大家分享下如何查看apk簽名信息,感興趣的朋友可以了解下哈
    2013-06-06
  • 最新評(píng)論

    竹山县| 涡阳县| 丹阳市| 耒阳市| 桓仁| 高邮市| 遂平县| 金川县| 子洲县| 六枝特区| 徐水县| 娄烦县| 金昌市| 秦安县| 灵台县| 会理县| 兴仁县| 光山县| 五大连池市| 东丽区| 西和县| 宁强县| 革吉县| 绍兴市| 景泰县| 阿拉尔市| 固阳县| 泸西县| 江陵县| 宁都县| 临江市| 思茅市| 大渡口区| 黄冈市| 勃利县| 南江县| 阳高县| 博爱县| 新蔡县| 鹿泉市| 普兰店市|