1.简介
1.1.页面图
1.2.问题
- 上下滑动列表的时候,有几率会卡顿,滑动无效,查找下原因。
- 自己写个demo监听蓝牙相关的广播,发现每次ACTION_DISCOVERY_STARTED的前后会卡。
- 首先startDiscovery()方法每次时间是12s左右,所以settings里会监听ACTION_DISCOVERY_FINISHED,完事重新开始扫描,参考3.9
1.3.解决
>1.简单处理
- 最开始,我以为startDiscovery是阻塞的,会卡是它引起的,所以把3.7的代码放入后台线程,结果无效。
- 然后就看了下3.6,蓝牙设备创建的选项就是这个类。
- 首先,参考3.1里的配置,我们只显示带名字的蓝牙设备,而扫描出来的大部分不带名字的,那么完全没必要创建3.6的对象,然后在内部判断显示隐藏。
- 参考3.6.1,设备注册了回调,再看小节8,里边蓝牙设备稍微发生点变化就会回调,太频繁。
- 最终修改的3.5.1的方法,对于不用显示的蓝牙设备,不再创建对象。
void createDevicePreference(CachedBluetoothDevice cachedDevice) {
if (mDeviceListGroup == null) {
Log.w(TAG, "Trying to create a device preference before the list group/category "
+ "exists!");
return;
}
//最开始修改的地方,新加的逻辑,不需要显示的不创建对象
//扫描结果十来个没问题,如果几十个还是会卡。
if (!mShowDevicesWithoutNames && !cachedDevice.hasHumanReadableName()) {
Log.w(TAG, "mytest====no need add device : mShowDevicesWithoutNames is false, and hasHumanReadableName is false==="+cachedDevice);
return;
}
>2.进一步
- 补充1里是根据实际情况处理的,毕竟有名字的蓝牙扫描结果不会太多,那么如果没名字的也显示的话,那补充1的修改不就无用了吗?
- 其实卡壳的根源还是选项刷新太频繁了。参考3.6.2的回调,根据小节8,它的回调是非常频繁的,尤其是重新开始扫描的时候,所以过滤下刷新条件。
private class BluetoothDevicePreferenceCallback implements CachedBluetoothDevice.Callback {
@Override
public void onDeviceAttributesChanged() {
//只处理名字发生变化的情况,其他的不处理。
if(nameChanged()){
onPreferenceAttributesChanged();}
}
}
private String mOldDeviceName;//构造方法里初始化
private boolean nameChanged() {
String currentName = mCachedDevice.getName();
boolean same = TextUtils.equals(mOldDeviceName, currentName);
if (!same) {
mOldDeviceName = currentName;
}
return !same;
}
2.BluetoothPairingDetail.java
public class BluetoothPairingDetail extends DeviceListPreferenceFragment implements
Indexable {
2.1.getPreferenceScreenResId
protected int getPreferenceScreenResId() {
return R.xml.bluetooth_pairing_detail;
}
>1.bluetooth_pairing_detail.xml
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/bluetooth_pairing_pref_title">
<Preference
android:key="bt_pair_rename_devices"
android:title="@string/bluetooth_device_name"
android:summary="@string/summary_placeholder"
settings:controller="com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController"/>
<!--蓝牙列表数据都是添加到这里的-->
<com.android.settings.bluetooth.BluetoothProgressCategory
android:key="available_devices"
android:title="@string/bluetooth_paired_device_title"/>
<com.android.settingslib.widget.FooterPreference/>
</PreferenceScreen>
2.2.onStart
public void onStart() {
super.onStart();
if (mLocalManager == null){
return;
}
updateBluetooth();//补充1
//是否正在扫描中
mAvailableDevicesCategory.setProgress(mBluetoothAdapter.isDiscovering());
}
>1.updateBluetooth
void updateBluetooth() {
if (mBluetoothAdapter.isEnabled()) {
//可用的话,更新数据
updateContent(mBluetoothAdapter.getState());
} else {//不可用的话,打开蓝牙
mBluetoothAdapter.enable();
}
}
>2.updateContent
void updateContent(int bluetoothState) {
switch (bluetoothState) {
case BluetoothAdapter.STATE_ON:
mDevicePreferenceMap.clear();//清除缓存数据
mBluetoothAdapter.enable();
//添加蓝牙设备列表,参考3.4
addDeviceCategory(mAvailableDevicesCategory,
R.string.bluetooth_preference_found_media_devices,
BluetoothDeviceFilter.ALL_FILTER, mInitialScanStarted);
//底部提示文字处理
updateFooterPreference(mFooterPreference);
//这个就是个广播
mAlwaysDiscoverable.start();
enableScanning();//补充3
break;
case BluetoothAdapter.STATE_OFF:
finish();//关闭页面
break;
}
}
>3.enableScanning
void enableScanning() {
//初始化一次
if (!mInitialScanStarted) {
//首次初始化,清空数据
if (mAvailableDevicesCategory != null) {
removeAllDevices();
}
mLocalManager.getCachedDeviceManager().clearNonBondedDevices();
mInitialScanStarted = true;
}
super.enableScanning();
}
2.3.onStop
public void onStop() {
super.onStop();
if (mLocalManager == null){
return;
}
//取消广播监听
mAlwaysDiscoverable.stop();
//断开连接
disableScanning();
}
3.DeviceListPreferenceFragment
public abstract class DeviceListPreferenceFragment extends
RestrictedDashboardFragment implements BluetoothCallback {
3.1.构造方法
private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY =
"persist.bluetooth.showdeviceswithoutnames";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLocalManager = Utils.getLocalBtManager(getActivity());
if (mLocalManager == null) {
return;
}
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//默认是不显示没有名字的蓝牙设备的
mShowDevicesWithoutNames = SystemProperties.getBoolean(
BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false);
initPreferencesFromPreferenceScreen();
mDeviceListGroup = (PreferenceCategory) findPreference(getDeviceListKey());
}
3.2.onStart
public void onStart() {
super.onStart();
if (mLocalManager == null || isUiRestricted()) return;
mLocalManager.setForegroundActivity(getActivity());
//注册蓝牙相关的各种回调
mLocalManager.getEventManager().registerCallback(this);
}
3.3.onStop
public void onStop() {
super.onStop();
if (mLocalManager == null || isUiRestricted()) {
return;
}
removeAllDevices();//清除数据
mLocalManager.setForegroundActivity(null);
//取消注册
mLocalManager.getEventManager().unregisterCallback(this);
}
>1.removeAllDevices
void removeAllDevices() {
mDevicePreferenceMap.clear();
mDeviceListGroup.removeAll();
}
3.4.addDeviceCategory
public void addDeviceCategory(PreferenceGroup preferenceGroup, int titleId,
BluetoothDeviceFilter.Filter filter, boolean addCachedDevices) {
cacheRemoveAllPrefs(preferenceGroup);
//默认的title被改了
preferenceGroup.setTitle(titleId);
mDeviceListGroup = preferenceGroup;
//添加缓存数据
if (addCachedDevices) {
setFilter(BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER);
addCachedDevices();
}
setFilter(filter);
preferenceGroup.setEnabled(true);
removeCachedPrefs(preferenceGroup);
}
3.5.onDeviceAdded
- 3.2注册的回调里有这个方法,发现新的设备后
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
if (mDevicePreferenceMap.get(cachedDevice) != null) {
//已经添加了
return;
}
//蓝牙已经关闭了
if (mBluetoothAdapter.getState() != BluetoothAdapter.STATE_ON) return;
if (mFilter.matches(cachedDevice.getDevice())) {
ThreadUtils.postOnBackgroundThread(() -> createDevicePreference(cachedDevice));//补充1
}
}
>1.createDevicePreference
这里就是添加新的蓝牙设备选项
void createDevicePreference(CachedBluetoothDevice cachedDevice) {
if (mDeviceListGroup == null) {
//容器还不存在
return;
}
String key = cachedDevice.getDevice().getAddress();
BluetoothDevicePreference preference = (BluetoothDevicePreference) getCachedPreference(key);
if (preference == null) {
//参考3.6
preference = new BluetoothDevicePreference(getPrefContext(), cachedDevice,
mShowDevicesWithoutNames, BluetoothDevicePreference.SortType.TYPE_FIFO);
preference.setKey(key);
preference.hideSecondTarget(true);
//加入容器
mDeviceListGroup.addPreference(preference);
}
initDevicePreference(preference);//空实现
//放入缓存
mDevicePreferenceMap.put(cachedDevice, preference);
}
3.6.BluetoothDevicePreference
蓝牙设备选项用的preference
>1.onPreferenceAttributesChanged
void onPreferenceAttributesChanged() {
//...
//没有名字可以显示标志为true,或者有名字 才可见
setVisible(mShowDevicesWithoutNames || mCachedDevice.hasHumanReadableName());
// This could affect ordering, so notify that
if (mNeedNotifyHierarchyChanged) {
notifyHierarchyChanged();
}
}
>2.BluetoothDevicePreferenceCallback
此回调参考小节8.1.1,蓝牙设备属性变化就会调用,有时候很频繁
private class BluetoothDevicePreferenceCallback implements CachedBluetoothDevice.Callback {
@Override
public void onDeviceAttributesChanged() {
onPreferenceAttributesChanged();
}
}
构造方法里注册的
mCachedDevice = cachedDevice;
//这里
mCallback = new BluetoothDevicePreferenceCallback();
mCachedDevice.registerCallback(mCallback);
3.7.enableScanning
void enableScanning() {
if (!mScanEnabled) {
startScanning();//补充1
mScanEnabled = true;
}
}
>1.startScanning
- 蓝牙扫描一次是12s,参考3.9的回调。结束后会重新扫描
void startScanning() {
if (!mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.startDiscovery();
}
}
3.8.disableScanning
void disableScanning() {
if (mScanEnabled) {
stopScanning();//补充1
mScanEnabled = false;
}
}
>1.stopScanning
void stopScanning() {
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
}
3.9.onScanningStateChanged
- ACTION_DISCOVERY_STARTED 的时候,回调为true
- ACTION_DISCOVERY_FINISHED 的时候,回调为false
- 所以每次扫描结束,就会重新开始扫描
public void onScanningStateChanged(boolean started) {
if (!started && mScanEnabled) {
startScanning();//参考3.7.1
}
}
4.BluetoothAdapter
4.1.getDefaultAdapter
public static synchronized BluetoothAdapter getDefaultAdapter() {
if (sAdapter == null) {
sAdapter = createAdapter(AttributionSource.myAttributionSource());
}
return sAdapter;
}
>1.myAttributionSource
public static @NonNull AttributionSource myAttributionSource() {
final AttributionSource globalSource = ActivityThread.currentAttributionSource();
if (globalSource != null) {
return globalSource;
}
int uid = Process.myUid();
if (uid == Process.ROOT_UID) {
uid = Process.SYSTEM_UID;
}
try {
return new AttributionSource.Builder(uid)
.setPackageName(AppGlobals.getPackageManager().getPackagesForUid(uid)[0])
.build();
} catch (Exception ignored) {
}
throw new IllegalStateException("Failed to resolve AttributionSource");
}
4.2.isDiscovering
是否还在扫描中,
- getSyncTimeout:超时时间是5s,参考BluetoothUtils.java
public boolean isDiscovering() {
if (getState() != STATE_ON) {//蓝牙未打开
return false;
}
try {
mServiceLock.readLock().lock();
if (mService != null) {
final SynchronousResultReceiver<Boolean> recv = SynchronousResultReceiver.get();
//参考4.3.1
mService.isDiscovering(mAttributionSource, recv);
//5.3,等待结果并返回
return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false);
}
} catch (RemoteException | TimeoutException e) {
} finally {
mServiceLock.readLock().unlock();
}
return false;
}
4.3.AdapterService.java
>1.isDiscovering
public void isDiscovering(AttributionSource source, SynchronousResultReceiver receiver) {
try {//参考5.1
receiver.send(isDiscovering(source));
} catch (RuntimeException e) {
receiver.propagateException(e);
}
}
private boolean isDiscovering(AttributionSource attributionSource) {
AdapterService service = getService();
if (service == null
|| !callerIsSystemOrActiveOrManagedUser(service, TAG, "isDiscovering")
|| !Utils.checkScanPermissionForDataDelivery(
service, attributionSource, "AdapterService isDiscovering")) {
return false;
}
return service.mAdapterProperties.isDiscovering();
}
>2.onCreate
public void onCreate() {
super.onCreate();
initMetricsLogger();
debugLog("onCreate()");
mDeviceConfigListener.start();
mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper());
mRemoteDevices.init();
clearDiscoveringPackages();
mBinder = new AdapterServiceBinder(this);
mAdapter = BluetoothAdapter.getDefaultAdapter();
//看这里
mAdapterProperties = new AdapterProperties(this);
4.4.startDiscovery
public boolean startDiscovery() {
android.util.SeempLog.record(58);
if (getState() != STATE_ON) {
return false;
}
try {
mServiceLock.readLock().lock();
if (mService != null) {
final SynchronousResultReceiver<Boolean> recv = SynchronousResultReceiver.get();
mService.startDiscovery(mAttributionSource, recv);
return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false);
}
} catch (RemoteException | TimeoutException e) {
} finally {
mServiceLock.readLock().unlock();
}
return false;
}
4.5.cancelDiscovery
public boolean cancelDiscovery() {
if (getState() != STATE_ON) {
return false;
}
try {
mServiceLock.readLock().lock();
if (mService != null) {
final SynchronousResultReceiver<Boolean> recv = SynchronousResultReceiver.get();
mService.cancelDiscovery(mAttributionSource, recv);
return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false);
}
} catch (RemoteException | TimeoutException e) {
} finally {
mServiceLock.readLock().unlock();
}
return false;
}
4.6.getScanMode
public int getScanMode() {
if (getState() != STATE_ON) {
return SCAN_MODE_NONE;
}
try {
mServiceLock.readLock().lock();
if (mService != null) {
SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get();
mService.getScanMode(mAttributionSource, recv);
return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(SCAN_MODE_NONE);
}
} catch (TimeoutException e) {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} finally {
mServiceLock.readLock().unlock();
}
return SCAN_MODE_NONE;
}
5.SynchronousResultReceiver
5.1.send
public void send(@Nullable T resultData) {
//参考5.2
complete(new Result<>(resultData));
}
5.2.complete
private void complete(Result<T> result) {
if (mIsCompleted) {
throw new IllegalStateException("Receiver has already been completed");
}
mIsCompleted = true;
if (mLocal) {
getFuture().complete(result);
} else {
final ISynchronousResultReceiver rr;
synchronized (this) {
rr = mReceiver;
}
if (rr != null) {
try {
rr.send(result);
} catch (RemoteException e) {
}
}
}
}
5.3.awaitResultNoInterrupt
public @NonNull Result<T> awaitResultNoInterrupt(@NonNull Duration timeout)
throws TimeoutException {
final long startWaitNanoTime = SystemClock.elapsedRealtimeNanos();
Duration remainingTime = timeout;
while (!remainingTime.isNegative()) {
try {
//这种阻塞式的
Result<T> result = getFuture().get(remainingTime.toMillis(), TimeUnit.MILLISECONDS);
synchronized (sLock) {
releaseLocked();
return result;
}
} catch (ExecutionException e) {
// This will NEVER happen.
throw new AssertionError("Error receiving response", e);
} catch (InterruptedException e) {
remainingTime = timeout.minus(
Duration.ofNanos(SystemClock.elapsedRealtimeNanos() - startWaitNanoTime));
}
}
synchronized (sLock) {
releaseLocked();
}
throw new TimeoutException();
}
6.BluetoothEventManager
蓝牙相关的广播都在这个类里注册监听的。
6.1.构造方法
BluetoothEventManager(LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager, Context context,
android.os.Handler handler, @Nullable UserHandle userHandle) {
mLocalAdapter = adapter;
mDeviceManager = deviceManager;
mAdapterIntentFilter = new IntentFilter();
mProfileIntentFilter = new IntentFilter();
mHandlerMap = new HashMap<>();
mContext = context;
mUserHandle = userHandle;
mReceiverHandler = handler;
// Bluetooth on/off broadcasts
addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler());//补充1
// Generic connected/not broadcast
addHandler(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED,
new ConnectionStateChangedHandler());
// Discovery broadcasts,参考补充2
addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED,
new ScanningStateChangedHandler(true));
addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED,
new ScanningStateChangedHandler(false));
//补充3
addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());
//蓝牙名字或者别名改变,参考补充4
addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler());
addHandler(BluetoothDevice.ACTION_ALIAS_CHANGED, new NameChangedHandler());
// Pairing broadcasts,配对状态变化,补充5
addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, new BondStateChangedHandler());
>1.AdapterStateChangedHandler
蓝牙状态变化会走,比如打开关闭
private class AdapterStateChangedHandler implements Handler {
public void onReceive(Context context, Intent intent, BluetoothDevice device) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR);
mLocalAdapter.setBluetoothStateInt(state);
for (BluetoothCallback callback : mCallbacks) {
callback.onBluetoothStateChanged(state);
}
mDeviceManager.onBluetoothStateChanged(state);
}
}
>2.ScanningStateChangedHandler
扫描开始,扫描结束会走这里
private class ScanningStateChangedHandler implements Handler {
private final boolean mStarted;
ScanningStateChangedHandler(boolean started) {
mStarted = started;
}
public void onReceive(Context context, Intent intent, BluetoothDevice device) {
for (BluetoothCallback callback : mCallbacks) {
callback.onScanningStateChanged(mStarted);
}
mDeviceManager.onScanningStateChanged(mStarted);
}
}
>3.DeviceFoundHandler
扫描到设备后执行
private class DeviceFoundHandler implements Handler {
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
final boolean isCoordinatedSetMember =
intent.getBooleanExtra(BluetoothDevice.EXTRA_IS_COORDINATED_SET_MEMBER, false);
//参考7.1
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
if (cachedDevice == null) {
cachedDevice = mDeviceManager.addDevice(device);//参考7.2
} else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
&& !cachedDevice.getDevice().isConnected()) {
//已绑定,未连接的设备,直接回调处理
dispatchDeviceAdded(cachedDevice);
}
cachedDevice.setRssi(rssi);
cachedDevice.setJustDiscovered(true);
cachedDevice.setIsCoordinatedSetMember(isCoordinatedSetMember);
}
}
>4.NameChangedHandler
蓝牙设备名字或者别名发生变化
private class NameChangedHandler implements Handler {
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
mDeviceManager.onDeviceNameUpdated(device);//参考7.3
}
}
>5.BondStateChangedHandler
蓝牙配对状态的变化
private class BondStateChangedHandler implements Handler {
public void onReceive(Context context, Intent intent, BluetoothDevice device) {
if (device == null) {
return;
}
int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
BluetoothDevice.ERROR);
if (mDeviceManager.onBondStateChangedIfProcess(device, bondState)) {
//设备的绑定状态更改在此函数中处理,并且不希望更新UI
return;
}
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
if (cachedDevice == null) {
//缓存里没有的,加入缓存
cachedDevice = mDeviceManager.addDevice(device);
}
if(bondState == BluetoothDevice.BOND_BONDED) {
int groupId = intent.getIntExtra(BluetoothDevice.EXTRA_GROUP_ID,
BluetoothDevice.ERROR);
if (groupId != BluetoothDevice.ERROR && groupId >= 0) {
updateCacheDeviceInfo(groupId, cachedDevice);
} else if (intent.getBooleanExtra(BluetoothDevice.EXTRA_IS_PRIVATE_ADDRESS,
false)) {
updateIgnoreDeviceFlag(cachedDevice);
}
}
for (BluetoothCallback callback : mCallbacks) {
callback.onDeviceBondStateChanged(cachedDevice, bondState);
}
cachedDevice.onBondingStateChanged(bondState);
if (bondState == BluetoothDevice.BOND_NONE) {
//看是否需要取消配对
if (cachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
|| cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
mDeviceManager.onDeviceUnpaired(cachedDevice);
}
int reason = intent.getIntExtra(BluetoothDevice.EXTRA_UNBOND_REASON,
BluetoothDevice.ERROR);
showUnbondMessage(context, cachedDevice.getName(), reason);
}
}
7.CachedBluetoothDeviceManager
7.1.CachedBluetoothDevice
就是看缓存里是否已有对应的device
public synchronized CachedBluetoothDevice findDevice(BluetoothDevice device) {
for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
if (cachedDevice.getDevice().equals(device)) {
//缓存里已经有了,返回即可。
return cachedDevice;
}
//检查子集是否有缓存的
final Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice();
if (!memberDevices.isEmpty()) {
for (CachedBluetoothDevice memberDevice : memberDevices) {
if (memberDevice.getDevice().equals(device)) {
return memberDevice;
}
}
}
//检查子设备是否有助听器
CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
if (subDevice != null && subDevice.getDevice().equals(device)) {
return subDevice;
}
}
return null;
}
7.2.addDevice
- CSIP(Coordinated Set Identification Profile)是一种用于蓝牙LE Audio开发的必备文档
public CachedBluetoothDevice addDevice(BluetoothDevice device) {
CachedBluetoothDevice newDevice;
final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
synchronized (this) {
newDevice = findDevice(device);//验证下是否有旧的,参考7.1
if (newDevice == null) {
newDevice = new CachedBluetoothDevice(mContext, profileManager, device);
//
mCsipDeviceManager.initCsipDeviceIfNeeded(newDevice);
//助听器
mHearingAidDeviceManager.initHearingAidDeviceIfNeeded(newDevice);
既不是CSIP设备也不是助听器
if (!mCsipDeviceManager.setMemberDeviceIfNeeded(newDevice)
&& !mHearingAidDeviceManager.setSubDeviceIfNeeded(newDevice)) {
//那么加入缓存集合
mCachedDevices.add(newDevice);
//回调处理,参考3.5
mBtManager.getEventManager().dispatchDeviceAdded(newDevice);
}
}
}
return newDevice;
}
7.3.onDeviceNameUpdated
public void onDeviceNameUpdated(BluetoothDevice device) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice != null) {
cachedDevice.refreshName();
}
}
7.4.onDeviceDisappeared
蓝牙设备消失
public static boolean onDeviceDisappeared(CachedBluetoothDevice cachedDevice) {
cachedDevice.setJustDiscovered(false);//8.5
return cachedDevice.getBondState() == BluetoothDevice.BOND_NONE;
}
7.5.onScanningStateChanged
扫描状态变化
public synchronized void onScanningStateChanged(boolean started) {
//扫描结束不处理
if (!started) return;
//如果开始新的扫描,清除旧的可见性,反向迭代,因为设备可能被移除
for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
cachedDevice.setJustDiscovered(false);//8.5
//下边就是子设备,成员设备的处理
final Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice();
if (!memberDevices.isEmpty()) {
for (CachedBluetoothDevice memberDevice : memberDevices) {
memberDevice.setJustDiscovered(false);
}
return;
}
final CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
if (subDevice != null) {
subDevice.setJustDiscovered(false);
}
}
}
7.6.onBluetoothStateChanged
public synchronized void onBluetoothStateChanged(int bluetoothState) {
//当蓝牙关闭时,我们需要清除非绑定设备,否则,它们最终会出现在下一个BT启用中
if (bluetoothState == BluetoothAdapter.STATE_TURNING_OFF) {
for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
final Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice();
if (!memberDevices.isEmpty()) {
for (CachedBluetoothDevice memberDevice : memberDevices) {
if (memberDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
cachedDevice.removeMemberDevice(memberDevice);
}
}
} else {
CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
if (subDevice != null) {
if (subDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
cachedDevice.setSubDevice(null);
}
}
}
if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
cachedDevice.setJustDiscovered(false);//8.5
mCachedDevices.remove(i);
}
//Clear if there any Tws battery info on BT turning OFF
cachedDevice.mTwspBatteryState = -1;
cachedDevice.mTwspBatteryLevel = -1;
}
}
}
8.CachedBluetoothDevice.java
8.1.refreshName
void refreshName() {
dispatchAttributesChanged();
}
>1.dispatchAttributesChanged
蓝牙属性改变,进行回调。此方法调用的地方比较多
void dispatchAttributesChanged() {
for (Callback callback : mCallbacks) {
callback.onDeviceAttributesChanged();
}
}
8.2.fillData
构造方法里调用
private void fillData() {
updateProfiles();
fetchActiveDevices();
migratePhonebookPermissionChoice();
migrateMessagePermissionChoice();
setLeAudioEnabled();
dispatchAttributesChanged();//8.1.1
}
8.3.setName
蓝牙名字发生变化调用
public void setName(String name) {
// Prevent getName() to be set to null if setName(null) is called
if (name != null && !TextUtils.equals(name, getName())) {
mDevice.setAlias(name);
dispatchAttributesChanged();
}
}
8.4.refresh
连接设备的时候,绑定状态的变化等
void refresh() {
ThreadUtils.postOnBackgroundThread(() -> {
if (BluetoothUtils.isAdvancedDetailsHeader(mDevice)) {
Uri uri = BluetoothUtils.getUriMetaData(getDevice(),
BluetoothDevice.METADATA_MAIN_ICON);
if (uri != null && mDrawableCache.get(uri.toString()) == null) {
mDrawableCache.put(uri.toString(),
(BitmapDrawable) BluetoothUtils.getBtDrawableWithDescription(
mContext, this).first);
}
}
ThreadUtils.postOnMainThread(() -> {
dispatchAttributesChanged();
});
});
}
8.5.setJustDiscovered
- 蓝牙设备消失,开始扫描,蓝牙关闭会设置为false,参考7.4到7.6
- 参考6.1.3,发现新设备后会设置为true
public void setJustDiscovered(boolean justDiscovered) {
if (mJustDiscovered != justDiscovered) {
mJustDiscovered = justDiscovered;
dispatchAttributesChanged();
}
}
8.6.onActiveDeviceChanged
public void onActiveDeviceChanged(boolean isActive, int bluetoothProfile) {
boolean changed = false;
switch (bluetoothProfile) {
case BluetoothProfile.A2DP:
changed = (mIsActiveDeviceA2dp != isActive);
mIsActiveDeviceA2dp = isActive;
break;
case BluetoothProfile.HEADSET:
changed = (mIsActiveDeviceHeadset != isActive);
mIsActiveDeviceHeadset = isActive;
break;
case BluetoothProfile.HEARING_AID:
changed = (mIsActiveDeviceHearingAid != isActive);
mIsActiveDeviceHearingAid = isActive;
break;
case BluetoothProfile.LE_AUDIO:
changed = (mIsActiveDeviceLeAudio != isActive);
mIsActiveDeviceLeAudio = isActive;
break;
default:
break;
}
if (changed) {
dispatchAttributesChanged();
}
}
8.7.onAudioModeChanged
void onAudioModeChanged() {
dispatchAttributesChanged();
}
8.8.setRssi
void setRssi(short rssi) {
if (mRssi != rssi) {
mRssi = rssi;
dispatchAttributesChanged();
}
8.9.onUuidChanged
void onUuidChanged() {
updateProfiles();
ParcelUuid[] uuids = mDevice.getUuids();
long timeout = MAX_UUID_DELAY_FOR_AUTO_CONNECT;
if (ArrayUtils.contains(uuids, BluetoothUuid.HOGP)) {
timeout = MAX_HOGP_DELAY_FOR_AUTO_CONNECT;
} else if (ArrayUtils.contains(uuids, BluetoothUuid.HEARING_AID)) {
timeout = MAX_HEARING_AIDS_DELAY_FOR_AUTO_CONNECT;
} else if (ArrayUtils.contains(uuids, BluetoothUuid.LE_AUDIO)) {
timeout = MAX_LEAUDIO_DELAY_FOR_AUTO_CONNECT;
}
if ((mConnectAttempted + timeout) > SystemClock.elapsedRealtime()) {
connectDevice();
}
dispatchAttributesChanged();
}