android bluetoothadapter类 和bluetoothmanager的区别

_Android蓝牙服务的相关类简介之BluetoothAdapter - 简书
_Android蓝牙服务的相关类简介之BluetoothAdapter
Android蓝牙服务的相关类简介之BluetoothAdapter
BluetoothAdapter
代表了本地设备蓝牙适配器,其作用有:执行基本的蓝牙任务,如初始化设备扫描,查询一系列配对的设备,利用MAC地址链接BluetoothDevice,创建BluetoothServerSocket来监听其他设备的链接请求,开始对Bluetooth LE devices(android4.3后支持的蓝牙类型)的扫描.
如何得到BluetoothAdapter?系统是JELLY_BEAN_MR1(android4.2* API17)或者更低版本,通过BluetoothAdapter.getDefaultAdapter() 的静态方法得到.系统是JELLY_BEAN_MR2(android4.3 API18)或者更高版本,也可以通过下面方法获得
BluetoothManager manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter adapter = manager.getAdapter();
可以肯定的说,获得BluetoothAdapter是蓝牙操作的开端.
获得了BluetoothAdapter后,可以通过getBondedDevices获得已经配对的设备集合;通过startDiscovery()开始设备扫描;创建BluetoothServerSocket监听到来的链接请求(listenUsingRfcommWithServiceRecord(String,UUID));或者利用startLeScan(LeScanCallback callback)来开启扫BLE设备
isEnabled()如果本地蓝牙处在可用状态(例如手机蓝牙开启)就返回true
getState()获得蓝牙状态 一般有BluetoothAdapter.STATE_BLE_ON ,STATE_BLE_TURNING_ON ,STATE_BLE_TURNING_OFF ,STATE_OFF
打开蓝牙设备,这种方式不友好,建议使用下面方法
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent,OPEN_REQUEST_CODE);
这样会有个弹窗提示用户是否开启蓝牙
disable()关闭所有的蓝牙连接后关闭本地蓝牙服务
getAddress()获得蓝牙mac地址
getName()获得蓝牙名称,也就收我们经常设置的蓝牙名称
setName()设置蓝牙名称
startDiscovery()开始发现设备(注意是设备,例如另外一个手机,而不是蓝牙耳机之类的)
getBondedDevices()获取绑定(配对)的设备,测试发现只有手动取消绑定才管用,否则即使关闭蓝牙,间隔一会再打开,这些仍然是绑定的.同时一些绑定的设备(例如手环)用这个方法并没有返回对应的device
startLeScan(LeScanCallback)开始对Bluetooth LE devices设备(蓝牙耳机,手环,电子称等)的扫描.回调函数会把扫描到的设备返回,注意设备会重复被扫描到,最好去掉重复,去重时可以用mac地址,也可以用名称,但是扫描到的Device第一次没有把名称带回,所以获取名称时最好做非空判断
stopLeScan(LeScanCallback)停止扫描Android 蓝牙4.0(BLE)开发实现对蓝牙的写入数据和读取数据
由于最近学校组织了一个移动APP(安卓)设计大赛,自己也学习安卓有一段时间了,就跟同学商量一起去参加试试,一拍即合,然后我们就开始想idea,因为最近可穿戴设备比较火,我们也就想试试。经过商量,我负责Android上位机的开发,同学负责下位机的开发。
上位机的开发主要是低功耗蓝牙BLE的开发,然后就开始找资料,各种找,最后谷歌官方提供的demo还有其他网友基于官方demo修改的demo,结合网上的博客对demo进行理解。刚开始是觉得看起来有点费劲,各种广播,跳来跳去的,刚开始就晕菜了。但是经过三四天的理解,算是把官方的demo理解了。
代码基本上都是官方的demo,只是通过修改获得自己想要的结果,下面就简单介绍一下自己的理解。
一、扫描BLE设备activity
检查该设备是否支持BLE设备,谷歌在Android4.3才开始支持BLE设备(晕死,很长一段时间都没有一台4.3的设备,看着程序修改了也不能测试!)。
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
初始化获得一个bluetoothManager,并检测设备是否支持蓝牙
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();// Checks if Bluetooth is supported on the device.
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
            finish();
           
        }
