Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BluetoothAdapter.getDefaultAdapter() throwing RuntimeException while not in Activity

When I'm trying to get default bluetooth adapter while i'm NOT in Activity, but in TimerTask (created inside Service) by using:

BluetoothAdapter.getDefaultAdapter();

I get the following exception:

Exception while invoking java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

My application do not have any activity - so is there any possibility to get this adapter away from Activity?

like image 643
Kocus Avatar asked May 07 '11 10:05

Kocus


3 Answers

This appears to be a bug in Android and still exists in Android 4.0 (Ice Cream Sandwich)

To workaround this and be able to call BluetoothAdapter.getDefaultAdapter() from a worker thread (e.g. AsyncTask), all you have to do is call BluetoothAdapter.getDefaultAdapter() once on the main UI thread (e.g. inside the onCreate() of your current activity).

The RuntimeException is only thrown during initialization, and BluetoothAdapter.getDefaultAdapter() only initializes the first time you call it. Subsequent calls to it will succeed, even in background threads.

like image 165
Toland Hon Avatar answered Nov 13 '22 05:11

Toland Hon


Calling BluetoothAdapter.getDefaultAdapter() in the UI thread works, but is not very practical. I have tried the workaround with a fake Activity, but since I hate such workarounds, I decided to READ what the error message really says and it is nothing more than that the thread didn't call Looper.prepare().

So calling Looper.prepare() just before calling BluetoothAdapter.getDefaultAdapter() should solve the problem anywhere, not just in a UI thread.

Works fine for me so far.

like image 45
Martin Hoza Avatar answered Nov 13 '22 05:11

Martin Hoza


Not sure how correct it is, but I added this wrapper function:

static boolean m_calledLooperAlready = false;

BluetoothAdapter getDefaultBluetoothAdapter() {
    if ( !m_calledLooperAlready ) {
        try  {
            android.os.Looper.prepare();
        } catch ( RuntimeException e ) { e.printStackTrace(); }
        m_calledLooperAlready = true;
    }
    return BluetoothAdapter.getDefaultAdapter();
}

... and replaced all occurrences of BluetoothAdapter.getDefaultAdapter() with getDefaultBluetoothAdapter(). This works ok for me on: 2.2.1, 2.3.3, 4.0.4, 4.3

like image 3
iforce2d Avatar answered Nov 13 '22 06:11

iforce2d