Java Can't create handler inside thread that has not called Looper.prepare()
android, java
Solution
A `Handler` is basically a callback class that Android uses to asynchronously run code when you send it messages of some form. In order for a `Handler` to receive and handle messages in a separate thread from the UI thread, it must keep the thread open. That is where the Looper class comes in. Like in the example of the page, call `Looper.prepare()` at the top of the `run()` method, then call `Looper.loop()` at the bottom. The thread will stay open until you explicitly destroy it. In order to destroy a `Looper` thread, you must have a method in your `Thread` class that calls `Looper.getMyLooper().quit()`.
An example thread class would be something like this:
class LooperThread extends Thread {
public Handler mHandler;
private volatile Looper mMyLooper;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
mMyLooper = Looper.getMyLooper();
Looper.loop();
}
public void killMe(){
mMyLooper.quit();
}
}
Run the thread normally by creating a new object of it.
LooperThread myLooperThread = new LooperThread();
Hold a reference to it. Then call:
myLooperThread.killMe();
Whenever you want the thread to die. This is usually in the `onPause()`, `onStop()`, or `onDestroy()` methods of the Activity.
Please note that a thread of this nature will stay open when the activity is closed so you must kill it before the user quits.
Problem
I saw most of the related questions, but I couldn't find any that fixed my problem. This is my code, and I have no idea what I'm doing wrong. ``` static class NamedFile { public File f; public String name; public String ext; public String path; public BitmapDrawable icon; public NamedFile (File file) { f = file; name = f.getName(); if (f.isFile()) { if (name.indexOf('.') != -1) { ext = name.substring(name.lastIndexOf('.') + 1).trim().toLowerCase(); } else { ext = "unknown"; } } path = f.getAbsolutePath(); if (ext == null) { icon = mFolderIcon; } else { BitmapDrawable i = icons.get(ext); if (i == null) { try { int rid = R.drawable.class.getField(ext).getInt(R.drawable.class); icons.put(ext, new BitmapDrawable(Bitmap.createScaledBitmap(BitmapFactory.decodeResource(res, rid, mOpts), iconSize, iconSize, false))); icon = icons.get(ext); } catch (Exception e1) {} } else { icon = i; } }/* else if (ext.equals("jpeg") || ext.equals("jpg") || ext.equals("bmp") || ext.equals("gif") || ext.equals("png")) { Bitmap b = BitmapFactory.decodeFile(path, mOpts); if (b != null) { icon = new BitmapDrawable(Bitmap.createScaledBitmap(b, iconSize, iconSize, false)); } }*/ if (ext != null && (ext.equals("jpeg") || ext.equals("jpg") || ext.equals("bmp") || ext.equals("gif") || ext.equals("png"))) { /* Bitmap b = BitmapFactory.decodeFile(path, mOpts); if (b != null) { icon = new BitmapDrawable(Bitmap.createScaledBitmap(b, iconSize, iconSize, false)); } */ final Handler handler = new Handler() { @Override public void handleMessage(Message message) { HashMap<String, Object> m = ((HashMap<String, Object>)message.obj); sendThumbnail ((String)m.get("path"), (byte[])m.get("data")); } }; Thread thread = new Thread() { public void writeInt (byte[] buff, int pos, int value) { buff[pos] = (byte)(value >>> 24); buff[pos + 1] = (byte)(value >>> 16); buff[pos + 2] = (byte)(value >>> 8); buff[pos + 3] = (byte)value; } @Override public void run() { try { Bitmap b = BitmapFactory.decodeFile(path, mOpts); if (b.getHeight() > 256 || b.getWidth() > 256) { float r; if (b.getHeight() > b.getWidth()) { r = 128f / b.getHeight(); } else { r = 128f / b.getWidth(); } b = Bitmap.createScaledBitmap(b, (int)(r * b.getWidth()), (int)(r * b.getHeight()), false); byte[] buffer = new byte[b.getWidth() * b.getHeight() * 4 + 8]; writeInt (buffer, 0, b.getWidth()); writeInt (buffer, 4, b.getHeight()); int i = 8; for (int y = 0; y < b.getHeight(); y ++) { for (int x = 0; x < b.getWidth(); x ++) { writeInt (buffer, i, b.getPixel(x, y)); i += 4; } } HashMap<String, Object> msg = new HashMap<String, Object>(); msg.put("path", path); msg.put("data", buffer); Message message = handler.obtainMessage(1, msg); handler.sendMessage(message); } } catch (Exception e) { sendLog (e.toString()); } } }; thread.start(); } if (icon == null) { icon = mFileIcon; } } public NamedFile () { } public NamedFile simpleClone () { final NamedFile nf = new NamedFile(); nf.name = name; nf.ext = ext; nf.path = path; return nf; } } ``` This is nested inside an if statement that is in a static class' constructor function and the static class is in a public class that extends ListActivity. I'm new to Java. Error: ``` 05-01 20:21:58.810: E/AndroidRuntime(584): Uncaught handler: thread AsyncTask #1 exiting due to uncaught exception 05-01 20:21:58.830: E/AndroidRuntime(584): java.lang.RuntimeException: An error occured while executing doInBackground() 05-01 20:21:58.830: E/AndroidRuntime(584): at android.os.AsyncTask$3.done(AsyncTask.java:200) 05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) 05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.FutureTask.setException(FutureTask.java:124) 05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) 05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.FutureTask.run(FutureTask.java:137) 05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068) 05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561) 05-01 20:21:58.830: E/AndroidRuntime(584): at java.lang.Thread.run(Thread.java:1096) 05-01 20:21:58.830: E/AndroidRuntime(584): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 05-01 20:21:58.830: E/AndroidRuntime(584): at android.os.Handler.<init>(Handler.java:121) 05-01 20:21:58.830: E/AndroidRuntime(584): at greg.projects.FileTransfer.FileTransferActivity$NamedFile$1.<init>(FileTransferActivity.java:588) 05-01 20:21:58.830: E/AndroidRuntime(584): at greg.projects.FileTransfer.FileTransferActivity$NamedFile.<init>(FileTransferActivity.java:588) 05-01 20:21:58.830: E/AndroidRuntime(584): at greg.projects.FileTransfer.FileTransferActivity$GesturesLoadTask.doInBackground(FileTransferActivity.java:489) 05-01 20:21:58.830: E/AndroidRuntime(584): at greg.projects.FileTransfer.FileTransferActivity$GesturesLoadTask.doInBackground(FileTransferActivity.java:1) 05-01 20:21:58.830: E/AndroidRuntime(584): at android.os.AsyncTask$2.call(AsyncTask.java:185) 05-01 20:21:58.830: E/AndroidRuntime(584): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 05-01 20:21:58.830: E/AndroidRuntime(584): ... 4 more ``` (FileTransferActivity.java:588 is `final Handler handler = new Handler() {`)