在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写一个专属的文件下载器。