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

リクエストのIntentService合間には強制終了されます。

レシーバーをサービスに登録するときは、登録を解除することはないため、「リーク」します。

レシーバーをに移動し、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

onHandleIntent() は、指定された Intent が受信されるたびに呼び出されます。したがって、BroadcastReceiver を何度も登録します。

したがって、操作が終了したら unregisterReceiver を呼び出すか、 onHandleIntent がトリガーされたときではなく、サービスが作成されたときに BroadcastReceive を登録する必要があります。

于 2012-12-20T09:55:26.993 に答える
0


私の考えは、放送受信機をサービス内に置いたり登録したりしないこと です。放送受信機
からサービスを開始できるのは悪い考えです。
ブロードキャスト レシーバーをサービスに配置/登録する場合は、登録を解除する必要があります。これはより複雑です。

于 2012-12-20T11:50:55.060 に答える