Android的DownloadManager API – 下载后打开文件?

我正在面对通过DownloadManager API成功下载后打开下载文件的问题。 在我的代码中:

Uri uri=Uri.parse("http://sofzh.miximages.com/android/206402main_jsc2007e113280_hires.jpg"); Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) .mkdirs(); lastDownload = mgr.enqueue(new DownloadManager.Request(uri) .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE) .setAllowedOverRoaming(false) .setTitle("app update") .setDescription("New version 1.1") .setShowRunningNotification(true) .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "a.apk")); Cursor c=mgr.query(new DownloadManager.Query().setFilterById(lastDownload)); if(c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS))==8){ try { mgr.openDownloadedFile(c.getLong(c.getColumnIndex(DownloadManager.COLUMN_ID))); } catch (NumberFormatException e) { // TODO Auto-generated catch block e.printStackTrace(); Log.d("MGR", "Error"); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); Log.d("MGR", "Error"); } } 

问题是何时如果(c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS))== 8)诱发。 我得到了状态-1和exception。 有没有更好的方法,如何使用DownloadManager API打开下载的文件? 在我的例子中,我正在下载大图片,在真实情况下,我将下载APK文件,我需要在udpate后立即显示isntallation对话框。

编辑:我发现状态= 8是成功下载后。 你可能有不同的“检查成功下载”的方法

谢谢

Solutions Collecting From Web of "Android的DownloadManager API – 下载后打开文件?"

下载完成后,您需要注册一个接收者:

 registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); 

和一个BroadcastReciever处理程序

 BroadcastReceiver onComplete=new BroadcastReceiver() { public void onReceive(Context ctxt, Intent intent) { // Do Something } }; 

买,而不是我撕下一切,我build议你会检查出来 。

编辑:

就像一个build议,我不会推荐使用API​​ 9: http://developer.android.com/resources/dashboard/platform-versions.html : http://developer.android.com/resources/dashboard/platform-versions.html

有办法解决这个问题,通过创build你自己的下载处理程序,像我这样做,因为我们不想疏远我们的大部分android的用户群,因为你需要:创buildAsyncTask来处理文件下载。

我build议创build一个下载对话框(如果你说这是一个大文件,我会让它出现在通知区域)。

比你需要处理文件的打开:

 protected void openFile(String fileName) { Intent install = new Intent(Intent.ACTION_VIEW); install.setDataAndType(Uri.fromFile(new File(fileName)), "MIME-TYPE"); startActivity(install); } 

问题

Android的DownloadManager API – 下载后打开文件?

 /** * Used to download the file from url. * <p/> * 1. Download the file using Download Manager. * * @param url Url. * @param fileName File Name. */ public void downloadFile(final Activity activity, final String url, final String fileName) { try { if (url != null && !url.isEmpty()) { Uri uri = Uri.parse(url); activity.registerReceiver(attachmentDownloadCompleteReceive, new IntentFilter( DownloadManager.ACTION_DOWNLOAD_COMPLETE)); DownloadManager.Request request = new DownloadManager.Request(uri); request.setMimeType(getMimeType(uri.toString())); request.setTitle(fileName); request.setDescription("Downloading attachment.."); request.allowScanningByMediaScanner(); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName); DownloadManager dm = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE); dm.enqueue(request); } } catch (IllegalStateException e) { Toast.makeText(activity, "Please insert an SD card to download file", Toast.LENGTH_SHORT).show(); } } /** * Used to get MimeType from url. * * @param url Url. * @return Mime Type for the given url. */ private String getMimeType(String url) { String type = null; String extension = MimeTypeMap.getFileExtensionFromUrl(url); if (extension != null) { MimeTypeMap mime = MimeTypeMap.getSingleton(); type = mime.getMimeTypeFromExtension(extension); } return type; } /** * Attachment download complete receiver. * <p/> * 1. Receiver gets called once attachment download completed. * 2. Open the downloaded file. */ BroadcastReceiver attachmentDownloadCompleteReceive = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) { long downloadId = intent.getLongExtra( DownloadManager.EXTRA_DOWNLOAD_ID, 0); openDownloadedAttachment(context, downloadId); } } }; /** * Used to open the downloaded attachment. * * @param context Content. * @param downloadId Id of the downloaded file to open. */ private void openDownloadedAttachment(final Context context, final long downloadId) { DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(downloadId); Cursor cursor = downloadManager.query(query); if (cursor.moveToFirst()) { int downloadStatus = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)); String downloadLocalUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); String downloadMimeType = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE)); if ((downloadStatus == DownloadManager.STATUS_SUCCESSFUL) && downloadLocalUri != null) { openDownloadedAttachment(context, Uri.parse(downloadLocalUri), downloadMimeType); } } cursor.close(); } /** * Used to open the downloaded attachment. * <p/> * 1. Fire intent to open download file using external application. * * 2. Note: * 2.a. We can't share fileUri directly to other application (because we will get FileUriExposedException from Android7.0). * 2.b. Hence we can only share content uri with other application. * 2.c. We must have declared FileProvider in manifest. * 2.c. Refer - https://developer.android.com/reference/android/support/v4/content/FileProvider.html * * @param context Context. * @param attachmentUri Uri of the downloaded attachment to be opened. * @param attachmentMimeType MimeType of the downloaded attachment. */ private void openDownloadedAttachment(final Context context, Uri attachmentUri, final String attachmentMimeType) { if(attachmentUri!=null) { // Get Content Uri. if (ContentResolver.SCHEME_FILE.equals(attachmentUri.getScheme())) { // FileUri - Convert it to contentUri. File file = new File(attachmentUri.getPath()); attachmentUri = FileProvider.getUriForFile(activity, "com.freshdesk.helpdesk.provider", file);; } Intent openAttachmentIntent = new Intent(Intent.ACTION_VIEW); openAttachmentIntent.setDataAndType(attachmentUri, attachmentMimeType); openAttachmentIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); try { context.startActivity(openAttachmentIntent); } catch (ActivityNotFoundException e) { Toast.makeText(context, context.getString(R.string.unable_to_open_file), Toast.LENGTH_LONG).show(); } } } 

初始化FileProvider细节

AndroidManifest中的Decleare FileProvider

 <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.freshdesk.helpdesk.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_path"/> </provider> 

添加以下文件“res – > xml – > file_path.xml”

 <?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="attachment_file" path="."/> </paths> 

注意

为什么使用FileProvider

  1. 从Android 7.0我们不能与其他应用共享FileUri。
  2. 使用“DownloadManager.COLUMN_LOCAL_URI”我们将只获得FileUri,因此我们需要将其转换成ContentUri并与其他应用程序共享。

Provblem使用“DownloadManager.getUriForDownloadedFile(long id)”

  1. 不要使用“DownloadManager.getUriForDownloadedFile(long id)” – 为了得到Uri从downloadId使用外部应用程序打开文件。
  2. 因为从Android 6.0和7.0“getUriForDownloadedFile”方法返回本地uri(只能由我们的应用程序访问),我们不能与其他应用程序共享该Uri,因为他们无法访问该URI(但它是固定在Android 7.1 请参阅Android提交在这里 )。
  3. Refere Android源代码DownloadManager.java & Downloads.java
  4. 因此总是使用Column“DownloadManager.COLUMN_LOCAL_URI”来获取Uri。

参考

  1. https://developer.android.com/reference/android/app/DownloadManager.html
  2. https://developer.android.com/reference/android/support/v4/content/FileProvider.html