12

当我不在活动中但在TimerTask(在内部创建Service)中尝试获取默认蓝牙适配器时,使用:

BluetoothAdapter.getDefaultAdapter();

我得到以下异常:

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

我的应用程序没有任何活动 - 那么有没有可能让这个适配器远离活动?

4

5 回答 5

14

这似乎是 Android 中的一个错误,并且在 Android 4.0(冰淇淋三明治)中仍然存在

要解决此问题并能够BluetoothAdapter.getDefaultAdapter()从工作线程(例如 AsyncTask)调用,您所要做的就是BluetoothAdapter.getDefaultAdapter()在主 UI 线程上调用一次(例如在onCreate()您当前活动的内部)。

RuntimeException 仅在初始化期间抛出,并且BluetoothAdapter.getDefaultAdapter()仅在您第一次调用它时进行初始化。对它的后续调用将成功,即使在后台线程中也是如此。

于 2013-02-23T02:42:04.267 回答
6

调用线程有效BluetoothAdapter.getDefaultAdapter()UI但不是很实用。我已经尝试过使用虚假 Activity 的解决方法,但由于我讨厌这样的解决方法,我决定阅读错误消息的真实内容,这只不过是线程没有调用Looper.prepare().

因此Looper.prepare(),在调用之前调用BluetoothAdapter.getDefaultAdapter()应该可以在任何地方解决问题,而不仅仅是在 UI 线程中。

到目前为止对我来说效果很好。

于 2013-04-21T15:43:49.523 回答
3

不知道它有多正确,但我添加了这个包装函数:

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();
}

...并将所有出现的 替换BluetoothAdapter.getDefaultAdapter()getDefaultBluetoothAdapter()。这适用于我:2.2.1、2.3.3、4.0.4、4.3

于 2013-10-30T03:12:55.930 回答
1

注意 2.3.x 中存在的一个陷阱,但在 4.x 中已修复:如果您调用BluetoothAdapter.getDefaultAdapter()主应用程序线程以外的任何线程,则该线程必须调用Looper.prepare()并且随后也必须调用Looper.loop().

如果不这样做,至少会导致我遇到一个问题:accept()第一次尝试连接时会成功,但随后尝试连接不会成功,即使在close()ServerSocket 上使用后也是如此。

发生这种情况是因为在较早的 BluetoothAdapter 实现中,SDP 条目的清理是通过将消息发布到在getDefaultAdapter()调用线程上创建的处理程序来进行的。

于 2013-10-02T01:59:06.577 回答
0

嗨 Kocus 没有调用任何方法getDefault()BluetoothAdapter calss它应该是BluetoothAdapter.getDefaultAdapter();

点击此链接了解更多信息。

于 2011-05-07T11:05:02.677 回答