Android Open Source - android-sdk Bluetooth Gatt Receiver






From Project

Back to project page android-sdk.

License

The source code is released under:

MIT License

If you think the Android project android-sdk listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package io.relayr.ble.service;
/*w  w w. j  a  va 2s. c om*/
import android.annotation.TargetApi;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.os.Build;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import io.relayr.RelayrApp;
import io.relayr.ble.DeviceCompatibilityUtils;
import io.relayr.ble.service.error.DisconnectionException;
import io.relayr.ble.service.error.WriteCharacteristicException;
import rx.Observable;
import rx.Subscriber;
import rx.functions.Func1;

import static android.bluetooth.BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION;
import static android.bluetooth.BluetoothGatt.GATT_INSUFFICIENT_ENCRYPTION;
import static android.bluetooth.BluetoothGatt.GATT_SUCCESS;
import static android.bluetooth.BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;
import static android.bluetooth.BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
import static io.relayr.ble.service.BluetoothGattReceiver.UndocumentedBleStuff.fixUndocumentedBleStatusProblem;
import static io.relayr.ble.service.BluetoothGattReceiver.UndocumentedBleStuff.isUndocumentedErrorStatus;

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class BluetoothGattReceiver extends BluetoothGattCallback {

    private volatile Subscriber<? super BluetoothGatt> mConnectionChangesSubscriber;
    private volatile Subscriber<? super BluetoothGatt> mDisconnectedSubscriber;
    private volatile Subscriber<? super BluetoothGatt> mBluetoothGattServiceSubscriber;
    private volatile Subscriber<? super BluetoothGattCharacteristic> mValueChangesSubscriber;
    private volatile Subscriber<? super BluetoothGattCharacteristic> mValueChangesUnSubscriber;
    private volatile Map<UUID, Subscriber<? super BluetoothGattCharacteristic>>
            mWriteCharacteristicsSubscriberMap = new ConcurrentHashMap<>();
    private volatile Map<UUID, Subscriber<? super BluetoothGattCharacteristic>>
            mReadCharacteristicsSubscriberMap = new ConcurrentHashMap<>();

    public Observable<BluetoothGatt> connect(final BluetoothDevice bluetoothDevice) {
        return Observable.create(new Observable.OnSubscribe<BluetoothGatt>() {
            @Override
            public void call(Subscriber<? super BluetoothGatt> subscriber) {
                mConnectionChangesSubscriber = subscriber;
                bluetoothDevice.connectGatt(RelayrApp.get(), false, BluetoothGattReceiver.this);
            }
        });
    }
    
    static class UndocumentedBleStuff {
        
        static boolean isUndocumentedErrorStatus(int status) {
            return status == 133 || status == 137;
        }
        
        static void fixUndocumentedBleStatusProblem(BluetoothGatt gatt, BluetoothGattReceiver receiver) {
            DeviceCompatibilityUtils.refresh(gatt);
            gatt.getDevice().connectGatt(RelayrApp.get(), false, receiver);
        }
    }

    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        if (isUndocumentedErrorStatus(status)) {
            fixUndocumentedBleStatusProblem(gatt, this);
            return;
        }
        if (status != GATT_SUCCESS) return;

        if (newState == STATE_CONNECTED) { // on connected
            if (mConnectionChangesSubscriber != null) mConnectionChangesSubscriber.onNext(gatt);
        } else if (newState == STATE_DISCONNECTED) {
            if (mDisconnectedSubscriber != null) { // disconnected voluntarily
                gatt.close(); // should stay here since you might want to reconnect if involuntarily
                mDisconnectedSubscriber.onNext(gatt);
                mDisconnectedSubscriber.onCompleted();
            } else { // disconnected involuntarily because an error occurred
                if (mConnectionChangesSubscriber != null)
                    mConnectionChangesSubscriber.onError(new DisconnectionException(status + ""));
            }
        } /*else if (BluetoothGattStatus.isFailureStatus(status)) {
            if (mConnectionChangesSubscriber != null)  // TODO: unreachable -propagate error earlier
                mConnectionChangesSubscriber.onError(new GattException(status + ""));
        }*/
    }

    public Observable<BluetoothGatt> discoverServices(final BluetoothGatt bluetoothGatt) {
        return Observable.create(new Observable.OnSubscribe<BluetoothGatt>() {
            @Override
            public void call(Subscriber<? super BluetoothGatt> subscriber) {
                mBluetoothGattServiceSubscriber = subscriber;
                //if (bluetoothGatt.getServices() != null && bluetoothGatt.getServices().size() > 0)
                //    mBluetoothGattServiceSubscriber.onNext(bluetoothGatt);
                //else // TODO: we don't cache bc we don't know if the services are up to date...
                bluetoothGatt.discoverServices();
            }
        });
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        if (mBluetoothGattServiceSubscriber == null) return;
        mBluetoothGattServiceSubscriber.onNext(gatt);
    }

    public Observable<BluetoothGatt> disconnect(final BluetoothGatt bluetoothGatt) {
        return Observable.create(new Observable.OnSubscribe<BluetoothGatt>() {
            @Override
            public void call(Subscriber<? super BluetoothGatt> subscriber) {
                mDisconnectedSubscriber = subscriber;
                bluetoothGatt.disconnect();
            }
        });
    }

    public Observable<BluetoothGattCharacteristic>
                            writeCharacteristic(final BluetoothGatt bluetoothGatt,
                                                final BluetoothGattCharacteristic characteristic) {
        return Observable.create(new Observable.OnSubscribe<BluetoothGattCharacteristic>() {
            @Override
            public void call(Subscriber<? super BluetoothGattCharacteristic> subscriber) {
                mWriteCharacteristicsSubscriberMap.put(characteristic.getUuid(), subscriber);
                bluetoothGatt.writeCharacteristic(characteristic);
            }
        });
    }

    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,
                                      final BluetoothGattCharacteristic characteristic,
                                      int status) {
        Subscriber<? super BluetoothGattCharacteristic> subscriber =
                mWriteCharacteristicsSubscriberMap.remove(characteristic.getUuid());
        if (status == GATT_SUCCESS) {
            subscriber.onNext(characteristic);
        } else if(GATT_INSUFFICIENT_AUTHENTICATION == status || GATT_INSUFFICIENT_ENCRYPTION == status) {
            Observable.just(gatt)
                    .flatMap(new BondingReceiver.BondingFunc1())
                    .map(new Func1<BluetoothGatt, Boolean>() {
                        @Override
                        public Boolean call(BluetoothGatt bluetoothGatt) {
                            return bluetoothGatt.writeCharacteristic(characteristic);
                        }
                    })
                    .subscribe();
        } else if (isUndocumentedErrorStatus(status)) {
            fixUndocumentedBleStatusProblem(gatt, this);
        } else {
            subscriber.onError(new WriteCharacteristicException(characteristic, status));
        }
    }
    public Observable<BluetoothGattCharacteristic> readCharacteristic(
                                                final BluetoothGatt gatt,
                                                final BluetoothGattCharacteristic characteristic) {
        return Observable.create(new Observable.OnSubscribe<BluetoothGattCharacteristic>() {
            @Override
            public void call(Subscriber<? super BluetoothGattCharacteristic> subscriber) {
                mReadCharacteristicsSubscriberMap.put(characteristic.getUuid(), subscriber);
                gatt.readCharacteristic(characteristic);
            }
        });
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
                                     final BluetoothGattCharacteristic characteristic,
                                     int status) {
        Subscriber<? super BluetoothGattCharacteristic> subscriber =
                mReadCharacteristicsSubscriberMap.remove(characteristic.getUuid());
        if (status == GATT_SUCCESS) {
            subscriber.onNext(characteristic);
        } else if(GATT_INSUFFICIENT_AUTHENTICATION == status || GATT_INSUFFICIENT_ENCRYPTION == status) {
            Observable.just(gatt)
                    .flatMap(new BondingReceiver.BondingFunc1())
                    .map(new Func1<BluetoothGatt, Boolean>() {
                        @Override
                        public Boolean call(BluetoothGatt bluetoothGatt) {
                            return bluetoothGatt.readCharacteristic(characteristic);
                        }
                    })
                    .subscribe();
        } else if (isUndocumentedErrorStatus(status)) {
            fixUndocumentedBleStatusProblem(gatt, this);
        } else {
            subscriber.onError(new WriteCharacteristicException(characteristic, status));
        }
    }

    public Observable<BluetoothGattCharacteristic> subscribeToCharacteristicChanges(
            final BluetoothGatt gatt,
            final BluetoothGattCharacteristic characteristic,
            final BluetoothGattDescriptor descriptor) {
        return Observable.create(new Observable.OnSubscribe<BluetoothGattCharacteristic>() {
            @Override
            public void call(Subscriber<? super BluetoothGattCharacteristic> subscriber) {
                mValueChangesSubscriber = subscriber;
                gatt.setCharacteristicNotification(characteristic, true);
                descriptor.setValue(ENABLE_NOTIFICATION_VALUE);
                gatt.writeDescriptor(descriptor);
            }
        });
    }

    public Observable<BluetoothGattCharacteristic> unsubscribeToCharacteristicChanges(
            final BluetoothGatt gatt,
            final BluetoothGattCharacteristic characteristic,
            final BluetoothGattDescriptor descriptor) {
        return Observable.create(new Observable.OnSubscribe<BluetoothGattCharacteristic>() {
            @Override
            public void call(Subscriber<? super BluetoothGattCharacteristic> subscriber) {
                mValueChangesUnSubscriber = subscriber;
                gatt.setCharacteristicNotification(characteristic, false);
                descriptor.setValue(DISABLE_NOTIFICATION_VALUE);
                gatt.writeDescriptor(descriptor);
            }
        });
    }

    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        super.onDescriptorWrite(gatt, descriptor, status);
        if (mValueChangesUnSubscriber != null) {
            mValueChangesUnSubscriber.onNext(descriptor.getCharacteristic());
        }
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        mValueChangesSubscriber.onNext(characteristic);
    }

}




