【问题标题】:BluetoothAdapter.getDefaultAdapter() throwing RuntimeException while not in ActivityBluetoothAdapter.getDefaultAdapter() 在不在 Activity 中时抛出 RuntimeException
【发布时间】: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 bluetooth runtimeexception


【解决方案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。你能提供一些代码吗?
      猜你喜欢
      • 2011-10-02
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 2016-12-28
      • 2015-03-15
      • 2011-04-13
      • 2015-01-25
      • 2023-03-24
      相关资源
      最近更新 更多