Created
October 14, 2016 14:23
-
-
Save aldoborrero/576cf4c80fcd0dfcca7f88850fb0250f to your computer and use it in GitHub Desktop.
This class is a helper for performing Bluetooth operations in a reactive way. Part of this code is extracted from library RxBluetooth created Addenie (https://github.com/adennie/RxBluetooth/blob/master/rxbluetooth/src/main/java/com/andydennie/rxbluetooth/RxBluetooth.java)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class BluetoothCompat { | |
public static boolean createBondCompat(final BluetoothDevice device) | |
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | |
return device.createBond(); | |
} else { | |
Method method = device.getClass().getMethod("createBond", (Class[]) null); | |
final Object invoke = method.invoke(device, (Object[]) null); | |
return (Boolean) invoke; | |
} | |
} | |
public static boolean removeBondCompat(final BluetoothDevice device) throws NoSuchMethodException, InvocationTargetException, | |
IllegalAccessException { | |
Method method = device.getClass().getMethod("removeBond", (Class[]) null); | |
final Object invoke = method.invoke(device, (Object[]) null); | |
return (Boolean) invoke; | |
} | |
private BluetoothCompat() { | |
throw new AssertionError("No instances!"); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class RxBluetoothHelper { | |
private static final Observable.Transformer<Integer, BondStatus> BOND_STATUS_TRANSFORMER = statusObservable -> statusObservable.map(status -> { | |
switch (status) { | |
case BluetoothDevice.BOND_NONE: | |
default: | |
return BondStatus.NONE; | |
case BluetoothDevice.BOND_BONDING: | |
return BondStatus.BONDING; | |
case BluetoothDevice.BOND_BONDED: | |
return BondStatus.BONDED; | |
} | |
}); | |
public enum BondStatus { | |
NONE, | |
BONDING, | |
BONDED | |
} | |
public static Observable<BondStatus> bondStatus(@NonNull final BluetoothDevice device) { | |
return Observable.defer(() -> Observable.just(device.getBondState()).compose(BOND_STATUS_TRANSFORMER)); | |
} | |
public static Observable<BondStatus> bond(@NonNull final Context context, @NonNull final BluetoothDevice device) { | |
return Observable.create(subscriber -> { | |
bondStatus(device).subscribe(bondStatus -> { | |
switch (bondStatus) { | |
case NONE: | |
observeDeviceBonding(context, device).compose(BOND_STATUS_TRANSFORMER).subscribe(subscriber); | |
try { | |
// TODO: Listen for createBond result and emit a associated value | |
BluetoothCompat.createBondCompat(device); | |
} catch (Exception e) { | |
subscriber.onError(new BluetoothIncompatibleBondingException(e)); | |
} | |
break; | |
case BONDING: | |
subscriber.onError(new BluetoothBondingException("device is already in the process of bonding")); | |
break; | |
case BONDED: | |
subscriber.onNext(BondStatus.BONDED); | |
subscriber.onCompleted(); | |
break; | |
} | |
}); | |
}); | |
} | |
public static Observable<BondStatus> removeBond(@NonNull final Context context, @NonNull final BluetoothDevice device) { | |
return Observable.create(subscriber -> { | |
bondStatus(device).subscribe(bondStatus -> { | |
switch (bondStatus) { | |
case NONE: | |
subscriber.onNext(BondStatus.NONE); | |
subscriber.onCompleted(); | |
break; | |
case BONDING: | |
subscriber.onError(new BluetoothBondingException("device is already in the process of unbonding")); | |
break; | |
case BONDED: | |
observeDeviceBonding(context, device).compose(BOND_STATUS_TRANSFORMER).subscribe(subscriber); | |
try { | |
BluetoothCompat.removeBondCompat(device); | |
} catch (Exception e) { | |
subscriber.onError(new BluetoothIncompatibleBondingException(e)); | |
} | |
break; | |
} | |
}); | |
}); | |
} | |
private static Observable<Integer> observeDeviceBonding(@NonNull final Context context, @NonNull final BluetoothDevice device) { | |
return observeBroadcast(context, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED)).filter(pair -> { | |
BluetoothDevice bondingDevice = pair.getValue1().getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); | |
return bondingDevice.equals(device); | |
}) | |
.map(pair1 -> pair1.getValue1().getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1)) | |
.skipWhile(state -> state != BluetoothDevice.BOND_BONDING) | |
.takeUntil(state -> state == BluetoothDevice.BOND_BONDED || state == BluetoothDevice.BOND_NONE); | |
} | |
private static Observable<Pair<Context, Intent>> observeBroadcast(final Context context, final IntentFilter filter) { | |
return Observable.create(new Observable.OnSubscribe<Pair<Context, Intent>>() { | |
@Override public void call(Subscriber<? super Pair<Context, Intent>> subscriber) { | |
final BroadcastReceiver receiver = new BroadcastReceiver() { | |
@Override public void onReceive(Context context, Intent intent) { | |
subscriber.onNext(Pair.with(context, intent)); | |
} | |
}; | |
context.registerReceiver(receiver, filter); | |
subscriber.add(Subscriptions.create(() -> context.unregisterReceiver(receiver))); | |
} | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment