Can’t create handler inside thread that has not called Looper.prepare()

http://www.wangzhanyun.net/index/2011/12/30/cant-create-handler-inside-thread-that-has-not-called-looper-prepare/


问题:
最近在做一个使用SIP通话的客户端。在程序启动的时候要启动蓝牙设备,以连接蓝牙耳机等。

当在一个Thread中调用蓝牙初始化的方法时出现如下的错误:








public static void init() {
if (ba == null ) {
ba = BluetoothAdapter.getDefaultAdapter();
am = (AudioManager) Receiver.mContext.getSystemService(
Context.AUDIO_SERVICE);
}
}

Error Code:

12-30 11:48:21.577: W/System.err(25134): java.lang.RuntimeException: Can’t create handler inside thread that has not called Looper.prepare()
12-30 11:48:21.639: W/System.err(25134): at android.os.Handler.(Handler.java:121)
12-30 11:48:21.639: W/System.err(25134): at android.bluetooth.BluetoothAdapter$1.(BluetoothAdapter.java:853)
12-30 11:48:21.639: W/System.err(25134): at android.bluetooth.BluetoothAdapter.(BluetoothAdapter.java:852)
12-30 11:48:21.639: W/System.err(25134): at android.bluetooth.BluetoothAdapter.getDefaultAdapter(BluetoothAdapter.java:324)
12-30 11:48:21.639: W/System.err(25134): at org.xxxx.media.Bluetooth.init(Bluetooth.java:43)

分析:
报的是一个Android Looper的错误,从字面意思上看是没有调用Looper.prepare()方法。

1. Looper是什么?
Looper又是什么呢? ,其实Android中每一个Thread都跟着一个Looper,Looper可以帮助Thread维护一个消息队列。默认的Thread是没有Looper机制的,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。















class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}

2. 为什么在Thread内调用初始化Bluetooth的方法需要调用Looper.prepare()?
从现象上来看调用ba = BluetoothAdapter.getDefaultAdapter();应该在主线程中进行调用,不应该在工作线程中。
在工作线程中调用可能会由于没有消息队列的管理导致线程不同步。

3. 使用Handler是否可以解决问题,怎么使用?
在主线程中创建Handler,另外一个线程怎样把消息放入主线程的消息队列呢?
答案是通过Handle对象,只要Handler对象以主线程的Looper创建,那么调用Handler的sendMessage等接口,将会把消息放入队列都将是放入主线程的消息队列。并且将会在Handler主线程中调用该handler的handleMessage接口来处理消息。

解决问题:
在Application创建一个Handler的实例,实现handleMessage接口。
在Thread中可以获取Application的实例,调用Application里面的一个方法用Handler send Message的方式执行蓝牙设备初始化的代码。






/*
* in Thread
*/
final App app = (App)mApplication;
app.startSIPEngine();



















/*
* in Application
*/
class App extends Application{
private Handler mApplicationHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
//TODO do some native service register work
BluetoothHelper.init();
}
};
public void startBluetooth(){
mApplicationHandler.sendMessage( new Message());
}
}

参考问题:
Can’t create handler inside thread that has not called Looper.prepare()
深入理解Android消息处理系统——Looper、Handler、Thread


你可能感兴趣的:(thread,工作,android,service,application,Class)