Reputation: 2591
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() {
)
Upvotes: 3
Views: 15888
Reputation: 1591
Runs the specified action on the UI thread
ActivityName.runOnUiThread(new Runnable() {
public void run()
{
//put your logic here
}
});
Upvotes: 2
Reputation: 36035
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.
Upvotes: 9
Reputation: 1307
I recommend using HandlerThread as it prepares the looper for you.
http://developer.android.com/reference/android/os/HandlerThread.html
Upvotes: 1