下面列出了android.bluetooth.BluetoothAdapter#LeScanCallback ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Call this method from your BluetoothAdapter.LeScanCallback method.
* Doing so is optional, but if you do, this class will be able to count the number of
* disctinct bluetooth devices scanned, and prevent crashes before they happen.
*
* This works very well if the app containing this class is the only one running bluetooth
* LE scans on the device, or it is constantly doing scans (e.g. is in the foreground for
* extended periods of time.)
*
* This will not work well if the application using this class is only scanning periodically
* (e.g. when in the background to save battery) and another application is also scanning on
* the same device, because this class will only get the counts from this application.
*
* Future augmentation of this class may improve this by somehow centralizing the list of
* unique scanned devices.
*/
@TargetApi(18)
public void notifyScannedDevice(BluetoothDevice device, BluetoothAdapter.LeScanCallback scanner) {
int oldSize = 0, newSize;
if (isDebugEnabled()) oldSize = distinctBluetoothAddresses.size();
distinctBluetoothAddresses.add(device.getAddress());
if (isDebugEnabled()) {
newSize = distinctBluetoothAddresses.size();
if (oldSize != newSize && newSize % 100 == 0) {
if (isDebugEnabled()) Log.d(TAG, "Distinct bluetooth devices seen: "+distinctBluetoothAddresses.size());
}
}
if (distinctBluetoothAddresses.size() > getCrashRiskDeviceCount()) {
if (PREEMPTIVE_ACTION_ENABLED && !recoveryInProgress) {
Logger.log.verbose("Large number of bluetooth devices detected: "+distinctBluetoothAddresses.size()+" Proactively attempting to clear out address list to prevent a crash");
Logger.log.verbose("Stopping LE Scan");
//noinspection deprecation old API compatability
BluetoothAdapter.getDefaultAdapter().stopLeScan(scanner);
startRecovery();
processStateChange();
}
}
}
private BluetoothAdapter.LeScanCallback getLeScanCallback() {
if (leScanCallback == null) {
leScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, final int rssi,
final byte[] scanRecord) {
LogManager.d(TAG, "got record");
mCycledLeScanCallback.onLeScan(device, rssi, scanRecord, System.currentTimeMillis());
if (mBluetoothCrashResolver != null) {
mBluetoothCrashResolver.notifyScannedDevice(device, getLeScanCallback());
}
}
};
}
return leScanCallback;
}
@Override
BluetoothAdapter.LeScanCallback createScanCallback(final ObservableEmitter<RxBleInternalScanResult> emitter) {
return new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
if (!scanFilterMatcher.isEmpty() && RxBleLog.isAtLeast(LogConstants.DEBUG) && RxBleLog.getShouldLogScannedPeripherals()) {
RxBleLog.d("%s, name=%s, rssi=%d, data=%s",
LoggerUtil.commonMacMessage(device.getAddress()),
device.getName(),
rssi,
LoggerUtil.bytesToHex(scanRecord)
);
}
final RxBleInternalScanResult internalScanResult = scanResultCreator.create(device, rssi, scanRecord);
if (scanFilterMatcher.matches(internalScanResult)) {
emitter.onNext(internalScanResult);
}
}
};
}
@Override
BluetoothAdapter.LeScanCallback createScanCallback(final ObservableEmitter<RxBleInternalScanResultLegacy> emitter) {
return new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
if (filterUuids != null && RxBleLog.isAtLeast(LogConstants.DEBUG)) {
RxBleLog.d("%s, name=%s, rssi=%d, data=%s",
LoggerUtil.commonMacMessage(device.getAddress()),
device.getName(),
rssi,
LoggerUtil.bytesToHex(scanRecord)
);
}
if (filterUuids == null || uuidUtil.extractUUIDs(scanRecord).containsAll(filterUuids)) {
emitter.onNext(new RxBleInternalScanResultLegacy(device, rssi, scanRecord));
}
}
};
}
@Override
boolean startScan(RxBleAdapterWrapper rxBleAdapterWrapper, BluetoothAdapter.LeScanCallback scanCallback) {
if (this.scanFilterMatcher.isEmpty()) {
RxBleLog.d("No library side filtering —> debug logs of scanned devices disabled");
}
return rxBleAdapterWrapper.startLegacyLeScan(scanCallback);
}
/** Implementation of Android LeScanCallback. */
private BluetoothAdapter.LeScanCallback getScanCallback() {
return (bluetoothDevice, rssi, eirData) -> {
if (RxCentralLogger.isDebug()) {
RxCentralLogger.debug("onLeScan - BD_ADDR: " + bluetoothDevice.getAddress()
+ " | RSSI: " + rssi);
}
ScanData scanData = new JellyBeanScanData(bluetoothDevice, rssi, parsedAdDataFactory.produce(eirData));
scanDataRelay.accept(scanData);
};
}
/**
* Call this method from your BluetoothAdapter.LeScanCallback method.
* Doing so is optional, but if you do, this class will be able to count the number of
* distinct Bluetooth devices scanned, and prevent crashes before they happen.
*
* This works very well if the app containing this class is the only one running bluetooth
* LE scans on the device, or it is constantly doing scans (e.g. is in the foreground for
* extended periods of time.)
*
* This will not work well if the application using this class is only scanning periodically
* (e.g. when in the background to save battery) and another application is also scanning on
* the same device, because this class will only get the counts from this application.
*
* Future augmentation of this class may improve this by somehow centralizing the list of
* unique scanned devices.
*
* @param device
*/
@TargetApi(18)
public void notifyScannedDevice(BluetoothDevice device, BluetoothAdapter.LeScanCallback scanner) {
int oldSize, newSize;
oldSize = distinctBluetoothAddresses.size();
synchronized(distinctBluetoothAddresses) {
distinctBluetoothAddresses.add(device.getAddress());
}
newSize = distinctBluetoothAddresses.size();
if (oldSize != newSize && newSize % 100 == 0) {
LogManager.d(TAG, "Distinct Bluetooth devices seen: %s", distinctBluetoothAddresses.size());
}
if (distinctBluetoothAddresses.size() > getCrashRiskDeviceCount()) {
if (PREEMPTIVE_ACTION_ENABLED && !recoveryInProgress) {
LogManager.w(TAG, "Large number of Bluetooth devices detected: %s Proactively "
+ "attempting to clear out address list to prevent a crash",
distinctBluetoothAddresses.size());
LogManager.w(TAG, "Stopping LE Scan");
BluetoothAdapter.getDefaultAdapter().stopLeScan(scanner);
startRecovery();
processStateChange();
}
}
}
@Test
@Config(sdk = Build.VERSION_CODES.KITKAT)
public void doNotFilterUuidsOnKitkatWithEmptyServiceList() {
ByteBuffer mockScanRecordBuffer = ByteBuffer.allocate(100).order(ByteOrder.LITTLE_ENDIAN)
.put((byte) 17)
.put((byte) 0x07)
.putLong(INVALID_UUID.getLeastSignificantBits())
.putLong(INVALID_UUID.getMostSignificantBits());
byte[] mockScanRecord = Arrays.copyOf(mockScanRecordBuffer.array(),
mockScanRecordBuffer.position());
Scanner.NewDeviceFoundListener listener = Mockito.mock(Scanner.NewDeviceFoundListener.class);
ScannerConfiguration configuration = new ScannerConfiguration();
configuration.setNewDeviceFoundListener(listener);
ArgumentCaptor<BluetoothAdapter.LeScanCallback> callbackCaptor
= ArgumentCaptor.forClass(BluetoothAdapter.LeScanCallback.class);
BluetoothAdapter testAdapter = Mockito.mock(BluetoothAdapter.class);
LolipopLEScanner scanner = new LolipopLEScanner(configuration);
scanner.onStart(testAdapter, 0);
Mockito.verify(testAdapter).startLeScan(callbackCaptor.capture());
callbackCaptor.getValue().onLeScan(Mockito.mock(BluetoothDevice.class), -10, mockScanRecord);
Mockito.verify(listener).onNewDeviceFound(Mockito.<ScanEvent>any());
}
@Override public final boolean startLeScan(BluetoothAdapter.LeScanCallback callback)
{
if (m_adaptor != null)
return m_adaptor.startLeScan(callback);
return false;
}
public BleDevicesScanner(BluetoothAdapter adapter, UUID[] servicesToDiscover, BluetoothAdapter.LeScanCallback callback) {
mBluetoothAdapter = adapter;
mServicesToDiscover = servicesToDiscover == null ? null : Arrays.asList(servicesToDiscover);
mLeScansPoster = new LeScansPoster(callback);
mHandler = new Handler();
}
public void findDevice(long scanTimeout, final BleFindListener userCallback){
if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Log.i(TAG, "BLE not supported on this device");
return;
}
if(lastUserCallback != null){
Log.e(TAG, "Already searching for device, you cant call findDevice(...) while the instance is scanning");
return;
}
lastUserCallback = userCallback;
lastScannedDevices.clear();
final BluetoothAdapter.LeScanCallback scanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
ScannedDevice scannedDevice = new ScannedDevice(device, rssi, scanRecord);
if(filter.filter(scannedDevice)) {
Log.i(TAG, "found " + device.getName() + " - " + device.toString() + " rssi:" + rssi);
lastScannedDevices.put(device.getAddress(), scannedDevice);
bluetoothDevice = userCallback.onDeviceFound(lastScannedDevices);
if(bluetoothDevice != null){
stopLastLeScan();
}
}
}
};
scanLeDevice(scanCallback, scanTimeout);
}
@Implementation(minSdk = JELLY_BEAN_MR2)
public boolean startLeScan(UUID[] serviceUuids, BluetoothAdapter.LeScanCallback callback) {
// Ignoring the serviceUuids param for now.
leScanCallbacks.add(callback);
return true;
}
@Implementation(minSdk = JELLY_BEAN_MR2)
public void stopLeScan(BluetoothAdapter.LeScanCallback callback) {
leScanCallbacks.remove(callback);
}
/*****************************************************
* Public methods
******************************************************/
public void setScanCallback(BluetoothAdapter.LeScanCallback cb) {
mLeScanCallback = cb;
}
private void startScan(final UUID[] servicesToScan) {
Log.d(TAG, "startScan");
// Stop current scanning (if needed)
stopScanning();
// Configure scanning
BluetoothAdapter bluetoothAdapter = BleUtils.getBluetoothAdapter(getApplicationContext());
if (BleUtils.getBleStatus(this) != BleUtils.STATUS_BLE_ENABLED) {
Log.w(TAG, "startScan: BluetoothAdapter not initialized or unspecified address.");
} else {
mScanner = new BleDevicesScanner(bluetoothAdapter, servicesToScan, new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) {
//final String deviceName = device.getName();
//Log.d(TAG, "Discovered device: " + (deviceName != null ? deviceName : "<unknown>"));
BluetoothDeviceData previouslyScannedDeviceData = null;
if (mScannedDevices == null) {
mScannedDevices = new ArrayList<>(); // Safeguard
}
// Check that the device was not previously found
for (BluetoothDeviceData deviceData : mScannedDevices) {
if (deviceData.device.getAddress().equals(device.getAddress())) {
previouslyScannedDeviceData = deviceData;
break;
}
}
BluetoothDeviceData deviceData;
if (previouslyScannedDeviceData == null) {
// Add it to the mScannedDevice list
deviceData = new BluetoothDeviceData();
mScannedDevices.add(deviceData);
} else {
deviceData = previouslyScannedDeviceData;
}
deviceData.device = device;
deviceData.rssi = rssi;
deviceData.scanRecord = scanRecord;
decodeScanRecords(deviceData);
// Update device data
long currentMillis = SystemClock.uptimeMillis();
if (previouslyScannedDeviceData == null || currentMillis - mLastUpdateMillis > kMinDelayToUpdateUI) { // Avoid updating when not a new device has been found and the time from the last update is really short to avoid updating UI so fast that it will become unresponsive
mLastUpdateMillis = currentMillis;
runOnUiThread(new Runnable() {
@Override
public void run() {
updateUI();
}
});
}
}
});
// Start scanning
mScanner.start();
}
// Update UI
updateUI();
}
public void stopLegacyLeScan(BluetoothAdapter.LeScanCallback leScanCallback) {
bluetoothAdapter.stopLeScan(leScanCallback);
}
private LeScansPoster(BluetoothAdapter.LeScanCallback leScanCallback) {
this.leScanCallback = leScanCallback;
}
@Override public void stopLeScan(BluetoothAdapter.LeScanCallback callback)
{
}
void stopLeScan(BluetoothAdapter.LeScanCallback callback);
void stopLeScan(BluetoothAdapter.LeScanCallback callback);