Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to make toast from another thread (sans runOnUiThread)

I need to make an Android toast from a processing thread, which is custom for OpenCV so I can't use runOnUiThread() as suggested here: Android: Toast in a thread.

Most of this code is from the CVCamera sample app. But those unfamiliar, when I select the Surf menu button, the SURFProcessor is called like so:

           else if (item.getTitle().equals("SURF")) {

                   defaultcallbackstack.addFirst(new SURFProcessor());
                   toasts(DIALOG_TUTORIAL_SURF, "");

           }

This Processor thread is run so that when I press the phone's camera button (capturePress = true), an image is taken and processing done. I want to call toasts method as shown:

class SURFProcessor implements NativeProcessor.PoolCallback {

           @Override
           public void process(int idx, image_pool pool, long timestamp,
                           NativeProcessor nativeProcessor) {
                   if(capturePress) {
                           String processMsg = processor.processFeatures(idx, pool, cvcamera.DETECT_SURF);
                           capturePress = false;
                           toasts(PROCESS_MESSAGE, processMsg);
                   }
           }
}

Here is the toasts method, located in the main class extending Activity:

void toasts(int id, String msg) {
           switch (id) {
           case PROCESS_MESSAGE:
                   Toast.makeText(MMRapp.this, msg, Toast.LENGTH_LONG).show();
                   break;
.........

Right now this code gives me an error: "can't create handler inside thread that has not called Looper.prepare()." How do I go about calling the toasts method? Or is it possible to have the toasts method listen for a change in processMsg? If possible, I can get by with sending the processMsg or changing a class variable instead. In essence, I need a String updated from this Processor thread.

Thank you very much, and I will provide more info/code if wanted.
-Tom

like image 849
wrapperapps Avatar asked Mar 22 '11 02:03

wrapperapps


2 Answers

use a handler and a runnable Make the Handler and runnable in the activity:

// these are members in the Activity class
Handler toastHandler = new Handler();
Runnable toastRunnable = new Runnable() {public void run() {Toast.makeText(Activity.this,...).show();}}

then to invoke it from your thread use

toastHandler.post(toastRunnable);

The handler executes the runnable in the thread it was created in.

like image 118
siliconeagle Avatar answered Sep 29 '22 07:09

siliconeagle


Use the overload that fit your needs.

/**
 * Muestra un toast sin necesidad de preocuparse de estar en el hilo de la
 * UI o no.
 *
 * @param mContext
 * @param sMessage
 */
public static void showToast(final Context mContext, final int nMessageId) {
    if (Utils.isUiThread()) {
        Toast.makeText(mContext.getApplicationContext(), nMessageId, Toast.LENGTH_LONG).show();
        return;
    }
    Runnable mRunnableToast = new Runnable() {
        @Override
        public void run() {
            Toast.makeText(mContext.getApplicationContext(), nMessageId, Toast.LENGTH_LONG).show();
        }
    };
    if (mContext instanceof Activity) {
        ((Activity) mContext).runOnUiThread(mRunnableToast);
        return;
    }
    Utils.runOnUiThread(mRunnableToast);
}

/**
 * Muestra un toast sin necesidad de preocuparse de estar en el hilo de la
 * UI o no.
 *
 * @param mContext
 * @param sMessage
 */
public static void showToast(final Context mContext, final CharSequence sMessage) {
    if (Utils.isUiThread()) {
        Toast.makeText(mContext.getApplicationContext(), sMessage, Toast.LENGTH_LONG).show();
        return;
    }
    Runnable mRunnableToast = new Runnable() {
        @Override
        public void run() {
            Toast.makeText(mContext.getApplicationContext(), sMessage, Toast.LENGTH_LONG).show();
        }
    };
    if (mContext instanceof Activity) {
        ((Activity) mContext).runOnUiThread(mRunnableToast);
        return;
    }
    Utils.runOnUiThread(mRunnableToast);
}

public static boolean isUiThread() {
    Looper mCurrentLooper = Looper.myLooper();
    if (mCurrentLooper == null) {
        return false;
    }
    if (mCurrentLooper.equals(Looper.getMainLooper())) {
        return true;
    }
    return false;
}

public static void runOnUiThread(Runnable mRunnable, Context mContext) {
    if (mContext instanceof Activity) {
        runOnUiThread(mRunnable, (Activity) mContext);
    } else {
        Utils.runOnUiThread(mRunnable);
    }
}

public static void runOnUiThread(Runnable mRunnable, View vView) {
    if (Utils.isUiThread()) {
        mRunnable.run();
    } else {
        vView.post(mRunnable);
    }
}

public static void runOnUiThread(Runnable mRunnable, Activity mActivity) {
    if (mActivity != null) {
        mActivity.runOnUiThread(mRunnable);
    } else {
        Utils.runOnUiThread(mRunnable);
    }
}

public static void runOnUiThread(Runnable mRunnable) {
    if (Utils.isUiThread()) {
        mRunnable.run();
    } else {
        Handler mUiHandler = new Handler(Looper.getMainLooper());
        mUiHandler.post(mRunnable);
    }
}
like image 28
Reaper Avatar answered Sep 29 '22 06:09

Reaper