React Native Android Bridge Error: Must be called on main thread

Viewed 2653

I am using the Sumup SDK to create a bridge to React Native. Most of the hard work is done but I am trying to call a specific function to wake up the card reader before a transaction is processed.

The original code I had was this:

@ReactMethod
    public void prepareCardTerminal() {
        SumUpAPI.prepareForCheckout();
    }
}

The RN bridge then calls this function like this:

static prepareCardTerminal() {
    NativeRNSumup.prepareCardTerminal();
}

How ever this gives me a React Native error of:

Must be called on main thread

I read that this could mean it needs to be run on the UI thread so I rewrote the function to be:

@ReactMethod
public void prepareCardTerminal() {
    new Thread(new Runnable() {
        public void run() {
    SumUpAPI.prepareForCheckout();
        }
    });
}

However this doesn't have the intended results (even though it doesn't show any errors).

Any tips would be much appreciated.

Edit: I found a solution to this issue. I used UiThreadUtil:

import com.facebook.react.bridge.UiThreadUtil;
...
    @ReactMethod
public void prepareCardTerminal() {
    UiThreadUtil.runOnUiThread(new Runnable() {
        @Override
        public void run() {
    SumUpAPI.prepareForCheckout();
        }
    });
}
2 Answers

You can do something like this:

@ReactMethod
public void prepareCardTerminal() {

    // Get a handler that can be used to post to the main thread
    Handler mainHandler = new Handler(context.getMainLooper());

    Runnable myRunnable = new Runnable() {
        @Override 
        public void run() {
            SumUpAPI.prepareForCheckout();
        }
    };

    mainHandler.post(myRunnable);

}


Or even simpler:

new Handler(Looper.getMainLooper()).post(new Runnable() {
       @Override
       public void run() {
           SumUpAPI.prepareForCheckout();
       }
});

The answer posted as an edit to the question is correct. The answer by @waquar-ulhaq is technically correct but using UiThreadUtil is way simpler and internally does use a Handler

import com.facebook.react.bridge.UiThreadUtil;
...
    @ReactMethod
public void prepareCardTerminal() {
    UiThreadUtil.runOnUiThread(new Runnable() {
        @Override
        public void run() {
    SumUpAPI.prepareForCheckout();
        }
    });
}
Related