Android BluetoothAdapter.getDefaultAdapter()在不在活动中时引发RuntimeException
当我尝试在未处于活动状态,但在Android BluetoothAdapter.getDefaultAdapter()在不在活动中时引发RuntimeException,android,bluetooth,runtimeexception,Android,Bluetooth,Runtimeexception,当我尝试在未处于活动状态,但在TimerTask(在服务中创建)中获取默认蓝牙适配器时,请使用: BluetoothAdapter.getDefaultAdapter(); 我得到以下例外情况: Exception while invoking java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 我的应用程序没有任何活动-因此是否有可能将此适配器
TimerTask
(在服务
中创建)中获取默认蓝牙适配器时,请使用:
BluetoothAdapter.getDefaultAdapter();
我得到以下例外情况:
Exception while invoking java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
我的应用程序没有任何活动-因此是否有可能将此适配器从活动中移除?嗨,Kocus在
BluetoothAdapter calss
中没有任何名为getDefault()
的方法。
它应该是BluetoothAdapter.getDefaultAdapter()代码>
这似乎是安卓系统中的一个缺陷,安卓4.0(冰淇淋三明治)中仍然存在这一缺陷
要解决此问题并能够从工作线程(例如AsyncTask)调用BluetoothAdapter.getDefaultAdapter()
,您只需在主UI线程上调用BluetoothAdapter.getDefaultAdapter()
RuntimeException仅在初始化期间引发,并且BluetoothAdapter.getDefaultAdapter()
仅在您第一次调用它时初始化。对它的后续调用将成功,即使在后台线程中也是如此。在UI
线程中调用BluetoothAdapter.getDefaultAdapter()
可以工作,但不太实用。我用一个假的活动尝试了这种变通方法,但由于我讨厌这种变通方法,我决定阅读错误消息的真正含义,只不过线程没有调用Looper.prepare()
因此,在调用BluetoothAdapter.getDefaultAdapter()
之前调用Looper.prepare()
应该可以在任何地方解决问题,而不仅仅是在UI线程中
到目前为止,对我来说效果很好。注意2.3.x中存在的问题,但在4.x中已经解决了:如果在主应用程序线程以外的任何线程上调用BluetoothAdapter.getDefaultAdapter()
,则该线程必须调用Looper.prepare()
,随后还必须调用Looper.loop()
如果不这样做,至少会导致我遇到一个问题:accept()
将在您第一次尝试连接时成功,但即使在ServerSocket上使用close()
后,连续尝试也不会成功
这是因为在BluetoothAdapter的旧实现中,SDP条目的清理是通过向调用getDefaultAdapter()
的线程上创建的处理程序发送消息来进行的。不确定它是否正确,但我添加了此包装函数:
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您的示例是从活动中获取BluetoothAdapter
。这不是我想要的。是的,但我认为无法从工作线程调用BluetoothAdapter.getDefaultAdapter()。它应该来自UI线程。不真正理解什么是假活动。你能提供一些代码吗?这似乎是个坏主意,除非你真的打算让你的工作线程成为一个循环器。请注意,你应该检查当前线程是否已经像这样调用了Looper.prepare()
:if(Looper.myLooper()==null){Looper.prepare();}
否则,您将得到一个运行时异常
,因为每个线程只能调用一次此函数。bug页面上有任何链接吗?请参阅Android对此bug的响应: