Question

I try to launch a service to download files from a server. The problem start when I manage the return of the DownloadManager with a BroadcastReceiver, it works if I copy paste in my MainActivity, but in the Service it throws an error. My objective is to download a file (video) and when it finish download the next, but it download only the first and then throws the error.

My class:

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, I dont understand the error:

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)

Thanks for reply.

Was it helpful?

Solution

an IntentService is killed in between requests.

When you are registering your receiver in the service you never unregister it, so you "leak it"

Move your receiver into your Activity, register in onResume and unregister in onPause.

Then every time your register receives a broadcast send an intent to your Service

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

Note: If registering a receiver in your Activity.onResume() implementation, you should unregister it in Activity.onPause(). (You won't receive intents when paused, and this will cut down on unnecessary system overhead). Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back in the history stack.

OTHER TIPS

onHandleIntent() is invoked any time the specified Intent is received. Thus you register your BroadcastReceiver numerous times.

So you either have to call unregisterReceiver when you're finished with your operations, either register the BroadcastReceive when the Service is created and not when the onHandleIntent is triggered.


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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top