【问题标题】:Broadcast receiver IntentReceiverLeaked广播接收器 IntentReceiverLeaked
【发布时间】:2018-06-29 02:01:31
【问题描述】:

我正在尝试下载一个文件,下载后想在数据库中更新它,但在我的意图中,服务广播接收器正在创建这个问题:

android.app.IntentReceiverLeaked: Service com.dev.newtermain.services.intent_service.DownloadService has leaked IntentReceiver com.dev.newtermain.services.intent_service.DownloadService$DownloadCompleteReceiver@d4fdde9 that was originally registered here. Are you missing a call to unregisterReceiver()?
    at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:969)
    at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:731)
    at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1179)
    at android.app.ContextImpl.registerReceiver(ContextImpl.java:1159)
    at android.app.ContextImpl.registerReceiver(ContextImpl.java:1153)
    at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:554)
    at com.dev.newtermain.services.intent_service.DownloadService.onStartCommand(DownloadService.java:70)
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3228)
    at android.app.ActivityThread.-wrap17(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1591)
    at android.os.Handler.dispatchMessage(Handler.java:111)
    at android.os.Looper.loop(Looper.java:207)
    at android.app.ActivityThread.main(ActivityThread.java:5769)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)

这是我的意图服务代码:

public class DownloadService extends IntentService {
 public DownloadService() {
    super("Download Service");
}

Long downloadId;
private DownloadManager downloadManager;

@Override public void onCreate() {
    super.onCreate();
    downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
    completeReceiver = new DownloadCompleteReceiver();
}

@Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    onHandleIntent(intent);
    this.intent = intent;
    return START_STICKY;
}

@Override
protected void onHandleIntent(Intent intent) {

    String key = intent.getStringExtra(DOWNLOAD_KEY);
    messageId = intent.getStringExtra(MESSAGE_ID);
    mReactionId = intent.getStringExtra(REACTION_ID);
    int messageType = intent.getIntExtra(MESSAGE_TYPE, 3);
    initDownload(key, messageType);
}

private void initDownload(String key, int messageType) {
    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
    request.addRequestHeader("Authorization", SharedPref.User.getToken());

    // In order for this if to run, you must use the Android 3.2 to
    // compile your app
    request.allowScanningByMediaScanner();
    request.setAllowedOverMetered(true);
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    request.setDestinationInExternalPublicDir(path, fileName);

    // Get download service and enqueue file
    downloadId = downloadManager.enqueue(request);

    Logs.e("file download", "downloading begin");
    IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
    this.registerReceiver(completeReceiver, intentFilter);
}

public class DownloadCompleteReceiver extends BroadcastReceiver {
    public DownloadCompleteReceiver() {
    }

    @Override public void onReceive(Context context, Intent intent) {
        Logs.e("file download", "broadcast received");
        DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId);
        Cursor cursor = downloadManager.query(query);
        if (cursor.moveToFirst()) {
            int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
            int status = cursor.getInt(columnIndex);
            cursor.close();

            switch (status) {
                case DownloadManager.STATUS_SUCCESSFUL:
                    Logs.e("file download", "download successful");
                    updateDb(fileName, messageId, Id);
                    break;
                case DownloadManager.STATUS_FAILED:
                    Logs.e("file download", "download Fail");
                    break;
                case DownloadManager.STATUS_PENDING:
                    Logs.e("file download", "STATUS_PENDING");
                    break;
                case DownloadManager.STATUS_RUNNING:
                    Logs.e("file download", "STATUS_RUNNING");
                    break;
            }
        }
    }
}

@Override public void onDestroy() {
    Logs.e("file download", "stopping service");
    this.unregisterReceiver(completeReceiver);
    downloadManager.remove(downloadId);
    super.onDestroy();
}

正如广播接收器的文档所暗示的,我正在注销广播接收器,但我不明白为什么会出现这个问题。

编辑

我应用了所有建议的答案,新问题是如果我添加广播接收器,它将给出成功响应但不保存文件,但是当我成功删除广播接收器文件下载时

【问题讨论】:

  • 删除此行后 downloadManager.remove(downloadId) 一切正常,因为它删除了下载的文件,任何人都知道如何删除下载管理器的下载通知

标签: android android-broadcast android-broadcastreceiver android-intentservice


【解决方案1】:

只需用更改广播注销函数的位置来替换您的代码

@Override public void onDestroy() {
    downloadManager.remove(downloadId);
    this.unregisterReceiver(completeReceiver);
    super.onDestroy();
}

【讨论】:

  • 嗨@Dhaval我已经尝试过它没有发送任何异常但问题是如果我删除广播接收器文件是否正确保存并且当我添加广播接收器时没有得到任何文件只是成功响应跨度>
【解决方案2】:

问题:

您遇到此问题的原因是因为IntentService 在下载完成之前运行完成,并且您的DownloadCompleteReceiver 仍处于注册状态。

downloadId = downloadManager.enqueue(request); 不会以同步方式下载。结果,IntentService 运行完成。

解决方法

如果您必须接收状态,您可以启动 ForegroundService 而不是IntentService,然后注册接收器。在您的 Service 的onDestory() 中,取消注册接收器。

【讨论】:

  • 嗨@Sagar 感谢前台服务的快速回复,没有例外,但文件没有正确下载,它总是说下载成功
  • @VirendraVarma 您只是在听来自 DownloadManager 的响应,对吗?可能问题出在您的文件或服务器上。成功响应来自 DownloadManager。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多