java.lang.RuntimeException: невозможно создать обработчик внутри потока, который не вызвал Looper.prepare()

Из Service я пытаюсь запустить другой IntentService, но это дает мне ошибку при попытке передать новый ResultReceiver с новым Handler в качестве параметра.

Не могу понять, почему он дает мне эту ошибку. Пожалуйста помоги!

Строка 797 в SocketIOService, в которой произошла ошибка:

downloadIntent.putExtra(DownloadService.KEY_RECEIVER, new DownloadReceiver(new Handler()));

Ошибка StackTrace

06-05 19:51:10.417: E/AndroidRuntime(7716): FATAL EXCEPTION: Thread-6358
06-05 19:51:10.417: E/AndroidRuntime(7716): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
06-05 19:51:10.417: E/AndroidRuntime(7716):     at android.os.Handler.<init>(Handler.java:121)
06-05 19:51:10.417: E/AndroidRuntime(7716):     at com.walintukai.lfdate.SocketIOService$9.run(SocketIOService.java:797)
06-05 19:51:10.417: E/AndroidRuntime(7716):     at java.lang.Thread.run(Thread.java:856)

Код запуска IntentService

new Thread(new Runnable() {
        public void run() {
            try {
                JSONArray array = json.getJSONArray(0);

                if (array.length() > 0) {
                    ArrayList<String> coverPhotos = new ArrayList<String>();

                    for (int i = 0; i < array.length(); i++) {
                        String id = array.getJSONObject(i).getString(KEY_ID);
                        String name = array.getJSONObject(i).getString(KEY_NAME);
                        String genre = array.getJSONObject(i).getString(KEY_GENRE);

                        String platform = "";
                        JSONArray platformArray = array.getJSONObject(i).getJSONArray(KEY_PLATFORM);
                        for (int p = 0; p < platformArray.length(); p++) {
                            if (p == 0) { platform = platformArray.getString(p); }
                            else { platform = platform + ", " + platformArray.getString(p); }
                        }

                        String coverPhoto = "";
                        JSONArray coverPhotoArray = array.getJSONObject(i).getJSONArray(KEY_COVER_PHOTO);
                        for (int c = 0; c < coverPhotoArray.length(); c++) {
                            if (c == 0) { coverPhoto = coverPhotoArray.getString(c); }
                            else { coverPhoto = coverPhoto + ", " + coverPhotoArray.getString(c); }
                        }

                        Game game = new Game(id, name, genre, platform, coverPhoto);
                        if (!db.doesGameExist(id)) { db.createGame(game); }
                        else { db.updateGame(game); }

                        coverPhotos.add(coverPhoto);

                    }

                    Intent downloadIntent = new Intent(SocketIOService.this, DownloadService.class);
                    downloadIntent.putStringArrayListExtra(DownloadService.KEY_COVER_PHOTOS, coverPhotos);
                    downloadIntent.putExtra(DownloadService.KEY_RECEIVER, new DownloadReceiver(new Handler()));
                    startService(downloadIntent);
                }
            } 
            catch (JSONException e) { e.printStackTrace(); }
        }
    }).start();

Код получателя результатов

private class DownloadReceiver extends ResultReceiver {

    public DownloadReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        super.onReceiveResult(resultCode, resultData);

        if (resultCode == DownloadService.RESULT_FINISHED) {
            Log.i("GAME COVER DOWNLOADS", "COMPLETE");
            if (mOnServiceListener != null) {
                mOnServiceListener.onGameListUpdated();
            }
        }
    }
}

Код IntentService

public class DownloadService extends IntentService {

public static final String KEY_COVER_PHOTOS = "coverPhotos";
public static final String KEY_RECEIVER = "receiver";
public static final int RESULT_FINISHED = 1000;
private static final String URL_GAME_COVER = "https://test.com/images/game_cover/";

public DownloadService(String name) {
    super(name);
}

@Override
protected void onHandleIntent(Intent intent) {
    ArrayList<String> coverPhotos = intent.getStringArrayListExtra(KEY_COVER_PHOTOS);
    ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra(KEY_RECEIVER);

    for (String coverPhoto : coverPhotos) {
        // TODO: implement code to handle multiple photos

        try {
            URL url = new URL(URL_GAME_COVER + coverPhoto);
            URLConnection connection = url.openConnection();
            connection.connect();

            // This will be useful so that you can show a typical 0-100% progress bar
            int fileLength = connection.getContentLength();

            // Download the file
            InputStream input = new BufferedInputStream(url.openStream());
            String filepath = this.getExternalFilesDir(Environment.DIRECTORY_PICTURES).toString() + "/" + coverPhoto;
            OutputStream output = new FileOutputStream(filepath);

            byte data[] = new byte[1024];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();
        } 
        catch (IOException e) { e.printStackTrace(); }

    }

    receiver.send(RESULT_FINISHED, null);

}

}


person The Nomad    schedule 06.06.2014    source источник


Ответы (1)


Какой у тебя тип SocketIOService ? Это действительно Service или нет?

Если вы создаете Handler в общем потоке, который не является Activity или Service, вы должны вызвать Looper.prepare();first, тогда в потоке запускается шина сообщений, и обработчик работает хорошо. Или вы получите исключение, потому что общий поток не имеет шина сообщений (просто бесконечный цикл, в котором потребляются сообщения).

EDIT: ваш обработчик находится не в вашей службе, а в подпотоке (в вашем новом потоке (xxx).start), так что это общий поток, в котором нет шины сообщений .Я думаю, вы должны инициализировать свой обработчик снаружи, а затем использовать его, который является обработчиком Service.

person tianwei    schedule 06.06.2014
comment
SocketIOService расширяет Service. Я только что добавил Looper.prepare(); перед созданием нового ResultReceiver, и теперь он больше не падает, но когда я пытаюсь receiver.send(RESULT_FINISHED, null);, ResultReceiver не подхватывает его. Ты знаешь почему? - person The Nomad; 06.06.2014
comment
Превосходно! Я удалил Looper.prepare(); и создал экземпляр Handler как член Service. Большое спасибо за вашу помощь :) - person The Nomad; 06.06.2014