BluetoothAdapter.getDefaultAdapter() 在不在 Activity 中时抛出 RuntimeException

Posted

技术标签:

【中文标题】BluetoothAdapter.getDefaultAdapter() 在不在 Activity 中时抛出 RuntimeException【英文标题】:BluetoothAdapter.getDefaultAdapter() throwing RuntimeException while not in Activity 【发布时间】:2011-08-20 16:55:56 【问题描述】:

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

BluetoothAdapter.getDefaultAdapter();

我得到以下异常:

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

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

【问题讨论】:

查看 android 对此错误的回复:code.google.com/p/android/issues/detail?id=16587 【参考方案1】:

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

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

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

【讨论】:

错误页面上有任何链接吗?【参考方案2】:

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

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

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

【讨论】:

这似乎是个坏主意,除非你真的打算让你的工作线程成为 Looper。 请注意,您应该检查当前线程是否已经调用了Looper.prepare(),如下所示:if (Looper.myLooper() == null) Looper.prepare(); 否则,您将得到一个RuntimeException,因为该函数每个线程只能调用一次。 【参考方案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

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

【参考方案5】:

嗨,Kocus,BluetoothAdapter calss 中没有任何名为 getDefault() 的方法。 应该是BluetoothAdapter.getDefaultAdapter();

follow this link for more information.

【讨论】:

您的示例是从Activity 获取BluetoothAdapter。这不是我想要的。 是的,但我认为 BluetoothAdapter.getDefaultAdapter() 不能从工作线程中调用。它应该来自 UI 线程。 不太明白什么是假Activity。你能提供一些代码吗?

以上是关于BluetoothAdapter.getDefaultAdapter() 在不在 Activity 中时抛出 RuntimeException的主要内容,如果未能解决你的问题,请参考以下文章