Android蓝牙开发——基础开发(三)-创新互联

蓝牙开发这部分主要以 APP 端调用功能接口为开始,到 Framework 端的调用流程,最后到调用状态机结束,不涉及蓝牙协议栈的开发分析。

创新互联公司主要从事成都网站设计、成都网站制作、外贸网站建设、网页设计、企业做网站、公司建网站等业务。立足成都服务城关,十多年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:028-86922220一、BluetoothAdapter 1、APP获取适配器 蓝牙权限
获取蓝牙适配器

所有的蓝牙 Activity 都是需要 BluetoothAdapter 的。获取 BluetoothAdapter 调用BluetoothAdapter 的静态方法 getDefaultAdapter() 方法。会返回一个表示设备自身的蓝牙适配器(蓝牙无线装置)的 BluetoothAdapter。如果返回 null 则说明该设备不支持蓝牙。

BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();

此时可以调用 BluetoothAdapter 中的各种方法实现蓝牙的基本操作了。 

2、源码分析 BluetoothAdapter 创建及获取
public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
private final IBluetoothManager mManagerService;
 
public static synchronized BluetoothAdapter getDefaultAdapter() {
    if (sAdapter == null) {
        sAdapter = createAdapter(BluetoothManager.resolveAttributionSource(null));
    }
    return sAdapter;
}
 
public static BluetoothAdapter createAdapter(AttributionSource attributionSource) {
    IBinder binder = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
    if (binder != null) {
        return new BluetoothAdapter(IBluetoothManager.Stub.asInterface(binder), attributionSource);
    } else {
        Log.e(TAG, "Bluetooth binder is null");
        return null;
    }
}
 
BluetoothAdapter(IBluetoothManager managerService, AttributionSource attributionSource) {
    mManagerService = Objects.requireNonNull(managerService);
    mAttributionSource = Objects.requireNonNull(attributionSource);
    synchronized (mServiceLock.writeLock()) {
        mService = getBluetoothService(mManagerCallback);
    }
    mLeScanClients = new HashMap();
    mToken = new Binder(DESCRIPTOR);
}

可以看到首先在我们调用的 getDefaultAdapter 方法里去创建 Adapter,然后在 BluetoothAdapter 的构造方法里去调用 getBluetoothService 方法得到 mService,且 mService 的类型为 IBluetooth,这是一个 aidl 的接口,他的实现实在 AdapterService.java 中。

源码位置:

/system/bt/service/common/android/bluetooth/IBluetooth.aidl

/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

继续查看 BluetoothAdapter 源码,很多功能都是通过 mService 去调用 AdapterService 中的方法实现的。

常用方法
方法名描述
enable打开蓝牙功能
disable关闭蓝牙功能
isEnable判断蓝牙功能是否打开
startDiscovery开始搜索周围的蓝牙设备
cancelDiscovery取消搜索操作
isDiscovering判断当前是否正在搜索设备
getBondedDevices获取己绑定的设备列表
setName设置本机的蓝牙名称
getName获取本机的蓝牙名称
getAddress获取本机的蓝牙地址
getRemoteDevice根据蓝牙地址获取远程的蓝牙设备
getState获取本地蓝牙适配器的状态
Adapter属性变更

协议栈蓝牙属性发生变化,通过 AdapterProperties.java 中 adapterPropertyChangedCallback 回调函数通知上来。(此变更为车机侧属性变更)

static final int BT_PROPERTY_BDNAME = 0x01; // 车机蓝牙设备名称修改

static final int BT_PROPERTY_BDADDR = 0x02; // 车机蓝牙设备地址修改

static final int BT_PROPERTY_UUIDS = 0x03; // 车机蓝牙设备支持的协议更新

static final int BT_PROPERTY_CLASS_OF_DEVICE = 0x04; // 不常用

static final int BT_PROPERTY_ADAPTER_SCAN_MODE = 0x07; // 车机蓝牙设备可见性更新