Java Source Code List

io.relayr.DebugModules.java
io.relayr.LoginEventListener.java
io.relayr.Modules.java
io.relayr.RelayrApp.java
io.relayr.RelayrModule.java
io.relayr.RelayrSdk.java
io.relayr.SocketClient.java
io.relayr.activity.LoginActivity.java
io.relayr.activity.UiModule.java
io.relayr.api.ApiModule.java
io.relayr.api.CloudApi.java
io.relayr.api.DebugApiModule.java
io.relayr.api.MockBackend.java
io.relayr.api.MockCloudApi.java
io.relayr.api.MockOauthApi.java
io.relayr.api.MockRelayrApi.java
io.relayr.api.MockStatusApi.java
io.relayr.api.MockSubscriptionApi.java
io.relayr.api.OauthApi.java
io.relayr.api.RelayrApi.java
io.relayr.api.StatusApi.java
io.relayr.api.SubscriptionApi.java
io.relayr.api.Utils.java
io.relayr.api.package-info.java
io.relayr.ble.BleDeviceManager.java
io.relayr.ble.BleDeviceMode.java
io.relayr.ble.BleDeviceType.java
io.relayr.ble.BleDevice.java
io.relayr.ble.BleDevicesScanner.java
io.relayr.ble.BleModule.java
io.relayr.ble.BleScannerFilter.java
io.relayr.ble.BleSocketClient.java
io.relayr.ble.BleUtils.java
io.relayr.ble.BluetoothGattStatus.java
io.relayr.ble.DebugBleModule.java
io.relayr.ble.DeviceCompatibilityUtils.java
io.relayr.ble.MockBleUtils.java
io.relayr.ble.NullableRelayrBleSdk.java
io.relayr.ble.RelayrBleSdkImpl.java
io.relayr.ble.RelayrBleSdk.java
io.relayr.ble.parser.AdvertisementPacketParser.java
io.relayr.ble.parser.BleDataParser.java
io.relayr.ble.service.BaseService.java
io.relayr.ble.service.BluetoothGattReceiver.java
io.relayr.ble.service.BondingReceiver.java
io.relayr.ble.service.DirectConnectionService.java
io.relayr.ble.service.MasterModuleService.java
io.relayr.ble.service.OnBoardingService.java
io.relayr.ble.service.Service.java
io.relayr.ble.service.ShortUUID.java
io.relayr.ble.service.Utils.java
io.relayr.ble.service.error.CharacteristicNotFoundException.java
io.relayr.ble.service.error.DisconnectionException.java
io.relayr.ble.service.error.GattException.java
io.relayr.ble.service.error.ReadCharacteristicException.java
io.relayr.ble.service.error.WriteCharacteristicException.java
io.relayr.ble.service.package-info.java
io.relayr.ble.package-info.java
io.relayr.log.LoggerStorage.java
io.relayr.log.Logger.java
io.relayr.model.AccelGyroscope.java
io.relayr.model.App.java
io.relayr.model.BookmarkDevice.java
io.relayr.model.Bookmark.java
io.relayr.model.Command.java
io.relayr.model.CreateWunderBar.java
io.relayr.model.DeviceModel.java
io.relayr.model.Device.java
io.relayr.model.LightColorProx.java
io.relayr.model.LogEvent.java
io.relayr.model.ModelDefinition.java
io.relayr.model.Model.java
io.relayr.model.OauthToken.java
io.relayr.model.ReadingMeaning.java
io.relayr.model.Reading.java
io.relayr.model.Status.java
io.relayr.model.TransmitterDevice.java
io.relayr.model.Transmitter.java
io.relayr.model.User.java
io.relayr.model.WebSocketConfig.java
io.relayr.model.WunderBar.java
io.relayr.model.package-info.java
io.relayr.storage.DataStorage.java
io.relayr.storage.RelayrProperties.java
io.relayr.util.DebugUtilModule.java
io.relayr.util.MockReachabilityUtils.java
io.relayr.util.ReachabilityUtils.java
io.relayr.util.UtilModule.java
io.relayr.websocket.DebugWebSocketModule.java
io.relayr.websocket.MockWebSocketFactory.java
io.relayr.websocket.MockWebSocket.java
io.relayr.websocket.WebSocketCallback.java
io.relayr.websocket.WebSocketClient.java
io.relayr.websocket.WebSocketFactory.java
io.relayr.websocket.WebSocketModule.java
io.relayr.websocket.WebSocket.java
io.relayr.websocket.package-info.java
io.relayr.package-info.java