AndroidBLE总结-源码篇(BluetoothLeAdvertir)

更新时间:2023-06-09 00:43:29 阅读: 评论:0

AndroidBLE总结-源码篇(BluetoothLeAdvertir)mBluetoothLeAdvertir.startAdvertising(advertiSettings,
advertiData, myAdvertiCallback);
那么我打算写的BLE总结之源码篇就以此为线索来分析Android BLE FrameWork⽅⾯的东西。
public void startAdvertising(AdvertiSettings ttings,
AdvertiData advertiData, final AdvertiCallback callback) {
startAdvertising(ttings, advertiData, null, callback);
}
public void startAdvertising(AdvertiSettings ttings,
AdvertiData advertiData, AdvertiData scanRespon,
final AdvertiCallback callback) {
synchronized (mLeAdvertirs) {
//该check只是检查mBluetoothAdater是否为null和其状态是否为State_ON
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
if (!mBluetoothAdapter.isMultipleAdvertimentSupported() &&
!mBluetoothAdapter.isPeripheralModeSupported()) {//是否⽀持⼴播和作为外围设备
postStartFailure(callback,
AdvertiCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED);
return;
}
boolean isConnectable = ttings.isConnectable();
if (totalBytes(advertiData, isConnectable) > MAX_ADVERTISING_DATA_BYTES ||
totalBytes(scanRespon, fal) > MAX_ADVERTISING_DATA_BYTES) {
postStartFailure(callback, AdvertiCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
return;
}
if (ainsKey(callback)) {
postStartFailure(callback, AdvertiCallback.ADVERTISE_FAILED_ALREADY_STARTED);
return;
}
IBluetoothGatt gatt;
try {
gatt = BluetoothGatt();
} catch (RemoteException e) {
Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
postStartFailure(callback, AdvertiCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
return;
}
AdvertiCallbackWrapper wrapper = new AdvertiCallbackWrapper(callback, advertiData,
scanRespon, ttings, gatt);
wrapper.startRegisteration();
}
}
⼤家可以看到在startAdvertising内部,⾸先经过了⼀系列的判断,然后包装了⼀个叫作AdvertiCallbackWrapper的类来做发⼴播数据的⾏为。
我们先看⼀下startAdvertising内部都是做了哪些判断:
1.判断蓝⽛是否已经打开,否则抛出异常。
2.判断回调callback是否为空
3.判断当前设备是否⽀持⼴播数据和作为外围设备
4.判断⼴播数据包的长度是否超过了31字节
5.判断⼴播是否已经开始
经过了这5步初步的判断,下⾯来到了最重要的地⽅,BluetoothGatt();获取⼀个引⽤,最终的发送⼴播和停⽌⼴播都是通过这个引⽤来进⾏实现的。这⾥不进⾏展开,因为本⽂主要是对BluetoothLeAdvertir的解读。
论坛 成人
下⾯我们就来看看刚才提到的AdvertiCallbackWrapper,代码如下:
/**
* Bluetooth GATT interface callbacks for advertising.
*/
private class AdvertiCallbackWrapper extends BluetoothGattCallbackWrapper {
private static final int LE_CALLBACK_TIMEOUT_MILLIS = 2000;
private final AdvertiCallback mAdvertiCallback;
private final AdvertiData mAdvertiment;
private final AdvertiData mScanRespon;
private final AdvertiSettings mSettings;奥斯卡奖杯
private final IBluetoothGatt mBluetoothGatt;
/
/ mClientIf 0: not registered
// -1: adverti stopped or registration timeout
// >0: registered and advertising started
private int mClientIf;
private boolean mIsAdvertising = fal;
public AdvertiCallbackWrapper(AdvertiCallback advertiCallback,
AdvertiData advertiData, AdvertiData scanRespon,
AdvertiSettings ttings,
IBluetoothGatt bluetoothGatt) {
mAdvertiCallback = advertiCallback;
mAdvertiment = advertiData;
mScanRespon = scanRespon;
mSettings = ttings;
mBluetoothGatt = bluetoothGatt;
mClientIf = 0;
}
public void startRegisteration() {
synchronized (this) {
if (mClientIf == -1) return;//这个就不解释了
try {
UUID uuid = UUID.randomUUID();
wait(LE_CALLBACK_TIMEOUT_MILLIS);//等待2秒,在过程中会依次回调onClientRegistered和onMultiAdvertiCallback
} catch (InterruptedException | RemoteException e) {
Log.e(TAG, "Failed to start registeration", e);
}
//注册成功并且⼴播成功,加⼊⼴播缓存,以callback为key的Hashmap,callback为⽤户⾃⼰定义的Callback
if (mClientIf > 0 && mIsAdvertising) {
mLeAdvertirs.put(mAdvertiCallback, this);
} el if (mClientIf <= 0) {//注册失败
// Registration timeout, ret mClientIf to -1 so no subquent operations can
// proceed.
if (mClientIf == 0) mClientIf = -1;
// Post internal error if registration failed.
postStartFailure(mAdvertiCallback,
AdvertiCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
} el {//注册成功但⼴播开启失败
// Unregister application if it's already registered but adverti failed.
try {
mBluetoothGatt.unregisterClient(mClientIf);
mClientIf = -1;
} catch (RemoteException e) {
Log.e(TAG, "remote exception when unregistering", e);
}
}
}
}
public void stopAdvertising() {
synchronized (this) {
try {
mBluetoothGatt.stopMultiAdvertising(mClientIf);
wait(LE_CALLBACK_TIMEOUT_MILLIS);
} catch (InterruptedException | RemoteException e) {
Log.e(TAG, "Failed to stop advertising", e);
}
// Adverti callback should have been removed from LeAdvertirs when
// onMultiAdvertiCallback was called. In ca onMultiAdvertiCallback is never
// invoked and wait timeout expires, remove callback here.
英语三级查询if (ainsKey(mAdvertiCallback)) {
}
}
}
/**
* Application interface registered - app is ready to go
*/
@Override
public void onClientRegistered(int status, int clientIf) {
Log.d(TAG, "onClientRegistered() - status=" + status + " clientIf=" + clientIf);
synchronized (this) {
if (status == BluetoothGatt.GATT_SUCCESS) {
try {
if (mClientIf == -1) {//在2秒内未完成注册,超时
// Registration succeeds after timeout, unregister client.
mBluetoothGatt.unregisterClient(clientIf);
} el {//完成注册,并开始⼴播
beyonce listenmClientIf = clientIf;
mBluetoothGatt.startMultiAdvertising(mClientIf, mAdvertiment,
mScanRespon, mSettings);
}大学英语教学大纲
return;
} catch (RemoteException e) {
Log.e(TAG, "failed to start advertising", e);
}
比赛主持人开场白}
// Registration failed.
mClientIf = -1;
notifyAll();
}
}
@Override
public void onMultiAdvertiCallback(int status, boolean isStart,
AdvertiSettings ttings) {
synchronized (this) {
if (isStart) {//⼴播成功时的回调教师节英文祝福语
if (status == AdvertiCallback.ADVERTISE_SUCCESS) {
// Start success
mIsAdvertising = true;
postStartSuccess(mAdvertiCallback, ttings);
} el {
// Start failure.
postStartFailure(mAdvertiCallback, status);
}
} el {//stop 时的回调,⽤来反注册和清除缓存的callback
// unregister client for stop.
try {
mBluetoothGatt.unregisterClient(mClientIf);
mClientIf = -1;
mIsAdvertising = fal;
} catch (RemoteException e) {
Log.e(TAG, "remote exception when unregistering", e);
}
norfolk
}
notifyAll();
}
}
}
private void postStartFailure(final AdvertiCallback callback, final int error) {        mHandler.post(new Runnable() {
@Override
piecewipublic void run() {
}
});
}
private void postStartSuccess(final AdvertiCallback callback,
final AdvertiSettings ttings) {
mHandler.post(new Runnable() {
@Override
public void run() {
}
});
}
AdvertiCallbackWrapper的成员变量mClientIf⾮常重要,在⼴播发送和停⽌的过程中起着重要的作⽤。这⾥先简单的记住该属性的以下特征:
mClientIf=0——>未注册
mClinetIf=-1——>⼴播停⽌或注册超时
mClientIf>0——>已注册并且已经⼴播成功
mClientIf默认值为0
这时我们追踪到startRegisteration这个⽅法了,该⽅法⾥⾯调⽤了registerClient⽅法,经过IPC通信后会回调到onClientRegistered⽅法,继续调⽤到了startMultiAdvertising⽅法,接着触发onMultiAdvertiCallback,成功发送⼴播后,将该AdvertiCallbackWrapper对象加⼊mLeAdvertirs。
这⾥我们需要注意和了解以下⼏点:
1.在调⽤startRegisteration的2秒的时间内,如果没有注册成功且⼴播成功,这次⼴播数据的⾏为均为失败。
2.即使2秒之后onClientRegistered回调,也将视为注册未成功,并进⾏解注册操作。
startAdvertising⽅法就到这,⾄于更底层的细节后续的⽂章会展开,下⾯我们看⼀下其对应的stopAdvertising⽅法
/**
* Stop Bluetooth LE advertising. The {@code callback} must be the same one u in
* {@link BluetoothLeAdvertir#startAdvertising}.
* <p>
* Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
*
* @param callback {@link AdvertiCallback} identifies the advertising instance to stop.
四六级报名官网
*/
public void stopAdvertising(final AdvertiCallback callback) {
synchronized (mLeAdvertirs) {
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
AdvertiCallbackWrapper wrapper = (callback);
if (wrapper == null) return;
wrapper.stopAdvertising();
}
}

本文发布于:2023-06-09 00:43:29,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/138669.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:是否   注册   判断   提到   总结
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图