static final int BT_PROPERTY_ADAPTER_BONDED_DEVICES = 0x08; // 返回车机蓝牙设备当前有多少配对成功的设备

static final int BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT = 0x09; // 不常用

二、蓝牙开关On/Off 1、APP调用流程

1、BtSettings App:蓝牙配置和连接管理应用,包括蓝牙界面加载、蓝牙搜索、蓝牙连接、蓝牙重命名等管理功能。

2、BluetoothAdapter:车机侧蓝牙适配器,App 调用 FW 的主要接口文件,提供基本的蓝牙任务接口,例如:启动/取消设备扫描、查询/绑定/移除配对设备、实例化 BluetoothDevice等。

3、BluetoothManagerService:管理蓝牙开关和服务的状态,例如:屏蔽多次点击开关,同步蓝牙状态变更等。

4、AdapterService:BluetoothAdapter 的实现类,FW核心业务逻辑类。实现提供给App的接口。

2、代码流程解析

通过上面的分析,蓝牙 Activity 都是通过调用 BluetoothAdapter 中的方法实现对应功能,所以我们直接从 BluetoothAdapter 开始分析。

1)BluetoothAdapter.enable()

通过 BluetoothAdapter 调用蓝牙开关接口,实现蓝牙开关功能,这里以打开蓝牙的代码为例。

public boolean enable() {
    if (isEnabled()) {
        if (DBG) {
            Log.d(TAG, "enable(): BT already enabled!");
        }
        return true;
    }
    try {
        return mManagerService.enable(mAttributionSource);
    } catch (RemoteException e) {
        Log.e(TAG, "", e);
    }
     return false;
}

可以看到最后调用的是 mManagerService.enable(),通过代码可以看到mManagerService为IBluetoothManager.aidl 接口,所以实际调用的是 BluetoothManagerService.java 的 enable()。

2)BluetoothManagerService.enable()
class BluetoothManagerService extends IBluetoothManager.Stub {
 
    public boolean enable(AttributionSource attributionSource) throws RemoteException {
        final String packageName = attributionSource.getPackageName();
        if (!checkBluetoothPermissions(attributionSource, "enable", true)) {
            return false;
        }
 
        final int callingUid = Binder.getCallingUid();
        final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
        if (!callerSystem && !isEnabled() && mWirelessConsentRequired
                && startConsentUiIfNeeded(packageName,
            callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
            return false;
        }
 
        synchronized (mReceiver) {
            mQuietEnableExternal = false;
            mEnableExternal = true;
            // waive WRITE_SECURE_SETTINGS permission check
            sendEnableMsg(false,
            BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
        }
        return true;
    }
}

这里通过 sendEnableMsg 最终会走到 handleEnable 方法,而 handleEnable 方法我们在蓝牙服务启动流程 中分析最终会调用 AdapterService 中对应的方法。

3)AdapterService.enable()
@Override
public boolean enable(boolean quietMode, AttributionSource attributionSource) {
    AdapterService service = getService();
    if (service == null || !callerIsSystemOrActiveUser(TAG, "enable") || !Utils.checkConnectPermissionForDataDelivery(
        service, attributionSource, "AdapterService enable")) {
        return false;
    }
    return service.enable(quietMode);
}
 
public synchronized boolean enable(boolean quietMode) {
    mQuietmode = quietMode;
    mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);
    return true;
}

可以看到 AdapterService enable() 最后调用了 AdapterState 状态机。

4)AdapterState 状态机迁移流程

源码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterState.java

蓝牙On时,状态机迁移流程: off ->TurningBleOn ->BleOn ->TurningOn ->On

蓝牙Off时,状态机迁移流程:On ->TurningOff ->BleOn ->TurningBleOff ->Off

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


本文名称:Android蓝牙开发——基础开发(三)-创新互联
网页URL:http://scyanting.com/article/jhehi.html