在Android中,DownloadManager.ACTION_DOWNLOAD_COMPLETE广播接收器会接收到相同的下载ID,但下载状态不同的情况。

32

我正在使用Android DownloadManager系统服务以以下方式下载一些文件

dwnId = mgr.enqueue(new DownloadManager.Request(serveruri)
        .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |
                DownloadManager.Request.NETWORK_MOBILE)
                .setAllowedOverRoaming(false)
                .setTitle(getAlbumName())
                .setDescription(getTrackName())
                .setDestinationUri(deviceUri)
                .setShowRunningNotification(true));

其中mgr是Download Manager实例,dwnId是返回的唯一ID。我还注册了ACTION_DOWNLOAD_COMPLETE事件。

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

在onDownloadComplete BroadcastReceiver的onReceive()方法中,我获取到了下载ID:

Long dwnId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);

之后我会查询下载管理器以获取下载状态

Cursor c = downloadManager.query(new DownloadManager.Query().setFilterById(dwnId)); c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
对于DownloadManager.STATUS_*常量。
问题在于我收到了相同的downId两次(意味着onReceive方法被调用了两次),一次是成功的DownloadManager.STATUS_SUCCESSFUL状态,一次是失败的DownloadManager.STATUS_FAILED状态,但是这两次是针对同一个dwnId。我一次性发出了下载10个文件的请求,在设备上下载管理器中却显示通知栏左上方的下载计数为12或13。我认为下载管理器在下载文件时存在问题,导致重新启动下载相同的文件。这就是我请求下载的文件数量和实际下载队列中的实际数量之间存在差异的原因。正是因为这个原因,我才会收到相同的DownloadId完成操作两次。如果这是真的,请问如何限制它。我错了吗?造成请求和实际下载之间的数量差异可能是什么原因?为什么广播接收器会收到相同的下载ID两次?请问有人可以告诉我吗?
提前感谢...

在我的情况下有些不同 - onReceive 方法被调用了两次,因为我注册了多个接收器:一个由清单文件注册,一个在 onCreate() 中使用 registerReceiver() 方法注册。 - marioosh
3个回答

38
这是一个已报告的错误,请参见:http://code.google.com/p/android/issues/detail?id=18462 我发现的解决方法是验证下载是否成功,如果没有成功,则放弃该意图或重新排队文件(如果从未下载)...
浪费了几个小时才弄清楚这一点 :(
**编辑:添加代码示例**
/**
 * Check if download was valid, see issue
 * http://code.google.com/p/android/issues/detail?id=18462
 * @param long1
 * @return
 */
private boolean validDownload(long downloadId) {

    Log.d(TAG,"Checking download status for id: " + downloadId);

    //Verify if download is a success
    Cursor c= dMgr.query(new DownloadManager.Query().setFilterById(downloadId));

    if(c.moveToFirst()){            
        int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));

        if(status == DownloadManager.STATUS_SUCCESSFUL){
            return true; //Download is valid, celebrate
        }else{
            int reason = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_REASON));
            Log.d(TAG, "Download not correct, status [" + status + "] reason [" + reason + "]");            
            return false;
        }   
    }               
    return false;                                   
}

完整代码请见:https://github.com/flegare/JAV387_LaboWidget/blob/master/src/com/mobidroid/widgetfact/service/FactService.java


如果我想启动多个并行下载,那么如何识别哪个下载已完成,如果我想取消特定的下载,那么如何存储特定下载的downloadId。如果可能,请告诉我如何做到这一点。 - Mansukh Ahir
我在想:这个问题还存在吗?我在 Nexus 7 (2012) 上看到过类似的情况,使用的是 Android 5.0.1,但它只是偶尔发生,我无法真正确定。这个问题还存在吗,还是我只是在看幽灵? :O - Darwind

1

一个简单的方法来下载您的文件,可以在通知栏中查看下载进度,甚至可以通过在通知栏中点击文件来打开下载完成的文件。

只需调用此方法并传递您的文件名和下载链接即可。

 public void downloadFile(String name, String url){ 
        //download link
        downloadUri = Uri.parse(url);

        DownloadManager.Request request = new DownloadManager.Request(downloadUri);

        //allow download to take place over wifi, mobile network and roaming
        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE ).setAllowedOverRoaming(true);
        request.setAllowedOverRoaming(false);

        //name to show while downloading
        request.setTitle(name);

        //description to show while downloading
        request.setDescription("Downloading " + name);

        //show on navigation
        request.setVisibleInDownloadsUi(true);

        //download path
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS.toString(), "/" + name);

        //file open when item on navigation is clicked
        request.allowScanningByMediaScanner();
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
       long downloadId = downloadManager.enqueue(request);

    }

输出

See the output from image below

您可以在这里了解更多信息。


0

您还可以在广播接收器下添加布尔值或数字条件,以在每个下载任务完成后执行特定的工作。

就像这样

private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        //Fetching the download id received with the broadcast
        long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        //Checking if the received broadcast is for our enqueued download by matching download id
        if (downloadID == id) {
            //firstDownload is a boolean variable and assign each downloadManager as true or false

            if (firstDownload) {
                //First task downlaoded
            } else {
                //Second task downloaded


            }
        }


    };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接