BroadcastReceiver в работе

Я пытаюсь запустить службу для загрузки файлов с сервера. Проблема начинается, когда я управляю возвратом DownloadManager с помощью BroadcastReceiver, он работает, если я копирую и вставляю в свою 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)

Спасибо за ответ.


person ƒernando Valle    schedule 20.12.2012    source источник
comment
Итак, вы пропустили вызов unregisterReceiver()?   -  person Egor    schedule 20.12.2012
comment
Похоже, вам не хватает, чтобы отменить регистрацию. после загрузки файла ... и вы можете попробовать AsyncTask для этого ... в doinbackground функции Asynctask вы должны реализовать код загрузки видеофайла.   -  person itsrajesh4uguys    schedule 20.12.2012
comment
Это не работает, я попробую решение Blundell, спасибо за ответ.   -  person ƒernando Valle    schedule 20.12.2012


Ответы (3)


IntentService уничтожается между запросами.

Когда вы регистрируете свой приемник в сервисе, вы никогда не отменяете его регистрацию, поэтому вы «сливаете его».

Переместите приемник в Activity, зарегистрируйтесь в onResume и отмените регистрацию в onPause.

Затем каждый раз, когда ваш регистр получает широковещательную рассылку, отправьте намерение на ваш Service

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

Примечание. Если вы регистрируете получателя в своей реализации Activity.onResume(), вы должны отменить его регистрацию в Activity.onPause(). (Вы не будете получать намерения во время паузы, и это сократит ненужные системные накладные расходы). Не отменяйте регистрацию в Activity.onSaveInstanceState(), потому что это не будет вызываться, если пользователь вернется в стек истории.

person Blundell    schedule 20.12.2012

onHandleIntent() вызывается каждый раз, когда получено указанное намерение. Таким образом, вы многократно регистрируете свой BroadcastReceiver.

Таким образом, вам нужно либо вызвать unregisterReceiver, когда вы закончите свои операции, либо зарегистрировать BroadcastReceive при создании службы, а не при запуске onHandleIntent.

person PeterGriffin    schedule 20.12.2012
comment
Это не работает, я попробую решение Blundell, спасибо за ответ. - person ƒernando Valle; 20.12.2012


Моя идея заключается в том, чтобы не размещать и не регистрировать широковещательный приемник внутри службы. Это плохая идея,
вы можете запустить службу из широковещательного приемника.
Если вы ставите/регистрируете вещательный приемник в сервисе, то вам необходимо его отменить. Это более сложно.

person SIVAKUMAR.J    schedule 20.12.2012