2017-11-02 29 views
0

iOS 장치에서 생성 된 BLE 장치를 검색하고 있습니다. 그런 다음 특정 서비스에 연결하고 특정 특성을 읽습니다. GATT 서비스가있는 iOS 앱이 포 그라운드에있을 때 완벽하게 작동합니다. 하지만 iOS 서버 앱을 숨기면 Android 클라이언트가 BLE GATT 기기를 감지하지 않습니다.배경에있는 BLE 장치를 검색 할 때 RxBleClient를 사용할 때의 문제

public static ScanFilter[] getFilters(UUID serviceUuid) { 
    ... 
    filters.add(new ScanFilter.Builder().setServiceUuid(new ParcelUuid(serviceUuid)).build()); 
    return filters.toArray(new ScanFilter[filters.size()]); 
} 
public static ScanSettings getScanSettings() { 
    return new ScanSettings.Builder() 
      .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) // change if needed 
      .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) // change if needed 
      .build(); 
} 

BLE Scanner app 성공적으로 숨겨 본다 GATT 서버

업데이트 다음 필터 코드 부분

public final class ScannerUtil { 
public static final List<UUID> BEACON_UUUIDs = Arrays.asList(
........... 

     UUID.fromString("a8427a96-70bd-4a7e-9008-6e5c3d445a2b")); 


public static ScanSettings getScanSettings() { 
    return new ScanSettings.Builder() 
      .setScanMode(ScanSettings.SCAN_MODE_BALANCED) // change if needed 
      .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) // change if needed 
      .build(); 
} 

public static ScanFilter[] getFilters(UUID serviceUuid) { 
    List<ScanFilter> filters = Stream.of(BEACON_UUUIDs) 
      .map(iBeaconScanFilter::setScanFilter) 
      .collect(toList()); 
    filters.add(new ScanFilter.Builder().setServiceUuid(new ParcelUuid(serviceUuid)).build()); 
    return filters.toArray(new ScanFilter[filters.size()]); 
} 

}

전체 스캐너 클래스 코드는 다음입니다 :

