BroadcastReceiver onReceive()被调用两次

9
在我的应用程序中,我正在使用DownloadManager来下载PDF文件。一旦下载完成,通过BroadcastReceiver通知应用程序。但是我的问题是,BroadcastReceiver的onReceive()方法被调用了两次。以下是代码:
在我的列表适配器中,使用for循环下载所选的pdf文件。下载代码编写在另一个类中,如下所示:
    public static void downloadCheat(final SherlockFragmentActivity activity, final String cheatName, String pathOnServer){

    Request request = new Request(
            Uri.parse(ApplicationConstants.CHEAT_DOWNLOAD_SERVER_URL
                    + "/" + pathOnServer + cheatName + ".pdf"));

    if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
        request.setShowRunningNotification(true);
    }
    else {
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    }

    final DownloadManager dm = (DownloadManager) activity
            .getSystemService(Context.DOWNLOAD_SERVICE);
    final long enqueue = dm.enqueue(request);

    BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            long i = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            System.out.println(i);
            if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
                Query query = new Query();
                query.setFilterById(enqueue);
                Cursor c = dm.query(query);

                if (c.moveToFirst()) {
                    int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
                    if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
                    }
                }
                                    //create custom notification
            }
        }
    };

    activity.registerReceiver(receiver, new IntentFilter(
            DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}

我正在尝试为每个PDF下载添加通知。对于HoneyComb及以上版本,下载管理器自带的内部通知可以完美地工作,但对于GingerBread则不行,因此我必须推送自己的自定义通知。因此,我需要确定PDF完全下载完成的确切时间。目前,我能够推送自己的自定义通知,但每次PDF下载时通知会出现两次(因为每个PDF的onReceive()被调用了两次)。请问有人能解释一下为什么onReceive()会被调用两次吗?有没有任何解决方法?另外,有人能否推荐一下如何在我的情况下取消广播接收器的注册?由于上述代码不是Activity的一部分,所以我不确定如何注销接收器。

感谢您阅读本篇文章。


1
在这两个onReceive()调用中,下载ID的值是否相同?可以通过intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)获取downloadid。 - StarPinkER
我检查了一下。当我下载两个PDF文件时,第一次调用onReceive时,两个PDF文件的下载ID相同(first.pdf-> id = 1,second.pdf-> Id = 1)。当第二次自动调用时,下载ID会更改(first.pdf-> Id = 2,second.pdf-> id = 2)。所以基本上我会看到四个打印语句打印1,1,2,2。这些ID是否应该对于每个PDF下载都是唯一的? - andro
我对你的first.pdf->id = 1和second.pdf->id = 1感到困惑。你能否更新你的代码,以便我更好地理解哪个是你的第一个和第二个? - StarPinkER
以上代码块位于一个方法内部。该方法在一个for循环内被调用,该循环运行以下载每个pdf文件。因此,当我尝试下载两个pdf文件时,for循环会调用上述方法两次。上述代码中的sysout按顺序打印下载ID(1,1,2,2)。我认为sysout应该每次仅打印两次具有唯一下载ID的内容。(带有sysout语句的代码更新) - andro
你解决了同样的问题吗? - Pravinsingh Waghela
3个回答

3

通常你会在 onResume() 中注册接收器,而在 onPause() 中取消注册。你是否这样做了呢?


我觉得我可能最初误解了你的意图。你应该能够从 onReceive 中调用 unregisterReceiver。这样做可以实现你想要的效果吗?


我没有在onResume()中注册接收器。广播接收器是为每个要下载的pdf文件创建的。正如我先前提到的,该代码位于一个单独的类中,而不是Activity类的一部分。 - andro
我明白了。我更新了我的回答。如果你从onReceive中注销接收器会发生什么? - yarian
如果我尝试在onReceive()内取消注册接收器,应用程序会崩溃并显示“未注册接收器”的错误。请查看我的更新问题,以更详细地了解我正在尝试实现的内容。感谢您的时间。 - andro
在onPause中取消注册接收器意味着当您从该Activity转到另一个Activity时,您的Activity将无法接收任何广播。非常无用。请在onCreate中注册它们,在onDestroy方法中取消注册。 - Johann
@AndroidDev 这并不是无用的。很多时候,你只关心广播是否在运行给定的活动。如果可以这样做,Android建议您采用这种方式来减少不必要的系统开销。http://developer.android.com/reference/android/content/BroadcastReceiver.html此外,Android建议您在onPause调用时释放系统资源(并特别提到BroadcastReceivers)。 http://developer.android.com/training/basics/activity-lifecycle/pausing.html - yarian

1
你说你正在下载两个pdf文件,但是我只看到你的方法中有一个下载请求。所以我猜测你做的是调用该方法两次。如果是这样的话,你实际上注册了两个接收器来接收 "ACTION_DOWNLOAD_COMPLETE" 事件。
你只需要在onCreate或onStart或其他某些方法中注册一次即可。为了通知目的,你可以使用 "intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)" 来获取下载id,每个下载都有唯一的id。你可以使用这个id来获取已下载文件的信息并制作特定于文件的通知。

是的,我已经调用了这个方法两次(每次下载一个pdf文件)。我这样做的原因是我想为每个pdf文件创建一个单独的通知。有没有办法只使用一个接收器来实现这一点? - andro

1

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