扫描BLE设备,然后添加到listView里面。
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
public void run() {
mScanning =
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
}, SCAN_PERIOD);
mScanning =
mBluetoothAdapter.startLeScan(mLeScanCallback);
mScanning =
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
二、蓝牙控制的服务BluetoothLeService
在这个服务里面有一个很重要的回调函数BluetoothGattCallback(),蓝牙的数据读取和状态改变都会回调这个函数。
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentA
//收到设备notify值 (设备上报值)
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, &Connected to GATT server.&);
// Attempts to discover services after successful connection.
Log.i(TAG, &Attempting to start service discovery:& +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, &Disconnected from GATT server.&);
broadcastUpdate(intentAction);
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
Log.w(TAG, &onServicesDiscovered received: & + status);
System.out.println(&onServicesDiscovered received: & + status);
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
//读取到值,在这里读数据
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
};在官方的demo中还使用到广播,可能是因为人大神写的,要严谨些。我一开始看的时候就得这有点麻烦,跳转的多麻烦。
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
// This is special handling for the Heart Rate Measurement profile.
Data parsing is
// carried out as per profile specifications:
// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, &Heart rate format UINT16.&);
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, &Heart rate format UINT8.&);
final int heartRate = characteristic.getIntValue(format, 1);
Log.d(TAG, String.format(&Received heart rate: %d&, heartRate));
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
// For all other profiles, writes the data formatted in HEX.对于所有的文件,写入十六进制格式的文件
//这里读取到数据
final byte[] data = characteristic.getValue();
for (int i = 0; i & data. i++) {
System.out.println(&data......& + data[i]);
if (data != null && data.length & 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
//以十六进制的形式输出
stringBuilder.append(String.format(&%02X &, byteChar));
// intent.putExtra(EXTRA_DATA, new String(data) + &\n& + stringBuilder.toString());
intent.putExtra(EXTRA_DATA, new String(data));
sendBroadcast(intent);
}发送了广播之后就肯定有广播接收器,这个是在控制蓝牙的activity中,后面再说。
还有几个重要的函数比如readCharacteristic(BluetoothGattCharacteristic characteristic)函数,读取蓝牙中数据。
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, &BluetoothAdapter not initialized&);
mBluetoothGatt.readCharacteristic(characteristic);
}有readCharacteristic(BluetoothGattCharacteristic characteristic)函数,当然就有writeCharacteristic(BluetoothGattCharacteristic characteristic),向蓝牙中写入数据。
public void writeCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, &BluetoothAdapter not initialized&);
mBluetoothGatt.writeCharacteristic(characteristic);
}另外在这个service中还有其他的一些函数例如初始化initialize()函数、连接蓝牙函数connect(final String address)、断开蓝牙连接函数disconnect()等。
三、蓝牙控制DeviceControlActivity
扫描到蓝牙设备之后就是对蓝牙进行自己需要的控制,比如写数据,读数据,获取设备信息,设备电量等。
在Service中讲到有一个广播,广播接收器就在这个activity中,通过不同的action做出相应的操作。
注册的几种事件
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentF
// Handles various events fired by the Service.处理服务所激发的各种事件
// ACTION_GATT_CONNECTED: connected to a GATT server.连接一个GATT服务
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.从GATT服务中断开连接
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.查找GATT服务
// ACTION_DATA_AVAILABLE: received data from the device.
This can be a result of read
or notification operations.从服务中接受数据
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected =
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected =
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
//发现有可支持的服务
else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
//写数据的服务和characteristic
mnotyGattService = mBluetoothLeService.getSupportedGattServices(UUID.fromString(&0000ffe5-00-fb&));
characteristic = mnotyGattService.getCharacteristic(UUID.fromString(&0000ffe9-00-fb&));
//读数据的服务和characteristic
readMnotyGattService = mBluetoothLeService.getSupportedGattServices(UUID.fromString(&0000ffe0-00-fb&));
readCharacteristic = readMnotyGattService.getCharacteristic(UUID.fromString(&0000ffe4-00-fb&));
//显示数据
else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
//将数据显示在mDataField上
String data = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
System.out.println(&data----& + data);
displayData(data);
在发现了有可支持的服务之后会回调Service中的onServicesDiscovered()函数,并发送广播,在官方的demo中发现了可用的Service之后,就查找该BLE设备支持的所有服务和characteristic,在这里不需要查找所有的服务,只需要向蓝牙写数据和读取数据的Service和characteristic的UUID即可。通过查询低功耗蓝牙(BLE)的数据手册可以得到所需要的UUID。
有了这两个Service和characteristic的UUID,就可以对蓝牙发送数据,并发出通知(当写数据发生改变时发出)。
&span style=&font-size:18&&//写数据的服务和characteristic
mnotyGattService = mBluetoothLeService.getSupportedGattServices(UUID.fromString(&0000ffe5-00-fb&));
characteristic = mnotyGattService.getCharacteristic(UUID.fromString(&0000ffe9-00-fb&));
//读数据的服务和characteristic
readMnotyGattService = mBluetoothLeService.getSupportedGattServices(UUID.fromString(&0000ffe0-00-fb&));
readCharacteristic = readMnotyGattService.getCharacteristic(UUID.fromString(&0000ffe4-00-fb&));&/span&得到这两个Service和characteristic就可以向蓝牙发送数据了。
private void read() {
//mBluetoothLeService.readCharacteristic(readCharacteristic);
//readCharacteristic的数据发生变化,发出通知
mBluetoothLeService.setCharacteristicNotification(readCharacteristic, true);
//Toast.makeText(this, &读成功&, Toast.LENGTH_SHORT).show();
}检测readCharacteristic的数据发生变化,发出通知。
向蓝牙发送数据。
final int charaProp = characteristic.getProperties();
//如果该char可写
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) & 0) {
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification( mNotifyCharacteristic, false);
mNotifyCharacteristic =
//读取数据,数据将在回调函数中
//mBluetoothLeService.readCharacteristic(characteristic);
byte[] value = new byte[20];
value[0] = (byte) 0x00;
if(edittext_input_value.getText().toString().equals(&&)){
Toast.makeText(getApplicationContext(), &请输入!&, Toast.LENGTH_SHORT).show();
WriteBytes = edittext_input_value.getText().toString().getBytes();
characteristic.setValue(value[0],BluetoothGattCharacteristic.FORMAT_UINT8, 0);
characteristic.setValue(WriteBytes);
mBluetoothLeService.writeCharacteristic(characteristic);
Toast.makeText(getApplicationContext(), &写入成功!&, Toast.LENGTH_SHORT).show();
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) & 0) {
mNotifyCharacteristic =
mBluetoothLeService.setCharacteristicNotification(characteristic, true);
edittext_input_value.setText(&&);
}一旦数据发生改变,就会发出通知,通知发出后就会调用下面的函数并发出广播。
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
在广播接收器中接收到广播后,把数据显示在EditText上。下面是测试的两张图片。
demo下载地址:
看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?> 博客详情
一、写在前面的话近来由于项目需求需要搞蓝牙这一块,之前在上家公司带LC(本地连接)组时也做过一点蓝牙,在Android系统中也解过一些bug,但是不够系统,现在正好比较系统的学习蓝牙。二、蓝牙的协议框架&&&&&&&&&&&&&&&&&&&& A2dp& Handset& opp Hid Health Pan Map& Dun... &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |& |&&&& |...&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& CORE Stack Specification&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Host Controller Interface&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& chip三、Android 4.4(Kitkat)上蓝牙的启动流程1.服务启动系统启动时在SystemServer中注册蓝牙服务管理BluetoothManagerService服务:&&&&&&&&&&& if (SystemProperties.get("ro.kernel.qemu").equals("1")) {&&&&&&&&&&&&&&& Slog.i(TAG, "No Bluetooh Service (emulator)");&&&&&&&&&&& } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {&&&&&&&&&&&&&&& Slog.i(TAG, "No Bluetooth Service (factory test)");&&&&&&&&&&& } else if (!context.getPackageManager().hasSystemFeature&&&&&&&&&&&&&&&&&&&&&& (PackageManager.FEATURE_BLUETOOTH)) {&&&&&&&&&&&&&&& Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");&&&&&&&&&&& } else if (disableBluetooth) {&&&&&&&&&&&&&&& Slog.i(TAG, "Bluetooth Service disabled by config");&&&&&&&&&&& } else {&&&&&&&&&&&&&&& Slog.i(TAG, "Bluetooth Manager Service");&&&&&&&&&&&&&&& bluetooth = new BluetoothManagerService(context);&&&&&&&&&&&&&&& ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);&&&&&&&&&&& }其它进程通过binder机制调用该服务,该服务属于综合服务管理类,包括AdapterService的启动、蓝牙适配器Adapter的管理等。2.蓝牙启动模式在4.4上蓝牙的启动模式分两种:QuietEnableMode和普通从“设置”里打开两种方式,前一中方式主要是为了NFC的Handover功能——在传递媒体大文件时nfc会打开蓝牙传送。3.蓝牙关键服务启动和回调处理下面就以在“设置”中打开为例描述下蓝牙的启动流程:1)蓝牙所有的profiles位于上层代码中/packages/apps/Bluetooth目录下,常用的几个profiles包括A2dp、HeadSet、Opp、Hid、Pan等,并且Android 4.4上蓝牙协议栈采用的是BRCM和Google共同开发的bluedroid;2)启动流程涉及代码结构Settings -& Bluetooth -& framework -& bluedroid -& hci -& chip,启动过程是先启动AdapterService并初始化bluedroid,然后启动所有的profile service(A2dpService、HeadsetService等),成功加载所支持的profiles后使能bluedroid给蓝牙上电,蓝牙上电成功后回bluedroid回调类com_android_bluetooth_btservice_AdapterService.cpp的接口static void adapter_state_change_callback(bt_state_t status),通过JNI回调通知AdapterStateMachine更新Adapter状态,并且通知注册到AdapterService上回调:void updateAdapterState(int prevState, int newState){&&&&&&& if (mCallbacks !=null) {&&&&&&&&&&& int n=mCallbacks.beginBroadcast();&&&&&&&&&&& Log.d(TAG,"Broadcasting updateAdapterState() to " + n + " receivers.");&&&&&&&&&&& for (int i=0; i &n;i++) {&&&&&&&&&&&&&&& try {&&&&&&&&&&&&&&&&&&& mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState);&&&&&&&&&&&&&&& }& catch (RemoteException e) {&&&&&&&&&&&&&&&&&&& Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e);&&&&&&&&&&&&&&& }&&&&&&&&&&& }&&&&&&&&&&& mCallbacks.finishBroadcast();&&&&&&& }&&& }mCallbacks该回调是BluetoothManagerService在成功bind到AdapterService时注册的回调mBluetoothCallback:case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:&&&&&&&&&&&&&&& {&&&&&&&&&&&&&&&&&&& if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);&&&&&&&&&&&&&&&&&&& mIsBluetoothServiceConnected =&&&&&&&&&&&&&&&&&&& IBinder service = (IBinder) msg.&&&&&&&&&&&&&&&&&&& synchronized(mConnection) {&&&&&&&&&&&&&&&&&&&&&&& if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {&&&&&&&&&&&&&&&&&&&&&&&&&&& mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& } // else must be SERVICE_IBLUETOOTH&&&&&&&&&&&&&&&&&&&&&&& //Remove timeout&&&&&&&&&&&&&&&&&&&&&&& mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);&&&&&&&&&&&&&&&&&&&&&&& mBinding =&&&&&&&&&&&&&&&&&&&&&&& mBluetooth = IBluetooth.Stub.asInterface(service);&&&&&&&&&&&&&&&&&&&&&&& try {&&&&&&&&&&&&&&&&&&&&&&&&&&& boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1);&&&&&&&&&&&&&&&&&&&&&&&&&&& if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) {&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Log.e(TAG,"IBluetooth.configHciSnoopLog return false");&&&&&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&&&&&& } catch (RemoteException e) {&&&&&&&&&&&&&&&&&&&&&&&&&&& Log.e(TAG,"Unable to call configHciSnoopLog", e);&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&&&&&& if (mConnection.isGetNameAddressOnly()) {&&&&&&&&&&&&&&&&&&&&&&&&&&& //Request GET NAME AND ADDRESS&&&&&&&&&&&&&&&&&&&&&&&&&&& Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);&&&&&&&&&&&&&&&&&&&&&&&&&&& mHandler.sendMessage(getMsg);&&&&&&&&&&&&&&&&&&&&&&&&&&& if (!mEnable)&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&&&&&& mConnection.setGetNameAddressOnly(false);&&&&&&&&&&&&&&&&&&&&&&& //Register callback object&&&&&&&&&&&&&&&&&&&&&&& try {&&&&&&&&&&&&&&&&&&&&&&&&&&& mBluetooth.registerCallback(mBluetoothCallback); //注册Adapter状态变更的callback&&&&&&&&&&&&&&&&&&&&&&& } catch (RemoteException re) {&&&&&&&&&&&&&&&&&&&&&&&&&&& Log.e(TAG, "Unable to register BluetoothCallback",re);&&&&&&&&&&&&&&&&&&&&&&& }...而BluetoothManagerService注册该callback的目的是通知系统所有支持的profiles蓝牙的开启状态,用于更新每个profile和对应profile服务的bind,如通知BluetoothHeadset bind到HeadsetService上,通过binder机制获取HeadsetService的句柄进行相关操作:BluetoothHeadset.javafinal private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =&&&&&&&&&&& new IBluetoothStateChangeCallback.Stub() {&&&&&&&&&&&&&&& public void onBluetoothStateChange(boolean up) {&&&&&&&&&&&&&&&&&&& if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);&&&&&&&&&&&&&&&&&&& if (!up) {&&&&&&&&&&&&&&&&&&&&&&& if (VDBG) Log.d(TAG,"Unbinding service...");&&&&&&&&&&&&&&&&&&&&&&& synchronized (mConnection) {&&&&&&&&&&&&&&&&&&&&&&&&&&& try {&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& mService =&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& mContext.unbindService(mConnection);&&&&&&&&&&&&&&&&&&&&&&&&&&& } catch (Exception re) {&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Log.e(TAG,"",re);&&&&&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&& } else {&&&&&&&&&&&&&&&&&&&&&&& synchronized (mConnection) {&&&&&&&&&&&&&&&&&&&&&&&&&&& try {&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& if (mService == null) {&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& if (VDBG) Log.d(TAG,"Binding service...");&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& doBind();//绑定到HeadsetService&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&&&&&&&&&& } catch (Exception re) {&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Log.e(TAG,"",re);&&&&&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&& }&&&&&&& };那么既然profile要去bind到对应的service上,这些profile对应的Sercice又是什么时候注册的呢?这个很关键,其实在我们使能蓝牙过程中,AdapaterStateMachine处于OffState状态,处理 msg.what == USER_TURN_ONcase USER_TURN_ON:&&&&&&&&&&&&&&&&&& if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_ON");&&&&&&&&&&&&&&&&&& notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON);&&&&&&&&&&&&&&&&&& mPendingCommandState.setTurningOn(true);&&&&&&&&&&&&&&&&&& transitionTo(mPendingCommandState);&&&&&&&&&&&&&&&&&& sendMessageDelayed(START_TIMEOUT, START_TIMEOUT_DELAY);&&&&&&&&&&&&&&&&&& adapterService.processStart();//启动系统支持的所有profiles的services对应调用AdapterService的接口:&&& void processStart() {&&&&&&& if (DBG) debugLog("processStart()");&&&&&&& Class[] supportedProfileServices = Config.getSupportedProfiles();&&&&&&& //Initialize data objects&&&&&&& for (int i=0; i & supportedProfileServices.i++) {&&&&&&&&&&& mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);&&&&&&& }&&&&&&& mRemoteDevices = new RemoteDevices(mPowerManager, this);&&&&&&& mAdapterProperties.init(mRemoteDevices);&&&&&&& if (DBG) {debugLog("processStart(): Make Bond State Machine");}&&&&&&& mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);&&&&&&& mJniCallbacks.init(mBondStateMachine,mRemoteDevices);&&&&&&& //FIXME: Set static instance here???&&&&&&& setAdapterService(this);&&&&&&& //Start profile services&&&&&&& if (!mProfilesStarted && supportedProfileServices.length &0) {&&&&&&&&&&& //Startup all profile services&&&&&&&&&&& setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);&&&&&&& }else {&&&&&&&&&&& if (DBG) {debugLog("processStart(): Profile Services alreay started");}&&&&&&&&&&& mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));&&&&&&& }&&& }以上就是profiles对应服务的注册。3)BluetoothManagerService中处理两个callback:一个是来自BluetoothAdapter实例化时注册的回调mManagerCallback并添加到BluetoothManagerService类private final RemoteCallbackList&IBluetoothManagerCallback& mCallbacks中,该callback主要用于当BluetoothManagerService成功bind到AdapterService时BluetoothDevice获取AdapterService的句柄(BluetoothDevice获取的过程也是向BluetoothAdapter注册回调的机制);另一个来自于各个profile实现类如BluetoothHeadset注册的callback添加到BluetoothManagerService类private final RemoteCallbackList&IBluetoothStateChangeCallback& mStateChangeCallbacks中,用户通知每个profile adapter状态的变化如TURNING_ON、TURN_ON、TURNING_OFF、TURN_OFF等;4)Bluetooth中采用的回调机的地方太多,从Settings中显示部分就多处采用回调来更新UI显示,如BluetoothSettings父类DeviceListPreferenceFragment在onResume()时向LocalBluetoothEventManager中注册callback:@Override&&& public void onResume() {&&&&&&& super.onResume();&&&&&&& if (mLocalManager == null)&&&&&&& mLocalManager.setForegroundActivity(getActivity());&&&&&&& mLocalManager.getEventManager().registerCallback(this);//注册回调&&&&&&& updateProgressUi(mLocalAdapter.isDiscovering());&&& }不仅如此,在JNI和bluedroid的通信中也采用的时回调机制,如com_android_bluetooth_btservice_AdapterService.cpp类在初始化bluedroid时:static bool initNative(JNIEnv* env, jobject obj) {&&& ALOGV("%s:",__FUNCTION__);&&& sJniCallbacksObj = env-&NewGlobalRef(env-&GetObjectField(obj, sJniCallbacksField));&&& if (sBluetoothInterface) {&&&&&&& int ret = sBluetoothInterface-&init(&sBluetoothCallbacks);//初始化回调接口&&&&&&& if (ret != BT_STATUS_SUCCESS) {&&&&&&&&&&& ALOGE("Error while setting the callbacks \n");&&&&&&&&&&& sBluetoothInterface = NULL;&&&&&&&&&&& return JNI_FALSE;&&&&&&& }&&&&&&& if ( (sBluetoothSocketInterface = (btsock_interface_t *)&&&&&&&&&&&&&&&&& sBluetoothInterface-&get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {&&&&&&&&&&&&&&& ALOGE("Error getting socket interface");&&&&&&& }&&&&&&& if ( (sBluetoothMceInterface = (btmce_interface_t *)&&&&&&&&&&&&&&&&& sBluetoothInterface-&get_profile_interface(BT_PROFILE_MAP_CLIENT_ID)) == NULL) {&&&&&&&&&&&&&&& ALOGE("Error getting mapclient interface");&&&&&&& } else {&&&&&&&&&&& if ( (sBluetoothMceInterface-&init(&sBluetoothMceCallbacks)) != BT_STATUS_SUCCESS) {&&&&&&&&&&&&&&& ALOGE("Failed to initialize Bluetooth MCE");&&&&&&&&&&&&&&& sBluetoothMceInterface = NULL;&&&&&&&&&&& }&&&&&&& }&&&&&&& return JNI_TRUE;&&& }&&& return JNI_FALSE;}初次看code时可能会感觉很绕,怎么会那么多回调呀?习惯了就好,这貌似时BRCM代码风格。4.蓝牙关键类管理流程&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& —— A2dpProfile&&&&& & ———— &&&&&&&&&& BluetoothA2dp&&&&&& &————&&&&&&& A2dpService&&&& &—————&&&& A2dpStateMachine&& &————& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |&&&&&&& (注册Listener监听profile的连接状态)&&&&&&&&& (bind到A2dpService)&&&&&&&&&&&& (采用状态机管理)&&&&&&&&&&&&&&&& (jni机制)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& com_android_bluetooth_a2dp &————& blueDroid &————& HCI&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |...&&&&&&&&&&&&&&&&&&&&& —— LocalBluetoothProfile &——&|&&&&&&&&&&&&&&&&&&&& |&&& (管理所有的profiles)&&&&& |&&&&&&&&&&&&&&&&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&& —— HidProfile&&&&& & ———— &&&&&&&&&& BluetoothHid&&&&&& &————&&&&&&& HidService&& &—————& com_android_bluetooth_hid &————& blueDroid &————& HCI&&&&&&&&&&&&&&&&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& (注册Listener监听profile的连接状态)&&&&&&&& (bind到HidService)&&&&&&&&&&&&&& (jni机制)&&&&&&&&&&&&&&&&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& —— AdapterStateMachineLocalBluetoothManager|—— LocalBluetoothApater&&&&& &——&&&&& BluetoothAdapter&& &————&&& BluetoothManagerService &————&&&&&&&&&& AdapterService&&&&&&&&&& & ————& |&&&&&&&&&&&&&&&& 均通过JniCallback回调(上层本地蓝牙管理类)|&&&&& (本地Adpater)&&&& (调用远端的实现)&&&&&&&&&&&&&&& (开启/关闭)&& (蓝牙远端服务管理类)&&&&&&&&& (负责开启/关闭及其它profile服务的管理)&&&&&&& —— BondStateMachine&&&&&&&&&&&&&&&&&&&& |&&&&&&&&&&&&&&&&&&&& |&&&&&&&&&&&&&&&&&&&&& —— BluetoothEventManager&&&&&&&&&&&&&& &————&&&&&&&&&&&&&&&&& CachedBluetoothDeviceManager&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& (注册广播监听蓝牙状态变更、蓝牙设备状态)四、小结本来想采用UML画出流程图以备后查,无奈时间紧张、手头没有环境,唉做项目的人真心悲催啊!待续...
人打赏支持
码字总数 4795
方先生,你好! 看到你写的这篇文章,我感觉非常专业,现在我也在做蓝牙模块,但是关于蓝牙共享网络的模块,我感觉你的文章是可以实现这个功能的,不知道你是不是已经实现了,如果有关于蓝牙共享网络模块的demo能否给我发一个? 或者如果没有能否教我一些相关方面的知识,麻烦加一下我的QQ: 指教我一下. 谢谢!
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥}

我要回帖

更多关于 openbluetoothadapter 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信