1

我尝试启动一项服务以从服务器下载文件。当我使用 BroadcastReceiver 管理 DownloadManager 的返回时,问题就开始了,如果我在 MainActivity 中复制粘贴,它会起作用,但在服务中它会引发错误。我的目标是下载一个文件(视频),当它完成下载下一个,但它只下载第一个然后抛出错误。

我的课:

public class VideosDownloader extends IntentService {

    public VideosDownloader() {
        super("VideosDownloader");
    }

    private boolean download = true;
    private final String SERVER_URL = 
            "http://127.0.0.1/42de2533d3b2776e456d62cd0fc3a101/";
    private SharedPreferences preferenceManager;
    final String strPref_Download_ID = "VIDEOS_DOWNLOAD_ID";
    private long enqueue;
    private DownloadManager manager;
    private int count = 0;
    private int count_max = 6;

    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle b = intent.getExtras();
        preferenceManager = PreferenceManager.getDefaultSharedPreferences(this);
        manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
        // THROW THE FIRST TIME:
        DownloadManager.Request request=new DownloadManager.Request(
                Uri.parse(SERVER_URL + "video" + count + ".mp4"));
        request.setDescription("");
        request.setTitle("Downloading");
        request.setDestinationInExternalPublicDir(
                Environment.DIRECTORY_DOWNLOADS, "video" + count + ".mp4");
        request.setShowRunningNotification(true);
        enqueue = manager.enqueue(request);
        Editor PrefEdit = preferenceManager.edit();
        PrefEdit.putLong(strPref_Download_ID, enqueue);
        PrefEdit.commit();
        count++;
        BroadcastReceiver receiver = new BroadcastReceiver() {

            private int progress = 0;

            @Override
            public void onReceive(Context context, Intent intent) {
                if (count < count_max) {
                    DownloadManager.Request request = new DownloadManager.Request(
                            Uri.parse(SERVER_URL + "video" + count + ".mp4"));
                    request.setDescription("");
                    request.setTitle("Downloading...");
                    request.setDestinationInExternalPublicDir(
                            Environment.DIRECTORY_DOWNLOADS, "video" + count
                                    + ".mp4");
                    request.setShowRunningNotification(true);
                    enqueue = manager.enqueue(request);
                    Editor PrefEdit = preferenceManager.edit();
                    PrefEdit.putLong(strPref_Download_ID, enqueue);
                    PrefEdit.commit();
                    Log.d("ENQUEUE", "ENQUEUE: " + enqueue);
                    count++;
                }
            }
        };
        registerReceiver(receiver, new IntentFilter(
                DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }
}

Logcat,我不明白错误:

12-20 10:17:06.859: E/ActivityThread(12324): Service com.example.downloadtest.VideosDownloader has leaked IntentReceiver com.example.downloadtest.VideosDownloader$1@4054a258 that was originally registered here. Are you missing a call to unregisterReceiver()?
    12-20 10:17:06.859: E/ActivityThread(12324): android.app.IntentReceiverLeaked: Service com.example.downloadtest.VideosDownloader has leaked IntentReceiver com.example.downloadtest.VideosDownloader$1@4054a258 that was originally registered here. Are you missing a call to unregisterReceiver()?
    12-20 10:17:06.859: E/ActivityThread(12324):    at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:756)
    12-20 10:17:06.859: E/ActivityThread(12324):    at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:551)
    12-20 10:17:06.859: E/ActivityThread(12324):    at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:836)
    12-20 10:17:06.859: E/ActivityThread(12324):    at android.app.ContextImpl.registerReceiver(ContextImpl.java:823)
    12-20 10:17:06.859: E/ActivityThread(12324):    at android.app.ContextImpl.registerReceiver(ContextImpl.java:817)
    12-20 10:17:06.859: E/ActivityThread(12324):    at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:318)
    12-20 10:17:06.859: E/ActivityThread(12324):    at com.example.downloadtest.VideosDownloader.onHandleIntent(VideosDownloader.java:132)
    12-20 10:17:06.859: E/ActivityThread(12324):    at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:59)
    12-20 10:17:06.859: E/ActivityThread(12324):    at android.os.Handler.dispatchMessage(Handler.java:99)
    12-20 10:17:06.859: E/ActivityThread(12324):    at android.os.Looper.loop(Looper.java:138)
    12-20 10:17:06.859: E/ActivityThread(12324):    at android.os.HandlerThread.run(HandlerThread.java:60)

谢谢您的回复。

4

3 回答 3

0

每当收到指定的 Intent 时都会调用 onHandleIntent()。因此,您多次注册 BroadcastReceiver。

因此,您要么必须在完成操作后调用 unregisterReceiver,要么在创建服务时注册 BroadcastReceive,而不是在触发 onHandleIntent 时注册。

于 2012-12-20T09:55:26.993 回答
0

anIntentService在请求之间被杀死。

当您在服务中注册您的接收器时,您永远不会取消注册它,因此您“泄漏”它

将您的接收器移入您的Activity,在 中注册onResume和取消注册onPause

然后每次您的寄存器收到广播时,都会向您的Service

http://developer.android.com/reference/android/content/BroadcastReceiver.html

注意:如果在 Activity.onResume() 实现中注册接收器,则应在 Activity.onPause() 中取消注册。(暂停时您不会收到意图,这将减少不必要的系统开销)。不要在 Activity.onSaveInstanceState() 中取消注册,因为如果用户移回历史堆栈,则不会调用它。

于 2012-12-20T10:07:38.340 回答
0


My idea is dont put or register broadcast receiver inside the service.It is a bad idea
you can start a service from broad cast receiver.
If you put/register broadcast receiver in the service,then you to need unregister it.It is more complex

于 2012-12-20T11:50:55.060 回答