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.
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.