在android2.3以后android系統提供了一個系統組件來供其他app調用來下載東西,使用起來非常方便。
例如我們可以拿來下載app的新版本apk,同時在同時注冊一個廣播接收器來接收下載完成時DownloadManager發出的的廣播,然后自動安裝程序。
因為通常大家的安裝包都比較大,不可能一下子就下載完讓用戶在界面上等着下載完的話用戶體驗就非常不好了。如果我們使用DownloadManager來下載就非常好了,用戶能去使用app的其他功能。
1 final DownloadManager dManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); 2 Uri uri = Uri.parse(dowloadPath); 3 DownloadManager.Request request = new Request(uri); 4 // 設置下載路徑和文件名 5 request.setDestinationInExternalPublicDir("download", "updata.apk"); 6 request.setDescription("軟件新版本下載"); 7 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); 8 request.setMimeType("application/vnd.android.package-archive"); 9 // 設置為可被媒體掃描器找到 10 request.allowScanningByMediaScanner(); 11 // 設置為可見和可管理 12 request.setVisibleInDownloadsUi(true); 13 // 獲取此次下載的ID 14 final long refernece = dManager.enqueue(request); 15 // 注冊廣播接收器,當下載完成時自動安裝 16 IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); 17 BroadcastReceiver receiver = new BroadcastReceiver() { 18 19 public void onReceive(Context context, Intent intent) { 20 long myDwonloadID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); 21 if (refernece == myDwonloadID) { 22 Intent install = new Intent(Intent.ACTION_VIEW); 23 Uri downloadFileUri = dManager.getUriForDownloadedFile(refernece); 24 install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive"); 25 install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 26 startActivity(install); 27 } 28 } 29 }; 30 registerReceiver(receiver, filter);
上面這個只是在當前注冊一個廣播接收器,退出activity時要記得注銷掉廣播接收器。而且有一定的局限性,出了這個activity就不能接受到廣播了。
所以我比較推薦在AndroidManifest.xml里注冊一個廣播接收器,這樣就算你的應用退出后也能接收到下載完成的廣播,然后自動彈出安裝界面。
需要修改下代碼,把當前下載任務的ID持久化儲存起來。
1 DownloadManager dManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); 2 Uri uri = Uri.parse(dowloadPath); 3 DownloadManager.Request request = new Request(uri); 4 // 設置下載路徑和文件名 5 request.setDestinationInExternalPublicDir("download", "DOTA2資料庫.apk"); 6 request.setDescription("DOTA2資料庫新版本下載"); 7 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); 8 request.setMimeType("application/vnd.android.package-archive"); 9 // 設置為可被媒體掃描器找到 10 request.allowScanningByMediaScanner(); 11 // 設置為可見和可管理 12 request.setVisibleInDownloadsUi(true); 13 long refernece = dManager.enqueue(request); 14 // 把當前下載的ID保存起來 15 SharedPreferences sPreferences = getSharedPreferences("downloadcomplete", 0); 16 sPreferences.edit().putLong("refernece", refernece).commit();
然后我們先寫一個我們需要的接收器。
1 public class UpdataBroadcastReceiver extends BroadcastReceiver { 2 3 @SuppressLint("NewApi") 4 public void onReceive(Context context, Intent intent) { 5 long myDwonloadID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); 6 SharedPreferences sPreferences = context.getSharedPreferences("downloadcomplete", 0); 7 long refernece = sPreferences.getLong("refernece", 0); 8 if (refernece == myDwonloadID) { 9 String serviceString = Context.DOWNLOAD_SERVICE; 10 DownloadManager dManager = (DownloadManager) context.getSystemService(serviceString); 11 Intent install = new Intent(Intent.ACTION_VIEW); 12 Uri downloadFileUri = dManager.getUriForDownloadedFile(myDwonloadID); 13 install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive"); 14 install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 15 context.startActivity(install);16 } 17 } 18 19 }
在AndroidManifest.xml的application節點下加入以下代碼就行了。
1 <receiver 2 android:name=".UpdataBroadcastReceiver"> 3 <intent-filter> 4 <action android:name="android.intent.action.DOWNLOAD_COMPLETE" /> 5 </intent-filter> 6 </receiver>
這樣就是你的應用退出后,DownloadManager下載文件完成后發出的廣播還能被接收到,然后接收器會執行你設定的動作。
這種下載器非常好用,但是我們如果想讓2.1、2.2的應用兼容呢?或者覺得不夠自定義。那么我們下篇就來仿照這種方式給自己app寫一個專屬的文件下載器。