public class BLEGlobalScanner { 
    private final ScannerConfiguration configuration; 
    private final Context context; 
    private final RxBleClient rxBleClient; 
    private final Map<String, String> devicesMap = new HashMap<>(); 
    private final Map<String, DeviceApoloBeacon> beaconsMap = new HashMap<>(); 
    private final ScanFilter[] scanFilter; 
public BLEGlobalScanner(ScannerConfiguration configuration, Context context) { 
    this.configuration = configuration; 
    this.context = context; 
    this.rxBleClient = RxBleClient.create(context); 
    this.scanFilter = getFilters(configuration.beacons(), configuration.gattServer().server()); 
} 

public Observable<BluetoothDeviceApolo> start() { 
    return bluetoothEnableObservable(context).switchMap(aBoolean -> startScanner()) 
      .filter(Optional::isPresent) 
      .map(Optional::get); 
} 

private Observable<Optional<BluetoothDeviceApolo>> startScanner() { 
    return rxBleClient.scanBleDevices(getScanSettings(), scanFilter) 
      .buffer(2, TimeUnit.SECONDS) 
      .flatMap(rxBleDevices -> Observable.from(rxBleDevices) 
        .distinct(scanResult -> scanResult.getBleDevice().getMacAddress()) 
        .concatMap(this::handleDevices) 
        .map(Optional::of)) 
      .observeOn(mainThread()) 
      .onErrorResumeNext(throwable -> { 
       Timber.e(throwable, "startScanner"); 
       return Observable.just(Optional.empty()); 
      }) 
      .onExceptionResumeNext(Observable.just(Optional.empty())) 
      .retry(); 
} 

private Observable<BluetoothDeviceApolo> handleDevices(ScanResult scanResult) { 
    if (beaconsMap.containsKey(scanResult.getBleDevice().getMacAddress())) { 
     return Observable.fromCallable(() -> beaconsMap.get(scanResult.getBleDevice().getMacAddress())) 
       .map(beacon -> beacon.toBuilder() 
         .lastSeen(System.currentTimeMillis()) 
         .rssi(scanResult.getRssi()) 
         .build()); 
    } else { 
     return handleBeacon(scanResult) 
       .map(device -> (BluetoothDeviceApolo) device) 
       .switchIfEmpty(
         handleDevice(scanResult).map(deviceApolo -> (BluetoothDeviceApolo) deviceApolo) 
       ); 
    } 
} 

private Observable<DeviceApoloBeacon> handleBeacon(ScanResult scanResult) { 
    return Observable.fromCallable(() -> scanResult.getScanRecord().getManufacturerSpecificData(COMPANY_ID_APPLE)) 
      .filter(bytes -> bytes != null) 
      .filter(bytes -> DeviceApoloBeacon.requiredManufactureSize == bytes.length) 
      .map(bytes -> DeviceApoloBeacon.builder() 
        .manufacturedData(bytes) 
        .lastSeen(System.currentTimeMillis()) 
        .rssi(scanResult.getRssi()) 
        .build()) 
      .filter(beacon -> configuration.beacons().contains(beacon.uuuid())) 
      .doOnNext(beacon -> beaconsMap.put(scanResult.getBleDevice().getMacAddress(), beacon)); 
} 


private Observable<DeviceApolo> handleDevice(ScanResult scanResult) { 
    final RxBleDevice rxBleDevice = scanResult.getBleDevice(); 
    if (devicesMap.containsKey(rxBleDevice.getMacAddress())) { 
     return Observable.fromCallable(() -> devicesMap.get(rxBleDevice.getMacAddress())) 
       .timestamp() 
       .map(deviceStr -> DeviceApolo.create(deviceStr.getValue(), deviceStr.getTimestampMillis(), scanResult.getRssi())); 
    } else { 
     return readCharacteristic(rxBleDevice, scanResult.getRssi()); 
    } 
} 

private Observable<DeviceApolo> readCharacteristic(RxBleDevice rxBleDevice, final int rssi) { 
    return rxBleDevice.establishConnection(false) 
      .compose(new ConnectionSharingAdapter()) 
      .switchMap(rxBleConnection -> rxBleConnection.readCharacteristic(configuration.gattServer().characteristic())) 
      .map(String::new) 
      .doOnNext(s -> devicesMap.put(rxBleDevice.getMacAddress(), s)) 
      .timestamp() 
      .map(deviceStr -> DeviceApolo.create(deviceStr.getValue(), deviceStr.getTimestampMillis(), rssi)) 
      .retry(); 
} 
} 
+1

'iOS 서버 앱 숨기기'란 무엇을 의미합니까? –

+0

즉, iOS 어플리케이션이 GATT 서버를 생성 할 때 백그라운드로 이동합니다. – Alex

+0

'Android 클라이언트가 BLE GATT 디바이스를 감지하지 못한다고 가정하면 스캔 할 때 디바이스를 방출하지 않는다는 것을 의미합니다. 'BLE Scanner app'이 단순히 iOS 앱이 포 그라운드에 있었던 시간부터 검색 결과를 캐시합니까? –

답변

0

코드에 문제가 없으며 RxAndroidBle에 문제가 있습니다. is discovered eventually을 스캔 할 주변 장치입니다.

iOS 앱이 백그라운드 모드에서 의도 한 동작을 경험하고 있습니다. The bluetooth-peripheral Background Execution Modethe official reference site으로 검색하십시오.

기준 상태 : 광고 모든 애플리케이션이 배경에있는 경우

는 주파수되는 사용자의 주변 장치는 광고 패킷을 감소시킬 수있다 보낸다.

iOS 응용 프로그램을 주변 기기로 사용하려는 경우 문서를 확인하는 것이 많지 않습니다. 또는 다른 하드웨어에서 주변 장치를 구현할 수 있는지 확인할 수 있습니다 (정확한 사용 사례를 모르지만이 질문의 요점은 아닙니다).

최고 감사 카드