android.bluetooth.BluetoothDevice

Here are the examples of the java api android.bluetooth.BluetoothDevice taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

1016 Examples 7

19 Source : AppRTCBluetoothManager.java
with ISC License
from zxcpoiu

/**
 * AppRTCProximitySensor manages functions related to Bluetoth devices in the
 * AppRTC demo.
 */
public clreplaced AppRTCBluetoothManager {

    private static final String TAG = "AppRTCBluetoothManager";

    // Timeout interval for starting or stopping audio to a Bluetooth SCO device.
    private static final int BLUETOOTH_SCO_TIMEOUT_MS = 4000;

    // Maximum number of SCO connection attempts.
    private static final int MAX_SCO_CONNECTION_ATTEMPTS = 2;

    // Bluetooth connection state.
    public enum State {

        // Bluetooth is not available; no adapter or Bluetooth is off.
        UNINITIALIZED,
        // Bluetooth error happened when trying to start Bluetooth.
        ERROR,
        // Bluetooth proxy object for the Headset profile exists, but no connected headset devices,
        // SCO is not started or disconnected.
        HEADSET_UNAVAILABLE,
        // Bluetooth proxy object for the Headset profile connected, connected Bluetooth headset
        // present, but SCO is not started or disconnected.
        HEADSET_AVAILABLE,
        // Bluetooth audio SCO connection with remote device is closing.
        SCO_DISCONNECTING,
        // Bluetooth audio SCO connection with remote device is initiated.
        SCO_CONNECTING,
        // Bluetooth audio SCO connection with remote device is established.
        SCO_CONNECTED
    }

    private final Context apprtcContext;

    private final InCallManagerModule apprtcAudioManager;

    private final AudioManager audioManager;

    private final Handler handler;

    int scoConnectionAttempts;

    private State bluetoothState;

    private final BluetoothProfile.ServiceListener bluetoothServiceListener;

    private BluetoothAdapter bluetoothAdapter;

    private BluetoothHeadset bluetoothHeadset;

    private BluetoothDevice bluetoothDevice;

    private final BroadcastReceiver bluetoothHeadsetReceiver;

    // Runs when the Bluetooth timeout expires. We use that timeout after calling
    // startScoAudio() or stopScoAudio() because we're not guaranteed to get a
    // callback after those calls.
    private final Runnable bluetoothTimeoutRunnable = new Runnable() {

        @Override
        public void run() {
            bluetoothTimeout();
        }
    };

    /**
     * Implementation of an interface that notifies BluetoothProfile IPC clients when they have been
     * connected to or disconnected from the service.
     */
    private clreplaced BluetoothServiceListener implements BluetoothProfile.ServiceListener {

        @Override
        public // connection and perform other operations that are relevant to the headset profile.
        void onServiceConnected(int profile, BluetoothProfile proxy) {
            if (profile != BluetoothProfile.HEADSET || bluetoothState == State.UNINITIALIZED) {
                return;
            }
            Log.d(TAG, "BluetoothServiceListener.onServiceConnected: BT state=" + bluetoothState);
            // Android only supports one connected Bluetooth Headset at a time.
            bluetoothHeadset = (BluetoothHeadset) proxy;
            updateAudioDeviceState();
            Log.d(TAG, "onServiceConnected done: BT state=" + bluetoothState);
        }

        @Override
        public /**
         * Notifies the client when the proxy object has been disconnected from the service.
         */
        void onServiceDisconnected(int profile) {
            if (profile != BluetoothProfile.HEADSET || bluetoothState == State.UNINITIALIZED) {
                return;
            }
            Log.d(TAG, "BluetoothServiceListener.onServiceDisconnected: BT state=" + bluetoothState);
            stopScoAudio();
            bluetoothHeadset = null;
            bluetoothDevice = null;
            bluetoothState = State.HEADSET_UNAVAILABLE;
            updateAudioDeviceState();
            Log.d(TAG, "onServiceDisconnected done: BT state=" + bluetoothState);
        }
    }

    // Intent broadcast receiver which handles changes in Bluetooth device availability.
    // Detects headset changes and Bluetooth SCO state changes.
    private clreplaced BluetoothHeadsetBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (bluetoothState == State.UNINITIALIZED) {
                return;
            }
            final String action = intent.getAction();
            // Change in connection state of the Headset profile. Note that the
            // change does not tell us anything about whether we're streaming
            // audio to BT over SCO. Typically received when user turns on a BT
            // headset while audio is active using another audio device.
            if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
                final int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED);
                Log.d(TAG, "BluetoothHeadsetBroadcastReceiver.onReceive: " + "a=ACTION_CONNECTION_STATE_CHANGED, " + "s=" + stateToString(state) + ", " + "sb=" + isInitialStickyBroadcast() + ", " + "BT state: " + bluetoothState);
                if (state == BluetoothHeadset.STATE_CONNECTED) {
                    scoConnectionAttempts = 0;
                    updateAudioDeviceState();
                } else if (state == BluetoothHeadset.STATE_CONNECTING) {
                // No action needed.
                } else if (state == BluetoothHeadset.STATE_DISCONNECTING) {
                // No action needed.
                } else if (state == BluetoothHeadset.STATE_DISCONNECTED) {
                    // Bluetooth is probably powered off during the call.
                    stopScoAudio();
                    updateAudioDeviceState();
                }
            // Change in the audio (SCO) connection state of the Headset profile.
            // Typically received after call to startScoAudio() has finalized.
            } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                final int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
                Log.d(TAG, "BluetoothHeadsetBroadcastReceiver.onReceive: " + "a=ACTION_AUDIO_STATE_CHANGED, " + "s=" + stateToString(state) + ", " + "sb=" + isInitialStickyBroadcast() + ", " + "BT state: " + bluetoothState);
                if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
                    cancelTimer();
                    if (bluetoothState == State.SCO_CONNECTING) {
                        Log.d(TAG, "+++ Bluetooth audio SCO is now connected");
                        bluetoothState = State.SCO_CONNECTED;
                        scoConnectionAttempts = 0;
                        updateAudioDeviceState();
                    } else {
                        Log.w(TAG, "Unexpected state BluetoothHeadset.STATE_AUDIO_CONNECTED");
                    }
                } else if (state == BluetoothHeadset.STATE_AUDIO_CONNECTING) {
                    Log.d(TAG, "+++ Bluetooth audio SCO is now connecting...");
                } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
                    Log.d(TAG, "+++ Bluetooth audio SCO is now disconnected");
                    if (isInitialStickyBroadcast()) {
                        Log.d(TAG, "Ignore STATE_AUDIO_DISCONNECTED initial sticky broadcast.");
                        return;
                    }
                    updateAudioDeviceState();
                }
            }
            Log.d(TAG, "onReceive done: BT state=" + bluetoothState);
        }
    }

    /**
     * Construction.
     */
    public static AppRTCBluetoothManager create(Context context, InCallManagerModule audioManager) {
        Log.d(TAG, "create");
        return new AppRTCBluetoothManager(context, audioManager);
    }

    protected AppRTCBluetoothManager(Context context, InCallManagerModule audioManager) {
        Log.d(TAG, "ctor");
        apprtcContext = context;
        apprtcAudioManager = audioManager;
        this.audioManager = getAudioManager(context);
        bluetoothState = State.UNINITIALIZED;
        bluetoothServiceListener = new BluetoothServiceListener();
        bluetoothHeadsetReceiver = new BluetoothHeadsetBroadcastReceiver();
        handler = new Handler(Looper.getMainLooper());
    }

    /**
     * Returns the internal state.
     */
    public State getState() {
        return bluetoothState;
    }

    /**
     * Activates components required to detect Bluetooth devices and to enable
     * BT SCO (audio is routed via BT SCO) for the headset profile. The end
     * state will be HEADSET_UNAVAILABLE but a state machine has started which
     * will start a state change sequence where the final outcome depends on
     * if/when the BT headset is enabled.
     * Example of state change sequence when start() is called while BT device
     * is connected and enabled:
     *   UNINITIALIZED --> HEADSET_UNAVAILABLE --> HEADSET_AVAILABLE -->
     *   SCO_CONNECTING --> SCO_CONNECTED <==> audio is now routed via BT SCO.
     * Note that the AppRTCAudioManager is also involved in driving this state
     * change.
     */
    public void start() {
        Log.d(TAG, "start");
        if (!hasPermission(apprtcContext, android.Manifest.permission.BLUETOOTH)) {
            Log.w(TAG, "Process (pid=" + Process.myPid() + ") lacks BLUETOOTH permission");
            return;
        }
        if (bluetoothState != State.UNINITIALIZED) {
            Log.w(TAG, "Invalid BT state");
            return;
        }
        bluetoothHeadset = null;
        bluetoothDevice = null;
        scoConnectionAttempts = 0;
        // Get a handle to the default local Bluetooth adapter.
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            Log.w(TAG, "Device does not support Bluetooth");
            return;
        }
        // Ensure that the device supports use of BT SCO audio for off call use cases.
        if (!audioManager.isBluetoothScoAvailableOffCall()) {
            Log.e(TAG, "Bluetooth SCO audio is not available off call");
            return;
        }
        logBluetoothAdapterInfo(bluetoothAdapter);
        // Establish a connection to the HEADSET profile (includes both Bluetooth Headset and
        // Hands-Free) proxy object and install a listener.
        if (!getBluetoothProfileProxy(apprtcContext, bluetoothServiceListener, BluetoothProfile.HEADSET)) {
            Log.e(TAG, "BluetoothAdapter.getProfileProxy(HEADSET) failed");
            return;
        }
        // Register receivers for BluetoothHeadset change notifications.
        IntentFilter bluetoothHeadsetFilter = new IntentFilter();
        // Register receiver for change in connection state of the Headset profile.
        bluetoothHeadsetFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
        // Register receiver for change in audio connection state of the Headset profile.
        bluetoothHeadsetFilter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
        registerReceiver(bluetoothHeadsetReceiver, bluetoothHeadsetFilter);
        Log.d(TAG, "HEADSET profile state: " + stateToString(bluetoothAdapter.getProfileConnectionState(BluetoothProfile.HEADSET)));
        Log.d(TAG, "Bluetooth proxy for headset profile has started");
        bluetoothState = State.HEADSET_UNAVAILABLE;
        Log.d(TAG, "start done: BT state=" + bluetoothState);
    }

    /**
     * Stops and closes all components related to Bluetooth audio.
     */
    public void stop() {
        Log.d(TAG, "stop: BT state=" + bluetoothState);
        if (bluetoothAdapter == null) {
            return;
        }
        // Stop BT SCO connection with remote device if needed.
        stopScoAudio();
        // Close down remaining BT resources.
        if (bluetoothState == State.UNINITIALIZED) {
            return;
        }
        unregisterReceiver(bluetoothHeadsetReceiver);
        cancelTimer();
        if (bluetoothHeadset != null) {
            bluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, bluetoothHeadset);
            bluetoothHeadset = null;
        }
        bluetoothAdapter = null;
        bluetoothDevice = null;
        bluetoothState = State.UNINITIALIZED;
        Log.d(TAG, "stop done: BT state=" + bluetoothState);
    }

    /**
     * Starts Bluetooth SCO connection with remote device.
     * Note that the phone application always has the priority on the usage of the SCO connection
     * for telephony. If this method is called while the phone is in call it will be ignored.
     * Similarly, if a call is received or sent while an application is using the SCO connection,
     * the connection will be lost for the application and NOT returned automatically when the call
     * ends. Also note that: up to and including API version JELLY_BEAN_MR1, this method initiates a
     * virtual voice call to the Bluetooth headset. After API version JELLY_BEAN_MR2 only a raw SCO
     * audio connection is established.
     * TODO(henrika): should we add support for virtual voice call to BT headset also for JBMR2 and
     * higher. It might be required to initiates a virtual voice call since many devices do not
     * accept SCO audio without a "call".
     */
    public boolean startScoAudio() {
        Log.d(TAG, "startSco: BT state=" + bluetoothState + ", " + "attempts: " + scoConnectionAttempts + ", " + "SCO is on: " + isSreplaced());
        if (scoConnectionAttempts >= MAX_SCO_CONNECTION_ATTEMPTS) {
            Log.e(TAG, "BT SCO connection fails - no more attempts");
            return false;
        }
        if (bluetoothState != State.HEADSET_AVAILABLE) {
            Log.e(TAG, "BT SCO connection fails - no headset available");
            return false;
        }
        // Start BT SCO channel and wait for ACTION_AUDIO_STATE_CHANGED.
        Log.d(TAG, "Starting Bluetooth SCO and waits for ACTION_AUDIO_STATE_CHANGED...");
        // The SCO connection establishment can take several seconds, hence we cannot rely on the
        // connection to be available when the method returns but instead register to receive the
        // intent ACTION_SCO_AUDIO_STATE_UPDATED and wait for the state to be SCO_AUDIO_STATE_CONNECTED.
        bluetoothState = State.SCO_CONNECTING;
        audioManager.startBluetoothSco();
        audioManager.setBluetoothSreplaced(true);
        scoConnectionAttempts++;
        startTimer();
        Log.d(TAG, "startScoAudio done: BT state=" + bluetoothState + ", " + "SCO is on: " + isSreplaced());
        return true;
    }

    /**
     * Stops Bluetooth SCO connection with remote device.
     */
    public void stopScoAudio() {
        Log.d(TAG, "stopScoAudio: BT state=" + bluetoothState + ", " + "SCO is on: " + isSreplaced());
        if (bluetoothState != State.SCO_CONNECTING && bluetoothState != State.SCO_CONNECTED) {
            return;
        }
        cancelTimer();
        audioManager.stopBluetoothSco();
        audioManager.setBluetoothSreplaced(false);
        bluetoothState = State.SCO_DISCONNECTING;
        Log.d(TAG, "stopScoAudio done: BT state=" + bluetoothState + ", " + "SCO is on: " + isSreplaced());
    }

    /**
     * Use the BluetoothHeadset proxy object (controls the Bluetooth Headset
     * Service via IPC) to update the list of connected devices for the HEADSET
     * profile. The internal state will change to HEADSET_UNAVAILABLE or to
     * HEADSET_AVAILABLE and |bluetoothDevice| will be mapped to the connected
     * device if available.
     */
    public void updateDevice() {
        if (bluetoothState == State.UNINITIALIZED || bluetoothHeadset == null) {
            return;
        }
        Log.d(TAG, "updateDevice");
        // Get connected devices for the headset profile. Returns the set of
        // devices which are in state STATE_CONNECTED. The BluetoothDevice clreplaced
        // is just a thin wrapper for a Bluetooth hardware address.
        List<BluetoothDevice> devices = bluetoothHeadset.getConnectedDevices();
        if (devices.isEmpty()) {
            bluetoothDevice = null;
            bluetoothState = State.HEADSET_UNAVAILABLE;
            Log.d(TAG, "No connected bluetooth headset");
        } else {
            // Always use first device in list. Android only supports one device.
            bluetoothDevice = devices.get(0);
            bluetoothState = State.HEADSET_AVAILABLE;
            Log.d(TAG, "Connected bluetooth headset: " + "name=" + bluetoothDevice.getName() + ", " + "state=" + stateToString(bluetoothHeadset.getConnectionState(bluetoothDevice)) + ", SCO audio=" + bluetoothHeadset.isAudioConnected(bluetoothDevice));
        }
        Log.d(TAG, "updateDevice done: BT state=" + bluetoothState);
    }

    /**
     * Stubs for test mocks.
     */
    protected AudioManager getAudioManager(Context context) {
        return (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    }

    protected void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        apprtcContext.registerReceiver(receiver, filter);
    }

    protected void unregisterReceiver(BroadcastReceiver receiver) {
        apprtcContext.unregisterReceiver(receiver);
    }

    protected boolean getBluetoothProfileProxy(Context context, BluetoothProfile.ServiceListener listener, int profile) {
        return bluetoothAdapter.getProfileProxy(context, listener, profile);
    }

    protected boolean hasPermission(Context context, String permission) {
        return apprtcContext.checkPermission(permission, Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * Logs the state of the local Bluetooth adapter.
     */
    @SuppressLint("HardwareIds")
    protected void logBluetoothAdapterInfo(BluetoothAdapter localAdapter) {
        Log.d(TAG, "BluetoothAdapter: " + "enabled=" + localAdapter.isEnabled() + ", " + "state=" + stateToString(localAdapter.getState()) + ", " + "name=" + localAdapter.getName() + ", " + "address=" + localAdapter.getAddress());
        // Log the set of BluetoothDevice objects that are bonded (paired) to the local adapter.
        Set<BluetoothDevice> pairedDevices = localAdapter.getBondedDevices();
        if (!pairedDevices.isEmpty()) {
            Log.d(TAG, "paired devices:");
            for (BluetoothDevice device : pairedDevices) {
                Log.d(TAG, " name=" + device.getName() + ", address=" + device.getAddress());
            }
        }
    }

    /**
     * Ensures that the audio manager updates its list of available audio devices.
     */
    private void updateAudioDeviceState() {
        Log.d(TAG, "updateAudioDeviceState");
        apprtcAudioManager.updateAudioDeviceState();
    }

    /**
     * Starts timer which times out after BLUETOOTH_SCO_TIMEOUT_MS milliseconds.
     */
    private void startTimer() {
        Log.d(TAG, "startTimer");
        handler.postDelayed(bluetoothTimeoutRunnable, BLUETOOTH_SCO_TIMEOUT_MS);
    }

    /**
     * Cancels any outstanding timer tasks.
     */
    private void cancelTimer() {
        Log.d(TAG, "cancelTimer");
        handler.removeCallbacks(bluetoothTimeoutRunnable);
    }

    /**
     * Called when start of the BT SCO channel takes too long time. Usually
     * happens when the BT device has been turned on during an ongoing call.
     */
    private void bluetoothTimeout() {
        if (bluetoothState == State.UNINITIALIZED || bluetoothHeadset == null) {
            return;
        }
        Log.d(TAG, "bluetoothTimeout: BT state=" + bluetoothState + ", " + "attempts: " + scoConnectionAttempts + ", " + "SCO is on: " + isSreplaced());
        if (bluetoothState != State.SCO_CONNECTING) {
            return;
        }
        // Bluetooth SCO should be connecting; check the latest result.
        boolean scoConnected = false;
        List<BluetoothDevice> devices = bluetoothHeadset.getConnectedDevices();
        if (devices.size() > 0) {
            bluetoothDevice = devices.get(0);
            if (bluetoothHeadset.isAudioConnected(bluetoothDevice)) {
                Log.d(TAG, "SCO connected with " + bluetoothDevice.getName());
                scoConnected = true;
            } else {
                Log.d(TAG, "SCO is not connected with " + bluetoothDevice.getName());
            }
        }
        if (scoConnected) {
            // We thought BT had timed out, but it's actually on; updating state.
            bluetoothState = State.SCO_CONNECTED;
            scoConnectionAttempts = 0;
        } else {
            // Give up and "cancel" our request by calling stopBluetoothSco().
            Log.w(TAG, "BT failed to connect after timeout");
            stopScoAudio();
        }
        updateAudioDeviceState();
        Log.d(TAG, "bluetoothTimeout done: BT state=" + bluetoothState);
    }

    /**
     * Checks whether audio uses Bluetooth SCO.
     */
    private boolean isSreplaced() {
        return audioManager.isBluetoothSreplaced();
    }

    /**
     * Converts BluetoothAdapter states into local string representations.
     */
    private String stateToString(int state) {
        switch(state) {
            case BluetoothAdapter.STATE_DISCONNECTED:
                return "DISCONNECTED";
            case BluetoothAdapter.STATE_CONNECTED:
                return "CONNECTED";
            case BluetoothAdapter.STATE_CONNECTING:
                return "CONNECTING";
            case BluetoothAdapter.STATE_DISCONNECTING:
                return "DISCONNECTING";
            case BluetoothAdapter.STATE_OFF:
                return "OFF";
            case BluetoothAdapter.STATE_ON:
                return "ON";
            case BluetoothAdapter.STATE_TURNING_OFF:
                // Indicates the local Bluetooth adapter is turning off. Local clients should immediately
                // attempt graceful disconnection of any remote links.
                return "TURNING_OFF";
            case BluetoothAdapter.STATE_TURNING_ON:
                // Indicates the local Bluetooth adapter is turning on. However local clients should wait
                // for STATE_ON before attempting to use the adapter.
                return "TURNING_ON";
            default:
                return "INVALID";
        }
    }
}

19 Source : AppRTCBluetoothManager.java
with ISC License
from zxcpoiu

/**
 * Logs the state of the local Bluetooth adapter.
 */
@SuppressLint("HardwareIds")
protected void logBluetoothAdapterInfo(BluetoothAdapter localAdapter) {
    Log.d(TAG, "BluetoothAdapter: " + "enabled=" + localAdapter.isEnabled() + ", " + "state=" + stateToString(localAdapter.getState()) + ", " + "name=" + localAdapter.getName() + ", " + "address=" + localAdapter.getAddress());
    // Log the set of BluetoothDevice objects that are bonded (paired) to the local adapter.
    Set<BluetoothDevice> pairedDevices = localAdapter.getBondedDevices();
    if (!pairedDevices.isEmpty()) {
        Log.d(TAG, "paired devices:");
        for (BluetoothDevice device : pairedDevices) {
            Log.d(TAG, " name=" + device.getName() + ", address=" + device.getAddress());
        }
    }
}

19 Source : Nes30Connection.java
with BSD 2-Clause "Simplified" License
from zugaldia

/**
 * Remove bond with the specific device.
 */
public void removeBond(BluetoothDevice device) {
    try {
        Timber.w("Removing bond.");
        Method m = device.getClreplaced().getMethod("removeBond", (Clreplaced[]) null);
        m.invoke(device, (Object[]) null);
    } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
        Timber.e(e, "Failed to remove bond.");
    }
}

19 Source : Nes30Connection.java
with BSD 2-Clause "Simplified" License
from zugaldia

/**
 * Pair with the specific device.
 */
public boolean createBond(BluetoothDevice device) {
    boolean result = device.createBond();
    Timber.d("Creating bond with: %s/%s/%b", device.getName(), device.getAddress(), result);
    return result;
}

19 Source : Nes30Connection.java
with BSD 2-Clause "Simplified" License
from zugaldia

/**
 * Checks whether the device is already paired.
 */
public BluetoothDevice getSelectedDevice() {
    Set<BluetoothDevice> pairedDevices = getPairedDevices();
    for (BluetoothDevice pairedDevice : pairedDevices) {
        if (isSelectedDevice(pairedDevice.getAddress())) {
            return pairedDevice;
        }
    }
    return null;
}

19 Source : MainActivity.java
with BSD 2-Clause "Simplified" License
from zugaldia

private void setupBluetooth() {
    nes30Manager = new Nes30Manager(this);
    nes30Connection = new Nes30Connection(this, RobocarConstants.NES30_MAC_ADDRESS);
    Timber.d("BT status: %b", nes30Connection.isEnabled());
    Timber.d("Paired devices: %d", nes30Connection.getPairedDevices().size());
    BluetoothDevice nes30device = nes30Connection.getSelectedDevice();
    if (nes30device == null) {
        Timber.d("Starting discovery: %b", nes30Connection.startDiscovery());
    } else {
        Timber.d("Creating bond: %b", nes30Connection.createBond(nes30device));
    }
}

19 Source : BluetoothLinkProvider.java
with GNU General Public License v2.0
from ZorinOS

public void disconnectedLink(BluetoothLink link, String deviceId, BluetoothDevice remoteAddress) {
    sockets.remove(remoteAddress);
    visibleComputers.remove(deviceId);
    connectionLost(link);
}

19 Source : GrblBluetoothSerialService.java
with GNU General Public License v3.0
from zeevy

private synchronized void connected(BluetoothSocket socket, BluetoothDevice device, final String socketType) {
    // Cancel the thread that completed the connection
    if (mConnectThread != null) {
        mConnectThread.cancel();
        mConnectThread = null;
    }
    // Cancel any thread currently running a connection
    if (mConnectedThread != null) {
        mConnectedThread.cancel();
        mConnectedThread = null;
    }
    // Cancel the accept thread because we only want to connect to one device
    if (mSecureAcceptThread != null) {
        mSecureAcceptThread.cancel();
        mSecureAcceptThread = null;
    }
    if (mInsecureAcceptThread != null) {
        mInsecureAcceptThread.cancel();
        mInsecureAcceptThread = null;
    }
    // Start the thread to manage the connection and perform transmissions
    mConnectedThread = new ConnectedThread(socket, socketType);
    mConnectedThread.start();
    // Send the name of the connected device back to the UI Activity
    if (mHandler != null) {
        Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        bundle.putString(Constants.DEVICE_NAME, device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);
    }
    updateUserInterfacereplacedle();
    try {
        wait(250);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    if (!isGrblFound)
        serialWriteByte(GrblUtils.GRBL_RESET_COMMAND);
}

19 Source : GrblBluetoothSerialService.java
with GNU General Public License v3.0
from zeevy

synchronized void connect(BluetoothDevice device, boolean secure) {
    // Cancel any thread attempting to make a connection
    if (mState == STATE_CONNECTING) {
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }
    }
    // Cancel any thread currently running a connection
    if (mConnectedThread != null) {
        mConnectedThread.cancel();
        mConnectedThread = null;
    }
    // Start the thread to connect with the given device
    mConnectThread = new ConnectThread(device, secure);
    mConnectThread.start();
    // Update UI replacedle
    updateUserInterfacereplacedle();
}

19 Source : GrblBluetoothSerialService.java
with GNU General Public License v3.0
from zeevy

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    this.start();
    if (intent != null) {
        String deviceAddress = intent.getStringExtra(KEY_MAC_ADDRESS);
        if (deviceAddress != null) {
            try {
                BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress.toUpperCase());
                this.connect(device, false);
            } catch (IllegalArgumentException e) {
                EventBus.getDefault().post(new UiToastEvent(e.getMessage(), true, true));
                disconnectService();
                stopSelf();
            }
        }
    } else {
        EventBus.getDefault().post(new UiToastEvent(getString(R.string.text_unknown_error), true, true));
        disconnectService();
        stopSelf();
    }
    return Service.START_NOT_STICKY;
}

19 Source : BluetoothController.java
with GNU General Public License v3.0
from xManager-v2

public synchronized void connected(BluetoothSocket socket, final BluetoothDevice device, BluetoothConnect bluetoothConnect, final BluetoothConnect.BluetoothConnectionListener listener, final String tag) {
    if (connectThread != null) {
        connectThread.cancel();
        connectThread = null;
    }
    if (connectedThread != null) {
        connectedThread.cancel();
        connectedThread = null;
    }
    if (acceptThread != null) {
        acceptThread.cancel();
        acceptThread = null;
    }
    connectedThread = new ConnectedThread(socket, bluetoothConnect, listener, tag);
    connectedThread.start();
    bluetoothConnect.getActivity().runOnUiThread(new Runnable() {

        @Override
        public void run() {
            HashMap<String, Object> deviceMap = new HashMap<>();
            deviceMap.put("name", device.getName());
            deviceMap.put("address", device.getAddress());
            listener.onConnected(tag, deviceMap);
        }
    });
}

19 Source : BluetoothController.java
with GNU General Public License v3.0
from xManager-v2

public synchronized void connect(BluetoothDevice device, BluetoothConnect bluetoothConnect, BluetoothConnect.BluetoothConnectionListener listener, String tag, UUID uuid, BluetoothAdapter bluetoothAdapter) {
    if (state.equals(STATE_CONNECTING)) {
        if (connectThread != null) {
            connectThread.cancel();
            connectThread = null;
        }
    }
    if (connectedThread != null) {
        connectedThread.cancel();
        connectedThread = null;
    }
    connectThread = new ConnectThread(device, bluetoothConnect, listener, tag, uuid, bluetoothAdapter);
    connectThread.start();
}

19 Source : BluetoothConnect.java
with GNU General Public License v3.0
from xManager-v2

public void startConnection(BluetoothConnectionListener listener, String uuid, String address, String tag) {
    BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
    BluetoothController.getInstance().connect(device, this, listener, tag, UUID.fromString(uuid), bluetoothAdapter);
}

19 Source : BluetoothConnect.java
with GNU General Public License v3.0
from xManager-v2

public void startConnection(BluetoothConnectionListener listener, String address, String tag) {
    BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
    BluetoothController.getInstance().connect(device, this, listener, tag, UUID.fromString(DEFAULT_UUID), bluetoothAdapter);
}

19 Source : BluetoothConnect.java
with GNU General Public License v3.0
from xManager-v2

public void getPairedDevices(ArrayList<HashMap<String, Object>> results) {
    Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
    if (pairedDevices.size() > 0) {
        for (BluetoothDevice device : pairedDevices) {
            HashMap<String, Object> result = new HashMap<>();
            result.put("name", device.getName());
            result.put("address", device.getAddress());
            results.add(result);
        }
    }
}

19 Source : ScanCallback.java
with Apache License 2.0
from xiaoyaoyou1212

@Override
public void onLeScan(BluetoothDevice bluetoothDevice, int rssi, byte[] scanRecord) {
    BluetoothLeDevice bluetoothLeDevice = new BluetoothLeDevice(bluetoothDevice, rssi, scanRecord, System.currentTimeMillis());
    BluetoothLeDevice filterDevice = onFilter(bluetoothLeDevice);
    if (filterDevice != null) {
        bluetoothLeDeviceStore.addDevice(filterDevice);
        scanCallback.onDeviceFound(filterDevice);
    }
}

19 Source : BluetoothHeadsetBroadcastReceiver.java
with GNU General Public License v2.0
from wzc25151

@Override
public void onReceive(Context context, Intent intent) {
    BluetoothDevice mConnectedHeadset = null;
    String action = intent.getAction();
    int state = BluetoothHeadset.STATE_DISCONNECTED;
    int previousState = intent.getIntExtra(BluetoothHeadset.EXTRA_PREVIOUS_STATE, BluetoothHeadset.STATE_DISCONNECTED);
    if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
        state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED);
        if (state == BluetoothHeadset.STATE_CONNECTED) {
            mConnectedHeadset = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            log.debug("AudioManager ACTION_CONNECTION_STATE_CHANGED " + mConnectedHeadset + " " + state);
            HeadsetPlugManager.getInstance().notifyHeadsetPlugged(true, HeadsetPlugManager.BLUETOOTH, mConnectedHeadset);
        } else if (state == BluetoothHeadset.STATE_DISCONNECTED) {
            mConnectedHeadset = null;
            log.debug("AudioManager ACTION_CONNECTION_STATE_CHANGED " + " " + state);
            HeadsetPlugManager.getInstance().notifyHeadsetPlugged(false, HeadsetPlugManager.BLUETOOTH);
        }
    } else if (BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED.equals(action)) {
        state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
        log.debug("AudioManager ACTION_AUDIO_STATE_CHANGED " + " " + state);
        if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
        // bluetooth audio connected. you send audio stream to headset now!!!
        } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
        }
    } else if (AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED.equals(action)) {
        state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
        log.debug("AudioManager ACTION_SCO_AUDIO_STATE_UPDATED " + " " + state);
    }
}

19 Source : DeviceListAdapter.java
with MIT License
from Wojtek120

/**
 * TODO OPISAC j.w.
 * @param position
 * @param convertView
 * @param parent
 * @return
 */
public View getView(int position, View convertView, ViewGroup parent) {
    // TODO ogarnac
    convertView = mLayoutInflater.inflate(mViewResourceId, null);
    BluetoothDevice device = mDevices.get(position);
    if (device != null) {
        TextView deviceName = convertView.findViewById(R.id.tvDeviceName);
        TextView deviceAddress = convertView.findViewById(R.id.tvDeviceAddress);
        if (deviceName != null) {
            deviceName.setText(device.getName());
        }
        if (deviceAddress != null) {
            deviceAddress.setText(device.getAddress());
        }
    }
    return convertView;
}

19 Source : BluetoothConnection.java
with MIT License
from Wojtek120

/**
 * Funkcja wypisujaca sparowane urzadzenia
 */
public void listPairedDevices() {
    Set<BluetoothDevice> all_devices = mBluetoothAdapter.getBondedDevices();
    if (all_devices.size() > 0) {
        for (BluetoothDevice currentDevice : all_devices) {
            Log.i("PairedDevices", "PairedDevices:" + currentDevice.getName() + ": " + currentDevice.getAddress());
            mDevicePairedListAdapter = new DeviceListAdapter(mContext, R.layout.device_adapter_view, mBluetoothPairedDevices);
            mBluetoothPairedDevices.add(currentDevice);
            lvPairedDevices.setAdapter(mDevicePairedListAdapter);
        }
    }
}

19 Source : BluetoothConnection.java
with MIT License
from Wojtek120

/**
 * Uruchamia watek ConnectionThread do nawiazania polaczenia
 * @see ConnectionThread
 */
private void startClient(BluetoothDevice device) {
    Log.d("startClient", "startClient: Started.");
    // uruchamia progress dialog
    mProgressDialog = ProgressDialog.show(mContext, mContext.getString(R.string.connectingProgress), mContext.getString(R.string.please_wait), true);
    mConnectionThread = new ConnectionThread(device);
    mConnectionThread.start();
}

19 Source : BluetoothConnection.java
with MIT License
from Wojtek120

/**
 * Uruchamia watek do zarzadzania polaczeniem i wysylania danych
 */
private void connected(BluetoothSocket mmSocket, BluetoothDevice mmDevice) {
    Log.d("connected", "connected: Starting.");
    mConnectedThread = new ConnectedThread(mmSocket);
    mConnectedThread.start();
}

19 Source : Connection.java
with Apache License 2.0
from woesss

public javax.microedition.io.Connection openConnection(String name, int mode, boolean timeouts) throws IOException {
    if (name == null)
        throw new IllegalArgumentException("URL is null");
    System.out.println("***** Connection URL: " + name);
    int port = -1;
    int portSepIndex = name.lastIndexOf(':');
    if (portSepIndex == -1) {
        throw new IllegalArgumentException("Port missing");
    }
    String host = name.substring("btspp://".length(), portSepIndex);
    int argsStart = name.indexOf(";");
    String[] args = name.substring(argsStart + 1).split(";");
    boolean authenticate = false, encrypt = false, secure;
    String srvname = "";
    for (int i = 0; i < args.length; i++) {
        if (args[i].startsWith("authenticate="))
            authenticate = Boolean.parseBoolean(args[i].substring(args[i].indexOf("=") + 1));
        if (args[i].startsWith("encrypt="))
            encrypt = Boolean.parseBoolean(args[i].substring(args[i].indexOf("=") + 1));
        if (args[i].startsWith("name="))
            srvname = args[i].substring(args[i].indexOf("=") + 1);
        if (args[i].startsWith("skipAfterWrite="))
            skipAfterWrite = Boolean.parseBoolean(args[i].substring(args[i].indexOf("=") + 1));
    }
    if (argsStart == -1) {
        argsStart = name.length() - 1;
    }
    secure = authenticate && encrypt;
    String uuid = name.substring(portSepIndex + 1, argsStart);
    connUuid = new javax.bluetooth.UUID(uuid, false);
    java.util.UUID btUuid = connUuid.uuid;
    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    if (adapter.isDiscovering())
        adapter.cancelDiscovery();
    // java.util.UUID btUuid = getJavaUUID(uuid);
    // "localhost" indicates that we are acting as server
    if (host.equals("localhost")) {
        // btUuid = new javax.bluetooth.UUID(0x1101).uuid;
        // Android 6.0.1 bug: UUID is reversed
        // see https://issuetracker.google.com/issues/37075233
        UUID NameUuid = new UUID(0x1102);
        nameServerSocket = adapter.listenUsingInsecureRfcommWithServiceRecord(srvname, NameUuid.uuid);
        String finalSrvname = srvname;
        // Send service name to client
        Thread connectThread = new Thread(() -> {
            try {
                byte[] dstByte = new byte[256];
                byte[] srcByte = finalSrvname.getBytes();
                System.arraycopy(srcByte, 0, dstByte, 0, srcByte.length);
                BluetoothSocket connectSocket = nameServerSocket.accept();
                OutputStream os = connectSocket.getOutputStream();
                os.write(0);
                os.write(dstByte);
                os.flush();
                nameServerSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        connectThread.start();
        if (secure)
            serverSocket = adapter.listenUsingRfcommWithServiceRecord(finalSrvname, btUuid);
        else
            serverSocket = adapter.listenUsingInsecureRfcommWithServiceRecord(finalSrvname, btUuid);
        return this;
    } else {
        StringBuilder sb = new StringBuilder(host);
        for (int i = 2; i < sb.length(); i += 3) sb.insert(i, ':');
        String addr = sb.toString();
        BluetoothDevice dev = adapter.getRemoteDevice(addr);
        if (secure)
            socket = dev.createRfcommSocketToServiceRecord(btUuid);
        else
            socket = dev.createInsecureRfcommSocketToServiceRecord(btUuid);
        try {
            socket.connect();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new SPPConnectionImpl(socket, false);
    }
}

19 Source : Connection.java
with Apache License 2.0
from woesss

public javax.microedition.io.Connection openConnection(String name, int mode, boolean timeouts) throws IOException {
    if (name == null)
        throw new IllegalArgumentException("URL is null");
    System.out.println("***** Connection URL: " + name);
    int port = -1;
    int portSepIndex = name.lastIndexOf(':');
    if (portSepIndex == -1) {
        throw new IllegalArgumentException("Port missing");
    }
    String host = name.substring("btl2cap://".length(), portSepIndex);
    int argsStart = name.indexOf(";");
    String[] args = name.substring(argsStart + 1).split(";");
    boolean authenticate = false, encrypt = false, secure;
    String srvname = "";
    for (int i = 0; i < args.length; i++) {
        if (args[i].startsWith("authenticate="))
            authenticate = Boolean.parseBoolean(args[i].substring(args[i].indexOf("=") + 1));
        if (args[i].startsWith("encrypt="))
            encrypt = Boolean.parseBoolean(args[i].substring(args[i].indexOf("=") + 1));
        if (args[i].startsWith("name="))
            srvname = args[i].substring(args[i].indexOf("=") + 1);
        if (args[i].startsWith("skipAfterWrite="))
            skipAfterWrite = Boolean.parseBoolean(args[i].substring(args[i].indexOf("=") + 1));
    }
    if (argsStart == -1) {
        argsStart = name.length() - 1;
    }
    secure = authenticate && encrypt;
    String uuid = name.substring(portSepIndex + 1, argsStart);
    connUuid = new javax.bluetooth.UUID(uuid, false);
    java.util.UUID btUuid = connUuid.uuid;
    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    if (adapter.isDiscovering())
        adapter.cancelDiscovery();
    // java.util.UUID btUuid = getJavaUUID(uuid);
    // "localhost" indicates that we are acting as server
    if (host.equals("localhost")) {
        // btUuid = new javax.bluetooth.UUID(0x1101).uuid;
        // Android 6.0.1 bug: UUID is reversed
        // see https://issuetracker.google.com/issues/37075233
        UUID NameUuid = new UUID(0x1102);
        nameServerSocket = adapter.listenUsingInsecureRfcommWithServiceRecord(srvname, NameUuid.uuid);
        String finalSrvname = srvname;
        // Send service name to client
        Thread connectThread = new Thread(() -> {
            try {
                byte[] dstByte = new byte[256];
                byte[] srcByte = finalSrvname.getBytes();
                System.arraycopy(srcByte, 0, dstByte, 0, srcByte.length);
                BluetoothSocket connectSocket = nameServerSocket.accept();
                OutputStream os = connectSocket.getOutputStream();
                os.write(1);
                os.write(dstByte);
                os.flush();
                nameServerSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        connectThread.start();
        if (secure)
            serverSocket = adapter.listenUsingRfcommWithServiceRecord(finalSrvname, btUuid);
        else
            serverSocket = adapter.listenUsingInsecureRfcommWithServiceRecord(finalSrvname, btUuid);
        return this;
    } else {
        StringBuilder sb = new StringBuilder(host);
        for (int i = 2; i < sb.length(); i += 3) sb.insert(i, ':');
        String addr = sb.toString();
        BluetoothDevice dev = adapter.getRemoteDevice(addr);
        if (secure)
            socket = dev.createRfcommSocketToServiceRecord(btUuid);
        else
            socket = dev.createInsecureRfcommSocketToServiceRecord(btUuid);
        try {
            socket.connect();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new L2CAPConnectionImpl(socket);
    }
}

19 Source : RemoteDevice.java
with Apache License 2.0
from woesss

public clreplaced RemoteDevice {

    BluetoothDevice dev;

    RemoteDevice(BluetoothDevice dev) {
        this.dev = dev;
    }

    static String javaToAndroidAddress(String addr) {
        StringBuilder sb = new StringBuilder(addr);
        for (int i = 2; i < sb.length(); i += 3) sb.insert(i, ':');
        return sb.toString();
    }

    protected RemoteDevice(String address) {
        if (address == null) {
            throw new NullPointerException("address is null");
        }
        dev = DiscoveryAgent.adapter.getRemoteDevice(javaToAndroidAddress(address));
    }

    public String getFriendlyName(boolean alwaysAsk) throws IOException {
        String name = dev.getName();
        if (name == null) {
            name = "";
        }
        return name;
    }

    public final String getBluetoothAddress() {
        return dev.getAddress().replace(":", "");
    }

    public boolean equals(Object obj) {
        if (obj == null || !(obj instanceof RemoteDevice))
            return false;
        return dev.equals(((RemoteDevice) obj).dev);
    }

    public int hashCode() {
        return dev.hashCode();
    }

    public static RemoteDevice getRemoteDevice(Connection conn) throws IOException {
        if (conn == null)
            throw new NullPointerException("conn is null");
        if (!(conn instanceof org.microemu.cldc.btspp.SPPConnectionImpl || conn instanceof org.microemu.cldc.btl2cap.L2CAPConnectionImpl))
            throw new java.lang.IllegalArgumentException("not a RFCOMM connection");
        if (conn instanceof org.microemu.cldc.btspp.SPPConnectionImpl) {
            org.microemu.cldc.btspp.SPPConnectionImpl connection = (org.microemu.cldc.btspp.SPPConnectionImpl) conn;
            if (connection.socket == null)
                throw new IOException("socket is null");
            return new RemoteDevice(connection.socket.getRemoteDevice());
        } else {
            org.microemu.cldc.btl2cap.L2CAPConnectionImpl connection = (org.microemu.cldc.btl2cap.L2CAPConnectionImpl) conn;
            if (connection.socket == null)
                throw new IOException("socket is null");
            return new RemoteDevice(connection.socket.getRemoteDevice());
        }
    }

    public boolean authenticate() throws IOException {
        return false;
    }

    public boolean authorize(javax.microedition.io.Connection conn) throws IOException {
        return false;
    }

    public boolean encrypt(javax.microedition.io.Connection conn, boolean on) throws IOException {
        return false;
    }

    public boolean isAuthenticated() {
        return false;
    }

    public boolean isAuthorized(javax.microedition.io.Connection conn) throws IOException {
        return false;
    }

    public boolean isEncrypted() {
        return false;
    }

    public boolean isTrustedDevice() {
        return false;
    }
}

19 Source : DiscoveryAgent.java
with Apache License 2.0
from woesss

public RemoteDevice[] retrieveDevices(int option) {
    Set<BluetoothDevice> set;
    if (option == CACHED) {
        set = discoveredList;
    } else if (option == PREKNOWN) {
        set = adapter.getBondedDevices();
    } else {
        throw new IllegalArgumentException();
    }
    RemoteDevice[] devices = new RemoteDevice[set.size()];
    int i = 0;
    for (BluetoothDevice device : set) devices[i++] = new RemoteDevice(device);
    return devices;
}

19 Source : BleConnect.java
with MIT License
from wladimir-computin

public clreplaced BleConnect extends BaseConnect implements IDataTransfer, IRetransmissionHandle, ITimerSendQueueHandle {

    private final int SEND_LEN = 20;

    BaseCommand bleStateCommand;

    private BluetoothGattCharacteristic characterWrite;

    public LinkedBlockingDeque<Object> cmdQuene = new LinkedBlockingDeque();

    public LinkedBlockingDeque<byte[]> cmdQuene2 = new LinkedBlockingDeque();

    public int[] cmds = new int[] { 193, 201, 202, 203, 204 };

    private Context context;

    private BluetoothDevice device;

    private ResultListener gh2ResultListener;

    boolean isWait = false;

    private long lastTime;

    Logger logger = LoggerFactory.getLogger("gh2_communication_log");

    private IBleSendData mBleSendDataHandle;

    private CheckDeviceConnectThread mCheckDeviceConnectThread;

    private DeviceConnectState mDeviceConnectState = DeviceConnectState.IDEL;

    private ReadThread mReadThread;

    private RetransmissionThread mRetransmissionThread;

    private TimerSendQueueThread mTimerSendQueueThread;

    private WriteThread mWriteThread;

    private Parser p = new Parser();

    public clreplaced CheckDeviceConnectThread extends Thread {

        private boolean isLoop = true;

        public void exit() {
            this.isLoop = false;
            interrupt();
        }

        public void run() {
            BleConnect.this.receiveLog(" CheckDeviceConnectThread run");
            while (this.isLoop) {
                if (System.currentTimeMillis() - BleConnect.this.lastTime > 2000 && BleConnect.this.cmdQuene.size() <= 0 && Constants.isCheckDeviceConnect && SessionManager.getInstance().hreplacedession()) {
                    BleConnect.this.sendCmd(BleConnect.this.bleStateCommand);
                }
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public clreplaced ReadThread extends Thread {

        private boolean mExit;

        public void releaseConnection() {
            this.mExit = true;
            interrupt();
        }

        public void run() {
            while (!this.mExit) {
                try {
                    if (BleConnect.this.cmdQuene2.isEmpty()) {
                        Thread.sleep(100);
                    } else {
                        byte[] data = (byte[]) BleConnect.this.cmdQuene2.poll();
                        if (data != null) {
                            BleConnect.this.gh2ResultListener.messageReceived(data);
                            BleConnect.this.receiveLog(ByteUtil.bytesToHexString(data) + "=======");
                        }
                    }
                } catch (Exception e) {
                    BleConnect.this.receiveLog(" sessionhandler writethread error " + e.toString());
                    return;
                }
            }
        }
    }

    public clreplaced WriteThread extends Thread {

        private boolean mExit;

        public void releaseConnection() {
            this.mExit = true;
            interrupt();
        }

        public void run() {
            while (!this.mExit) {
                try {
                    if (BleConnect.this.cmdQuene.isEmpty()) {
                        BleConnect.this.sendSignal();
                    } else {
                        BaseCommand cmd = (BaseCommand) BleConnect.this.cmdQuene.poll();
                        if (cmd != null) {
                            cmd.setLastSendTime(SystemClock.uptimeMillis());
                            if (cmd.isAddToSendQueue()) {
                                if (cmd.isTimerCmd()) {
                                    BleConnect.this.mTimerSendQueueThread.addToSendList(cmd);
                                } else {
                                    BleConnect.this.mRetransmissionThread.addToSendList(cmd);
                                }
                            }
                            BleConnect.this.sendDividedData(cmd.getMsgGroudId(), cmd.getMsgId(), cmd.getCmdData(), cmd.getCmdData().length);
                        }
                    }
                } catch (Exception e) {
                    BleConnect.this.receiveLog(" sessionhandler writethread error " + e.toString());
                    return;
                }
            }
        }
    }

    public BleConnect(IBleSendData mIBleSendData, ResultListener listener) {
        this.mBleSendDataHandle = mIBleSendData;
        this.gh2ResultListener = listener;
    }

    public void setBleState(BaseCommand bleStateCommand) {
        this.bleStateCommand = bleStateCommand;
    }

    public BluetoothDevice getDevice() {
        return this.device;
    }

    public void setDevice(BluetoothDevice device) {
        this.device = device;
    }

    public void sendCmd(BaseCommand cmd) {
        this.cmdQuene.offer(cmd);
        sendSignal();
    }

    public void sendJsonCmd(BaseCommand cmd) {
    }

    public void sendTimeCmd(BaseCommand cmd) {
        sendDividedData(cmd.getMsgGroudId(), cmd.getMsgId(), cmd.getCmdData(), cmd.getCmdData().length);
    }

    public void startSession() {
        setClientAddress(this.device.getAddress());
        setClientName(this.device.getName());
        SessionManager.getInstance().addSession(this, this.device.getAddress());
        receiveLog("startSession");
        this.mWriteThread = new WriteThread();
        this.mReadThread = new ReadThread();
        this.mRetransmissionThread = new RetransmissionThread(this);
        this.mTimerSendQueueThread = new TimerSendQueueThread();
        this.gh2ResultListener.setRetransmissionHandle(this);
        this.gh2ResultListener.setTimerSendQueueHandle(this);
        if (this.mWriteThread != null) {
            this.mWriteThread.start();
        }
        if (this.mReadThread != null) {
            this.mReadThread.start();
        }
        if (this.mRetransmissionThread != null) {
            this.mRetransmissionThread.start();
        }
        if (this.mTimerSendQueueThread != null) {
            this.mTimerSendQueueThread.start();
        }
    }

    public void startRetransmissionThread() {
        receiveLog("" + hashCode() + " 蓝牙通途收发启动.................");
        if (this.mCheckDeviceConnectThread == null) {
            receiveLog("" + hashCode() + " 开启连接检测线程.................");
            this.mDeviceConnectState = DeviceConnectState.CONNECTED;
            SessionManager.getInstance().onDeviveState(1);
            this.mCheckDeviceConnectThread = new CheckDeviceConnectThread();
            updateTime();
            this.mCheckDeviceConnectThread.start();
        }
    }

    public void closeSession() {
        receiveLog("closeSession");
        if (this.mWriteThread != null) {
            this.mWriteThread.releaseConnection();
            this.mWriteThread = null;
        }
        if (this.mReadThread != null) {
            this.mReadThread.releaseConnection();
            this.mReadThread = null;
        }
        if (this.mCheckDeviceConnectThread != null) {
            this.mCheckDeviceConnectThread.exit();
            this.mCheckDeviceConnectThread = null;
        }
        if (this.mRetransmissionThread != null) {
            this.mRetransmissionThread.exit();
            this.mRetransmissionThread = null;
        }
        if (this.mTimerSendQueueThread != null) {
            this.mTimerSendQueueThread.exit();
            this.mTimerSendQueueThread = null;
        }
        this.mDeviceConnectState = DeviceConnectState.DISCONNECT;
        SessionManager.getInstance().onDeviveState(0);
        SessionManager.getInstance().removeSession();
    }

    public boolean isDeviceConnected() {
        return this.mDeviceConnectState == DeviceConnectState.CONNECTED;
    }

    private boolean isUpdateCmd(int groupId, int msgId) {
        if (groupId != 9) {
            return false;
        }
        for (int c : this.cmds) {
            if (msgId == c) {
                return true;
            }
        }
        return false;
    }

    private void sendDividedData(int groupId, int msgId, byte[] bytes, int len) {
        int slices;
        int divided = len / 20;
        int remainder = len % 20;
        if (remainder == 0) {
            slices = divided;
        } else {
            slices = divided + 1;
        }
        int deviceModle = bytes[22] & 255;
        int sleepTime = 10;
        if (groupId == 9 && msgId == 201 && deviceModle == 8) {
            sleepTime = 15;
        } else if (groupId == 9 && msgId == 201 && deviceModle == 3) {
            sleepTime = 15;
        }
        for (int i = 0; i < slices; i++) {
            byte[] buff;
            if (i != slices - 1 || remainder == 0) {
                buff = new byte[20];
                System.arraycopy(bytes, i * 20, buff, 0, 20);
                this.mBleSendDataHandle.sendMessage(groupId, msgId, buff, sleepTime);
            } else {
                buff = new byte[remainder];
                System.arraycopy(bytes, i * 20, buff, 0, remainder);
                this.mBleSendDataHandle.sendMessage(groupId, msgId, buff, sleepTime);
            }
        }
        updateTime();
        sendLog(ByteHexHelper.bytesToHexString(bytes));
    }

    public boolean removeFromListByCmdID(int groupId, int cmdId, int seq, LinkPacket packet) {
        if (this.mRetransmissionThread == null) {
            return false;
        }
        return this.mRetransmissionThread.removeFromListByCmdID(groupId, cmdId, seq, packet);
    }

    public boolean removeFromListByCmdIDLinkPacket4(int groupId, int cmdId, int seq, LinkPacket4 packet) {
        return false;
    }

    public boolean removeFromTimerSendQueueByCmdID(int groupId, int cmdId, int seq, LinkPacket packet) {
        if (this.mTimerSendQueueThread == null) {
            return false;
        }
        return this.mTimerSendQueueThread.removeFromListByCmdID(groupId, cmdId, seq, packet);
    }

    public void sendRestransmissionData(BaseCommand cmd) {
        sendLog("" + hashCode() + " 重发数据 seq =" + cmd.getMsgSeq() + " " + Integer.toHexString(cmd.getMsgId()));
        sendDividedData(cmd.getMsgGroudId(), cmd.getMsgId(), cmd.getCmdData(), cmd.getCmdData().length);
    }

    public void onSendTimeOut(int groupId, int cmdId, BaseCommand bcd) {
        NoticeManager.getInstance().onSendTimeOut(groupId, cmdId, bcd);
    }

    public void sendSignal() {
        synchronized (this.cmdQuene) {
            if (this.isWait) {
                this.isWait = false;
                this.cmdQuene.notify();
            } else {
                this.isWait = true;
                try {
                    this.cmdQuene.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void updateTime() {
        this.lastTime = System.currentTimeMillis();
    }

    public void receiveLog(String msg) {
        this.logger.info("                App ==>" + msg);
    }

    public void sendLog(String msg) {
        this.logger.info("             send   ==> " + msg);
    }

    public void onBleData(byte[] data) {
        this.cmdQuene2.add(data);
    }
}

19 Source : BleConnect.java
with MIT License
from wladimir-computin

public void setDevice(BluetoothDevice device) {
    this.device = device;
}

19 Source : ShadowBluetoothLEAdapter.java
with MIT License
from weliem

public void addDevice(BluetoothDevice device) {
    devices.put(device.getAddress(), device);
}

19 Source : BluetoothPeripheralTest.java
with MIT License
from weliem

@RunWith(RobolectricTestRunner.clreplaced)
@Config(manifest = Config.NONE, sdk = { M })
public clreplaced BluetoothPeripheralTest {

    private BluetoothPeripheral peripheral;

    private final Handler handler = new Handler();

    public static final UUID SERVICE_UUID = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb");

    @Mock
    private BluetoothPeripheral.InternalCallback internalCallback;

    @Mock
    private BluetoothPeripheralCallback peripheralCallback;

    @Mock
    private Context context;

    @Mock
    private BluetoothDevice device;

    @Mock
    private BluetoothGatt gatt;

    @Captor
    ArgumentCaptor<BluetoothPeripheral> captorPeripheral;

    @Captor
    ArgumentCaptor<byte[]> captorValue;

    @Captor
    ArgumentCaptor<BluetoothGattCharacteristic> captorCharacteristic;

    @Captor
    ArgumentCaptor<BluetoothGattDescriptor> captorDescriptor;

    @Captor
    ArgumentCaptor<GattStatus> captorGattStatus;

    @Before
    public void setUp() {
        openMocks(this);
        when(device.getAddress()).thenReturn("12:23:34:98:76:54");
        when(device.connectGatt(any(Context.clreplaced), anyBoolean(), any(BluetoothGattCallback.clreplaced), anyInt())).thenReturn(gatt);
        when(gatt.getDevice()).thenReturn(device);
        peripheral = new BluetoothPeripheral(context, device, internalCallback, peripheralCallback, handler);
    }

    @Test
    public void Given_a_not_connected_peripheral_when_connect_is_called_and_succeeds_then_the_state_is_connected() {
        // When
        peripheral.connect();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        ArgumentCaptor<BluetoothGattCallback> captor = ArgumentCaptor.forClreplaced(BluetoothGattCallback.clreplaced);
        verify(device).connectGatt(any(Context.clreplaced), anyBoolean(), captor.capture(), anyInt());
        BluetoothGattCallback callback = captor.getValue();
        callback.onConnectionStateChange(gatt, GATT_SUCCESS, STATE_CONNECTED);
        // Then
        replacedertEquals(CONNECTED, peripheral.getState());
    }

    @Test
    public void Given_a_not_connected_peripheral_when_autoConnect_is_called_and_succeeds_then_the_state_is_connected() {
        // When
        peripheral.autoConnect();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        ArgumentCaptor<BluetoothGattCallback> captor = ArgumentCaptor.forClreplaced(BluetoothGattCallback.clreplaced);
        ArgumentCaptor<Boolean> autoConnectCaptor = ArgumentCaptor.forClreplaced(Boolean.clreplaced);
        verify(device).connectGatt(any(Context.clreplaced), autoConnectCaptor.capture(), captor.capture(), anyInt());
        replacedertTrue(autoConnectCaptor.getValue());
        BluetoothGattCallback callback = captor.getValue();
        callback.onConnectionStateChange(gatt, GATT_SUCCESS, STATE_CONNECTED);
        // Then
        replacedertEquals(CONNECTED, peripheral.getState());
    }

    @Test
    public void Given_a_connected_peripheral_when_cancelConnection_is_called_then_disconnect_is_called_and_state_is_disconnected_when_successful() {
        // Given
        peripheral.connect();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        ArgumentCaptor<BluetoothGattCallback> captor = ArgumentCaptor.forClreplaced(BluetoothGattCallback.clreplaced);
        verify(device).connectGatt(any(Context.clreplaced), anyBoolean(), captor.capture(), anyInt());
        BluetoothGattCallback callback = captor.getValue();
        callback.onConnectionStateChange(gatt, GATT_SUCCESS, STATE_CONNECTED);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // When
        peripheral.cancelConnection();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).disconnect();
        replacedertEquals(DISCONNECTING, peripheral.getState());
        // When
        callback.onConnectionStateChange(gatt, GATT_SUCCESS, STATE_DISCONNECTED);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).close();
        replacedertEquals(DISCONNECTED, peripheral.getState());
    }

    @Test
    public void Given_an_autoConnect_pending_when_cancelConnection_is_called_then_a_disconnect_is_done() {
        // Given
        peripheral.autoConnect();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // When
        peripheral.cancelConnection();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).disconnect();
        verify(gatt).close();
        replacedertEquals(DISCONNECTED, peripheral.getState());
    }

    @Test
    public void When_calling_cancelConnection_on_an_unconnected_peripheral_then_disconnect_is_not_called() {
        // When
        peripheral.cancelConnection();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt, never()).disconnect();
    }

    @Test
    public void When_calling_getAddress_then_the_peripherals_address_is_returned() {
        replacedertEquals("12:23:34:98:76:54", peripheral.getAddress());
    }

    @Test
    public void Given_a_connected_peripheral_when_the_name_is_null_then_an_empty_string_is_returned() {
        // Given
        when(device.getName()).thenReturn(null);
        connectAndGetCallback();
        // When
        String name = peripheral.getName();
        // Then
        replacedertNotNull(name);
        replacedertEquals("", name);
    }

    @Test
    public void Given_a_connected_peripheral_when_the_name_becomes_null_after_having_a_name_then_first_name_is_returned() {
        // Given
        when(device.getName()).thenReturn("first");
        connectAndGetCallback();
        // When
        String name = peripheral.getName();
        // Then
        replacedertNotNull(name);
        replacedertEquals("first", name);
        // When
        when(device.getName()).thenReturn(null);
        // Then
        replacedertEquals("first", peripheral.getName());
    }

    @Test
    public void Given_a_connected_peripheral_and_services_discovered_when_getService_is_called_the_right_service_is_returned() {
        // Given
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        when(gatt.getService(SERVICE_UUID)).thenReturn(service);
        connectAndGetCallback();
        // When
        BluetoothGattService receivedService = peripheral.getService(SERVICE_UUID);
        // Then
        replacedertNotNull(receivedService);
        replacedertEquals(service, receivedService);
    }

    @Test
    public void Given_a_connected_peripheral_and_services_discovered_when_getService_for_unknown_service_is_called_then_null_is_returned() {
        // Given
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        when(gatt.getService(SERVICE_UUID)).thenReturn(service);
        connectAndGetCallback();
        // When
        BluetoothGattService receivedService = peripheral.getService(UUID.fromString("00001000-0000-1000-8000-00805f9b34fb"));
        // Then
        replacedertNull(receivedService);
    }

    @Test
    public void Given_a_connected_peripheral_and_services_discovered_when_getCharacteristic_is_called_the_right_characteristic_is_returned() {
        // Given
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_INDICATE, 0);
        service.addCharacteristic(characteristic);
        when(gatt.getService(SERVICE_UUID)).thenReturn(service);
        connectAndGetCallback();
        // When
        BluetoothGattCharacteristic receivedCharacteristic = peripheral.getCharacteristic(SERVICE_UUID, UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"));
        // Then
        replacedertNotNull(receivedCharacteristic);
        replacedertEquals(characteristic, receivedCharacteristic);
    }

    @Test
    public void Given_a_connected_peripheral_and_services_discovered_when_getCharacteristic_with_unknownUUID_is_called_then_null_is_returned() {
        // Given
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_INDICATE, 0);
        service.addCharacteristic(characteristic);
        when(gatt.getService(SERVICE_UUID)).thenReturn(service);
        connectAndGetCallback();
        // When
        BluetoothGattCharacteristic receivedCharacteristic = peripheral.getCharacteristic(SERVICE_UUID, UUID.fromString("00002AAA-0000-1000-8000-00805f9b34fb"));
        // Then
        replacedertNull(receivedCharacteristic);
    }

    @Test
    public void Given_a_connected_peripheral_with_a_characteristic_supporting_indications_when_setNotify_with_true_is_called_then_the_indication_is_enabled() {
        // Given
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_INDICATE, 0);
        BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"), 0);
        service.addCharacteristic(characteristic);
        characteristic.addDescriptor(descriptor);
        when(gatt.getServices()).thenReturn(Collections.singletonList(service));
        when(gatt.setCharacteristicNotification(characteristic, true)).thenReturn(true);
        BluetoothGattCallback callback = connectAndGetCallback();
        // When
        peripheral.setNotify(characteristic, true);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).setCharacteristicNotification(characteristic, true);
        replacedertEquals(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE[0], descriptor.getValue()[0]);
        replacedertEquals(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE[1], descriptor.getValue()[1]);
        verify(gatt).writeDescriptor(descriptor);
        callback.onDescriptorWrite(gatt, descriptor, 0);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(peripheralCallback).onNotificationStateUpdate(peripheral, characteristic, GattStatus.SUCCESS);
        replacedertTrue(peripheral.isNotifying(characteristic));
        replacedertEquals(1, peripheral.getNotifyingCharacteristics().size());
    }

    @Test
    public void Given_a_connected_peripheral_with_a_characteristic_supporting_notifications_when_setNotify_with_true_is_called_then_the_notification_is_enabled() {
        // Given
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_NOTIFY, 0);
        BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"), 0);
        service.addCharacteristic(characteristic);
        characteristic.addDescriptor(descriptor);
        when(gatt.getServices()).thenReturn(Collections.singletonList(service));
        when(gatt.setCharacteristicNotification(characteristic, true)).thenReturn(true);
        BluetoothGattCallback callback = connectAndGetCallback();
        // When
        peripheral.setNotify(characteristic, true);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt, timeout(1000)).setCharacteristicNotification(characteristic, true);
        replacedertEquals(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE[0], descriptor.getValue()[0]);
        replacedertEquals(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE[1], descriptor.getValue()[1]);
        verify(gatt, timeout(1000)).writeDescriptor(descriptor);
        callback.onDescriptorWrite(gatt, descriptor, 0);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(peripheralCallback).onNotificationStateUpdate(peripheral, characteristic, GattStatus.SUCCESS);
        replacedertTrue(peripheral.isNotifying(characteristic));
        replacedertEquals(1, peripheral.getNotifyingCharacteristics().size());
    }

    @Test
    public void Given_a_connected_peripheral_with_a_characteristic_supporting_notifications_when_setNotify_with_false_is_called_then_the_notification_is_disabled() {
        // Given
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_NOTIFY, 0);
        BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"), 0);
        service.addCharacteristic(characteristic);
        characteristic.addDescriptor(descriptor);
        when(gatt.getServices()).thenReturn(Collections.singletonList(service));
        when(gatt.setCharacteristicNotification(characteristic, false)).thenReturn(true);
        BluetoothGattCallback callback = connectAndGetCallback();
        // When
        peripheral.setNotify(characteristic, false);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).setCharacteristicNotification(characteristic, false);
        replacedertEquals(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE[0], descriptor.getValue()[0]);
        replacedertEquals(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE[1], descriptor.getValue()[1]);
        verify(gatt).writeDescriptor(descriptor);
        callback.onDescriptorWrite(gatt, descriptor, 0);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(peripheralCallback).onNotificationStateUpdate(peripheral, characteristic, GattStatus.SUCCESS);
        replacedertFalse(peripheral.isNotifying(characteristic));
        replacedertEquals(0, peripheral.getNotifyingCharacteristics().size());
    }

    @Test
    public void Given_a_connected_peripheral_when_readCharacteristic_is_called_then_the_received_value_is_returned() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_READ, 0);
        characteristic.setValue(new byte[] { 0x00 });
        when(gatt.readCharacteristic(characteristic)).thenReturn(true);
        // When
        peripheral.readCharacteristic(characteristic);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).readCharacteristic(characteristic);
        byte[] value = new byte[] { 0x01 };
        characteristic.setValue(value);
        callback.onCharacteristicRead(gatt, characteristic, 0);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(peripheralCallback).onCharacteristicUpdate(captorPeripheral.capture(), captorValue.capture(), captorCharacteristic.capture(), captorGattStatus.capture());
        byte[] receivedValue = captorValue.getValue();
        replacedertEquals(0x01, receivedValue[0]);
        replacedertEquals(peripheral, captorPeripheral.getValue());
        replacedertEquals(characteristic, captorCharacteristic.getValue());
        replacedertEquals(GattStatus.SUCCESS, captorGattStatus.getValue());
    }

    @Test
    public void Given_a_connected_peripheral_when_readCharacteristic_using_UUID_is_called_then_the_received_value_is_returned() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_READ, 0);
        service.addCharacteristic(characteristic);
        characteristic.setValue(new byte[] { 0x00 });
        when(gatt.getService(SERVICE_UUID)).thenReturn(service);
        when(gatt.readCharacteristic(characteristic)).thenReturn(true);
        // When
        peripheral.readCharacteristic(SERVICE_UUID, UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"));
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).readCharacteristic(characteristic);
        byte[] value = new byte[] { 0x01 };
        characteristic.setValue(value);
        callback.onCharacteristicRead(gatt, characteristic, 0);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(peripheralCallback).onCharacteristicUpdate(captorPeripheral.capture(), captorValue.capture(), captorCharacteristic.capture(), captorGattStatus.capture());
        byte[] receivedValue = captorValue.getValue();
        replacedertEquals(0x01, receivedValue[0]);
        replacedertEquals(peripheral, captorPeripheral.getValue());
        replacedertEquals(characteristic, captorCharacteristic.getValue());
        replacedertEquals(GattStatus.SUCCESS, captorGattStatus.getValue());
    }

    @Test
    public void Given_an_unconnected_peripheral_when_readCharacteristic_is_called_then_the_characteristic_is_not_read() {
        // Given
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_READ, 0);
        // When
        peripheral.readCharacteristic(characteristic);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt, never()).readCharacteristic(characteristic);
    }

    @Test
    public void Given_a_connected_peripheral_without_a_readable_characteristic_when_readCharacteristic_is_called_then_the_characteristic_is_not_read() {
        // Given
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), 0, 0);
        connectAndGetCallback();
        // When
        peripheral.readCharacteristic(characteristic);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt, never()).readCharacteristic(any(BluetoothGattCharacteristic.clreplaced));
    }

    @Test
    public void Given_a_connected_peripheral_when_writeCharacteristic_WithResponse_is_called_then_the_value_is_written_and_a_correct_response_is_received() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_WRITE, 0);
        when(gatt.writeCharacteristic(characteristic)).thenReturn(true);
        // When
        peripheral.writeCharacteristic(characteristic, new byte[] { 5 }, WriteType.WITH_RESPONSE);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).writeCharacteristic(characteristic);
        replacedertEquals(5, characteristic.getValue()[0]);
        replacedertEquals(WRITE_TYPE_DEFAULT, characteristic.getWriteType());
        // When
        byte[] valueAfterWrite = new byte[] { 0x01 };
        characteristic.setValue(valueAfterWrite);
        callback.onCharacteristicWrite(gatt, characteristic, 0);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onCharacteristicWrite(captorPeripheral.capture(), captorValue.capture(), captorCharacteristic.capture(), captorGattStatus.capture());
        byte[] value = captorValue.getValue();
        // Check if original value is returned and not the one in the characteristic
        replacedertEquals(5, value[0]);
        replacedertEquals(peripheral, captorPeripheral.getValue());
        replacedertEquals(characteristic, captorCharacteristic.getValue());
        replacedertEquals(GattStatus.SUCCESS, (GattStatus) captorGattStatus.getValue());
    }

    @Test
    public void Given_a_connected_peripheral_when_writeCharacteristic_WithResponse_usingUUID_is_called_then_the_value_is_written_and_a_correct_response_is_received() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_WRITE, 0);
        service.addCharacteristic(characteristic);
        when(gatt.writeCharacteristic(characteristic)).thenReturn(true);
        when(gatt.getService(SERVICE_UUID)).thenReturn(service);
        // When
        peripheral.writeCharacteristic(SERVICE_UUID, UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), new byte[] { 5 }, WriteType.WITH_RESPONSE);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).writeCharacteristic(characteristic);
        replacedertEquals(5, characteristic.getValue()[0]);
        replacedertEquals(WRITE_TYPE_DEFAULT, characteristic.getWriteType());
        // When
        byte[] valueAfterWrite = new byte[] { 0x01 };
        characteristic.setValue(valueAfterWrite);
        callback.onCharacteristicWrite(gatt, characteristic, 0);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onCharacteristicWrite(captorPeripheral.capture(), captorValue.capture(), captorCharacteristic.capture(), captorGattStatus.capture());
        byte[] value = captorValue.getValue();
        // Check if original value is returned and not the one in the characteristic
        replacedertEquals(5, value[0]);
        replacedertEquals(peripheral, captorPeripheral.getValue());
        replacedertEquals(characteristic, captorCharacteristic.getValue());
        replacedertEquals(GattStatus.SUCCESS, (GattStatus) captorGattStatus.getValue());
    }

    @Test
    public void Given_a_connected_peripheral_when_writeCharacteristic_WithoutResponse_is_called_then_the_value_is_written_and_a_correct_response_is_received() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_WRITE_NO_RESPONSE, 0);
        when(gatt.writeCharacteristic(characteristic)).thenReturn(true);
        // When
        peripheral.writeCharacteristic(characteristic, new byte[] { 0 }, WriteType.WITHOUT_RESPONSE);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).writeCharacteristic(characteristic);
        replacedertEquals(0, characteristic.getValue()[0]);
        replacedertEquals(WRITE_TYPE_NO_RESPONSE, characteristic.getWriteType());
        // When
        byte[] originalByteArray = new byte[] { 0x01 };
        characteristic.setValue(originalByteArray);
        callback.onCharacteristicWrite(gatt, characteristic, GATT_SUCCESS);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onCharacteristicWrite(captorPeripheral.capture(), captorValue.capture(), captorCharacteristic.capture(), captorGattStatus.capture());
        byte[] value = captorValue.getValue();
        // Check if original value is returned and not the one in the characteristic
        replacedertEquals(0, value[0]);
        replacedertEquals(peripheral, captorPeripheral.getValue());
        replacedertEquals(characteristic, captorCharacteristic.getValue());
        replacedertEquals(GattStatus.SUCCESS, (GattStatus) captorGattStatus.getValue());
    }

    @Test
    public void Given_an_unconnected_peripheral_when_writeCharacteristic_is_called_then_the_characteristic_is_not_written() {
        // Given
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_WRITE, 0);
        // When
        peripheral.writeCharacteristic(characteristic, new byte[] { 0 }, WriteType.WITH_RESPONSE);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt, never()).writeCharacteristic(characteristic);
    }

    @Test
    public void Given_a_connected_peripheral_with_not_writable_characteristic_when_writeCharacteristic_is_called_then_the_value_is_not_written() {
        // Given
        connectAndGetCallback();
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), 0, 0);
        // When
        boolean result = peripheral.writeCharacteristic(characteristic, new byte[] { 0, 0 }, WriteType.WITH_RESPONSE);
        // Then
        replacedertFalse(result);
        verify(gatt, never()).writeCharacteristic(any(BluetoothGattCharacteristic.clreplaced));
    }

    @Test(expected = IllegalArgumentException.clreplaced)
    public void Given_a_connected_peripheral_when_writeCharacteristic_is_called_with_an_empty_value_then_an_exception_is_thrown() {
        // Given
        connectAndGetCallback();
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_WRITE, 0);
        // When
        peripheral.writeCharacteristic(characteristic, new byte[0], WriteType.WITH_RESPONSE);
    }

    @Test
    public void Given_a_connected_peripheral_when_readCharacteristic_is_called_twice_then_they_are_done_sequentially() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_READ, 0);
        BluetoothGattCharacteristic characteristic2 = new BluetoothGattCharacteristic(UUID.fromString("00002A1E-0000-1000-8000-00805f9b34fb"), PROPERTY_READ, 0);
        service.addCharacteristic(characteristic);
        service.addCharacteristic(characteristic2);
        byte[] byteArray = new byte[] { 0x01, 0x02, 0x03 };
        characteristic.setValue(byteArray);
        characteristic2.setValue(byteArray);
        when(gatt.readCharacteristic(characteristic)).thenReturn(true);
        // When
        peripheral.readCharacteristic(characteristic);
        peripheral.readCharacteristic(characteristic2);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt, times(1)).readCharacteristic(characteristic);
        // Confirm read
        callback.onCharacteristicRead(gatt, characteristic, GATT_SUCCESS);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onCharacteristicUpdate(peripheral, byteArray, characteristic, GattStatus.SUCCESS);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(gatt).readCharacteristic(characteristic2);
        // Confirm read
        callback.onCharacteristicRead(gatt, characteristic2, GATT_SUCCESS);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onCharacteristicUpdate(peripheral, byteArray, characteristic2, GattStatus.SUCCESS);
    }

    @Test
    public void Given_a_connected_peripheral_when_readCharacteristic_is_called_twice_then_they_are_done_sequentially_even_when_errors_occur() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_READ, 0);
        BluetoothGattCharacteristic characteristic2 = new BluetoothGattCharacteristic(UUID.fromString("00002A1E-0000-1000-8000-00805f9b34fb"), PROPERTY_READ, 0);
        service.addCharacteristic(characteristic);
        service.addCharacteristic(characteristic2);
        byte[] byteArray = new byte[] { 0x01, 0x02, 0x03 };
        characteristic.setValue(byteArray);
        characteristic2.setValue(byteArray);
        when(gatt.readCharacteristic(characteristic)).thenReturn(true);
        // When
        peripheral.readCharacteristic(characteristic);
        peripheral.readCharacteristic(characteristic2);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt, times(1)).readCharacteristic(characteristic);
        // Confirm read
        callback.onCharacteristicRead(gatt, characteristic, 128);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onCharacteristicUpdate(peripheral, byteArray, characteristic, GattStatus.NO_RESOURCES);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(gatt, times(1)).readCharacteristic(characteristic2);
        // Confirm read
        callback.onCharacteristicRead(gatt, characteristic2, GATT_SUCCESS);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onCharacteristicUpdate(peripheral, byteArray, characteristic2, GattStatus.SUCCESS);
    }

    @Test
    public void Given_a_connected_peripheral_when_two_reads_are_done_but_no_reply_is_received_then_the_second_read_is_not_done() {
        // Given
        connectAndGetCallback();
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_READ, 0);
        BluetoothGattCharacteristic characteristic2 = new BluetoothGattCharacteristic(UUID.fromString("00002A1E-0000-1000-8000-00805f9b34fb"), PROPERTY_READ, 0);
        service.addCharacteristic(characteristic);
        service.addCharacteristic(characteristic2);
        byte[] byteArray = new byte[] { 0x01, 0x02, 0x03 };
        characteristic.setValue(byteArray);
        characteristic2.setValue(byteArray);
        when(gatt.readCharacteristic(characteristic)).thenReturn(true);
        // When
        peripheral.readCharacteristic(characteristic);
        peripheral.readCharacteristic(characteristic2);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).readCharacteristic(characteristic);
        verify(peripheralCallback, never()).onCharacteristicUpdate(peripheral, byteArray, characteristic, GattStatus.SUCCESS);
        verify(gatt, never()).readCharacteristic(characteristic2);
    }

    @Test
    public void Given_a_connected_peripheral_with_notifications_on_when_a_notification_is_received_onCharacteristicUpdate_is_called() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_INDICATE, 0);
        peripheral.setNotify(characteristic, true);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // When
        byte[] originalByteArray = new byte[] { 0x01 };
        characteristic.setValue(originalByteArray);
        callback.onCharacteristicChanged(gatt, characteristic);
        characteristic.setValue(new byte[] { 0x00 });
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(peripheralCallback).onCharacteristicUpdate(captorPeripheral.capture(), captorValue.capture(), captorCharacteristic.capture(), captorGattStatus.capture());
        byte[] value = captorValue.getValue();
        replacedertEquals(0x01, value[0]);
        replacedertEquals(peripheral, captorPeripheral.getValue());
        replacedertEquals(characteristic, captorCharacteristic.getValue());
        replacedertEquals(GattStatus.SUCCESS, (GattStatus) captorGattStatus.getValue());
    }

    @Test
    public void Given_a_connected_peripheral_when_a_readDescriptor_is_done_then_the_descriptor_is_read_and_the_onDescriptorRead_is_called_with_the_result() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_INDICATE, 0);
        BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UUID.fromString("00002903-0000-1000-8000-00805f9b34fb"), 0);
        service.addCharacteristic(characteristic);
        characteristic.addDescriptor(descriptor);
        when(gatt.getServices()).thenReturn(Collections.singletonList(service));
        // When
        peripheral.readDescriptor(descriptor);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).readDescriptor(descriptor);
        // When
        byte[] originalByteArray = new byte[] { 0x01 };
        descriptor.setValue(originalByteArray);
        callback.onDescriptorRead(gatt, descriptor, GATT_SUCCESS);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onDescriptorRead(captorPeripheral.capture(), captorValue.capture(), captorDescriptor.capture(), captorGattStatus.capture());
        byte[] value = captorValue.getValue();
        replacedertEquals(0x01, value[0]);
        replacedertEquals(peripheral, captorPeripheral.getValue());
        replacedertEquals(descriptor, captorDescriptor.getValue());
        replacedertEquals(GattStatus.SUCCESS, (GattStatus) captorGattStatus.getValue());
    }

    @Test
    public void Given_a_connected_peripheral_when_writeDescriptor_is_called_then_the_descriptor_is_written_and_the_response_is_received() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_INDICATE, 0);
        BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UUID.fromString("00002903-0000-1000-8000-00805f9b34fb"), 0);
        service.addCharacteristic(characteristic);
        characteristic.addDescriptor(descriptor);
        when(gatt.getServices()).thenReturn(Collections.singletonList(service));
        // When
        byte[] originalByteArray = new byte[] { 0x01 };
        peripheral.writeDescriptor(descriptor, originalByteArray);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).writeDescriptor(descriptor);
        // When
        callback.onDescriptorWrite(gatt, descriptor, 0);
        descriptor.setValue(new byte[] { 0x00 });
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onDescriptorWrite(captorPeripheral.capture(), captorValue.capture(), captorDescriptor.capture(), captorGattStatus.capture());
        byte[] value = captorValue.getValue();
        replacedertEquals(0x01, value[0]);
        replacedertNotEquals(value, originalByteArray);
        replacedertEquals(peripheral, captorPeripheral.getValue());
        replacedertEquals(descriptor, captorDescriptor.getValue());
        replacedertEquals(GattStatus.SUCCESS, (GattStatus) captorGattStatus.getValue());
    }

    @Test
    public void Given_a_connected_peripheral_when_readRemoteRssi_is_called_then_the_rssi_is_read_and_the_result_is_received() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        // When
        peripheral.readRemoteRssi();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).readRemoteRssi();
        // When
        callback.onReadRemoteRssi(gatt, -40, GATT_SUCCESS);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(peripheralCallback).onReadRemoteRssi(peripheral, -40, GattStatus.SUCCESS);
    }

    @Test
    public void Given_a_connected_peripheral_when_requestMTU_is_called_then_the_MTU_is_requested_and_the_result_is_received() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        // When
        peripheral.requestMtu(32);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).requestMtu(32);
        // When
        callback.onMtuChanged(gatt, 32, GATT_SUCCESS);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onMtuChanged(peripheral, 32, GattStatus.SUCCESS);
    }

    @Test
    public void Given_a_connected_peripheral_when_requestConnectionPriority_is_called_then_a_connection_priority_is_requested() {
        // Given
        connectAndGetCallback();
        // When
        peripheral.requestConnectionPriority(ConnectionPriority.HIGH);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).requestConnectionPriority(CONNECTION_PRIORITY_HIGH);
    }

    @Test
    public void Given_a_connected_peripheral_when_createBond_is_called_then_the_bond_is_created() {
        // Given
        connectAndGetCallback();
        // When
        peripheral.createBond();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(device).createBond();
    }

    @Test
    public void Given_an_unconnected_peripheral_when_createBond_is_called_then_the_bond_is_created() {
        peripheral.createBond();
        verify(device).createBond();
    }

    @Test
    public void Given_a_connected_peripheral_when_a_read_triggers_a_bond_the_read_is_retried() throws Exception {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, 0);
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_READ, 0);
        BluetoothGattCharacteristic characteristic2 = new BluetoothGattCharacteristic(UUID.fromString("00002A1E-0000-1000-8000-00805f9b34fb"), PROPERTY_READ, 0);
        service.addCharacteristic(characteristic);
        service.addCharacteristic(characteristic2);
        when(gatt.readCharacteristic(characteristic)).thenReturn(true);
        when(gatt.getServices()).thenReturn(Collections.singletonList(service));
        // When
        peripheral.readCharacteristic(characteristic);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).readCharacteristic(characteristic);
        // Trigger bonding to start
        callback.onCharacteristicRead(gatt, characteristic, 5);
        Field field = BluetoothPeripheral.clreplaced.getDeclaredField("bondStateReceiver");
        field.setAccessible(true);
        BroadcastReceiver broadcastReceiver = (BroadcastReceiver) field.get(peripheral);
        Intent intent = mock(Intent.clreplaced);
        when(intent.getAction()).thenReturn(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        when(intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR)).thenReturn(BOND_BONDED);
        when(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)).thenReturn(device);
        broadcastReceiver.onReceive(context, intent);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(gatt, times(2)).readCharacteristic(characteristic);
    }

    @Test
    public void When_a_peripheral_connects_then_the_services_are_discovered() {
        // Given
        when(device.getBondState()).thenReturn(BOND_NONE);
        // When
        connectAndGetCallback();
        // Then
        verify(gatt).discoverServices();
    }

    @Test
    public void Given_a_connected_peripheral_when_the_connected_drops_unexpected_then_the_gatt_is_closed() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        // When
        callback.onConnectionStateChange(gatt, GATT_FAILURE, STATE_DISCONNECTED);
        // Then
        verify(gatt).close();
    }

    @Test
    public void Given_a_unconnected_bonded_peripheral_when_it_connects_services_are_discovered() {
        // Given
        when(device.getBondState()).thenReturn(BOND_BONDED);
        // When
        connectAndGetCallback();
        // Then
        verify(gatt).discoverServices();
    }

    @Test
    public void Given_a_unconnected_peripheral_when_it_connects_and_bonding_is_in_progress_then_discoverServices_is_not_called() {
        // When
        when(device.getBondState()).thenReturn(BOND_BONDING);
        connectAndGetCallback();
        // Then
        verify(gatt, never()).discoverServices();
    }

    @Test
    public void Given_a_connected_peripheral_when_a_disconnect_happens_then_gatt_is_closed_and_the_disconnected_event_is_sent() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        // When
        callback.onConnectionStateChange(gatt, GATT_SUCCESS, BluetoothProfile.STATE_DISCONNECTED);
        // Then
        verify(gatt).close();
        verify(internalCallback).disconnected(peripheral, HciStatus.SUCCESS);
    }

    @Test
    public void Given_a_connected_peripheral_when_onServicesDiscovered_is_called_then_the_list_of_services_is_returned() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        BluetoothGattService service = mock(BluetoothGattService.clreplaced);
        when(service.getUuid()).thenReturn(SERVICE_UUID);
        when(gatt.getServices()).thenReturn(Collections.singletonList(service));
        BluetoothGattCharacteristic characteristic = mock(BluetoothGattCharacteristic.clreplaced);
        when(characteristic.getProperties()).thenReturn(PROPERTY_READ);
        when(service.getCharacteristics()).thenReturn(Collections.singletonList(characteristic));
        // When
        callback.onServicesDiscovered(gatt, 0);
        // Then
        List<BluetoothGattService> expected = Collections.singletonList(service);
        replacedertEquals(expected, peripheral.getServices());
        replacedertEquals(1, peripheral.getServices().get(0).getCharacteristics().size());
    }

    @Test
    public void Given_a_connected_peripheral_when_service_discovery_fails_then_a_disconnect_is_issued() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        // When
        callback.onServicesDiscovered(gatt, 129);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).disconnect();
    }

    @Test
    public void Given_a_connected_peripheral_when_bonding_succeeds_and_services_were_not_discovered_then_service_discovery_is_started() throws Exception {
        // Given
        connectAndGetCallback();
        Field field = BluetoothPeripheral.clreplaced.getDeclaredField("bondStateReceiver");
        field.setAccessible(true);
        BroadcastReceiver broadcastReceiver = (BroadcastReceiver) field.get(peripheral);
        Intent intent = mock(Intent.clreplaced);
        when(intent.getAction()).thenReturn(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        when(intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR)).thenReturn(BOND_BONDED);
        when(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)).thenReturn(device);
        // When
        broadcastReceiver.onReceive(context, intent);
        // Then
        verify(gatt).discoverServices();
    }

    @Test
    public void Given_a_bonded_connected_peripheral_when_bond_is_lost_then_a_disconnect_is_issued() throws Exception {
        // Given
        when(device.getBondState()).thenReturn(BOND_BONDED);
        connectAndGetCallback();
        Field field = BluetoothPeripheral.clreplaced.getDeclaredField("bondStateReceiver");
        field.setAccessible(true);
        BroadcastReceiver broadcastReceiver = (BroadcastReceiver) field.get(peripheral);
        Intent intent = mock(Intent.clreplaced);
        when(intent.getAction()).thenReturn(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        when(intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR)).thenReturn(BluetoothDevice.BOND_NONE);
        when(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)).thenReturn(device);
        // When
        broadcastReceiver.onReceive(context, intent);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).disconnect();
    }

    @Test
    @Config(sdk = { O_MR1 })
    public void Given_a_connected_peripheral_when_requestPhy_is_called_the_Phy_is_requested() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        // When
        peripheral.setPreferredPhy(PhyType.LE_2M, PhyType.LE_2M, PhyOptions.NO_PREFERRED);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).setPreferredPhy(PhyType.LE_2M.value, PhyType.LE_2M.value, PhyOptions.NO_PREFERRED.value);
        // When
        callback.onPhyUpdate(gatt, PhyType.LE_2M.value, PhyType.LE_2M.value, GATT_SUCCESS);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onPhyUpdate(peripheral, PhyType.LE_2M, PhyType.LE_2M, GattStatus.SUCCESS);
    }

    @Test
    @Config(sdk = { O_MR1 })
    public void Given_a_connected_peripheral_when_readPhy_is_called_the_Phy_is_read() {
        // Given
        BluetoothGattCallback callback = connectAndGetCallback();
        // When
        peripheral.readPhy();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(gatt).readPhy();
        // When
        callback.onPhyRead(gatt, PhyType.LE_2M.value, PhyType.LE_2M.value, GATT_SUCCESS);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralCallback).onPhyUpdate(peripheral, PhyType.LE_2M, PhyType.LE_2M, GattStatus.SUCCESS);
    }

    @Test
    public void testPeripheralCallbackEmptyNoCrash() {
        BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb"), PROPERTY_NOTIFY, 0);
        peripheral.peripheralCallback.onCharacteristicUpdate(peripheral, new byte[] { 0x00 }, characteristic, GattStatus.ATTRIBUTE_NOT_FOUND);
    }

    private BluetoothGattCallback connectAndGetCallback() {
        peripheral.connect();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        ArgumentCaptor<BluetoothGattCallback> bluetoothGattCallbackCaptor = ArgumentCaptor.forClreplaced(BluetoothGattCallback.clreplaced);
        verify(device).connectGatt(any(Context.clreplaced), anyBoolean(), bluetoothGattCallbackCaptor.capture(), anyInt());
        BluetoothGattCallback callback = bluetoothGattCallbackCaptor.getValue();
        callback.onConnectionStateChange(gatt, GATT_SUCCESS, STATE_CONNECTED);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        return callback;
    }
}

19 Source : BluetoothPeripheralManagerTest.java
with MIT License
from weliem

@RunWith(RobolectricTestRunner.clreplaced)
@Config(manifest = Config.NONE, sdk = { M })
public clreplaced BluetoothPeripheralManagerTest {

    private static final UUID DIS_SERVICE_UUID = UUID.fromString("0000180A-0000-1000-8000-00805f9b34fb");

    private BluetoothPeripheralManager peripheralManager;

    @Mock
    BluetoothManager bluetoothManager;

    @Mock
    BluetoothAdapter bluetoothAdapter;

    @Mock
    BluetoothLeAdvertiser bluetoothLeAdvertiser;

    @Mock
    BluetoothGattServer server;

    @Mock
    BluetoothPeripheralManagerCallback peripheralManagerCallback;

    @Mock
    BluetoothDevice device;

    @Mock
    BluetoothGattCharacteristic characteristic;

    @Mock
    BluetoothGattDescriptor descriptor;

    // @Mock
    // BluetoothCentral central;
    @Before
    public void setUp() {
        openMocks(this);
        Context context = ApplicationProvider.getApplicationContext();
        when(device.getAddress()).thenReturn("12:23:34:98:76:54");
        when(bluetoothManager.getAdapter()).thenReturn(bluetoothAdapter);
        when(bluetoothAdapter.getBluetoothLeAdvertiser()).thenReturn(bluetoothLeAdvertiser);
        when(bluetoothManager.openGattServer(any(Context.clreplaced), any(BluetoothGattServerCallback.clreplaced))).thenReturn(server);
        peripheralManager = new BluetoothPeripheralManager(context, bluetoothManager, peripheralManagerCallback);
    }

    @Test
    public void When_addService_is_called_with_a_valid_service_then_the_operation_is_enqueued_and_onServiceAdded_is_called_upon_completed() {
        BluetoothGattService service = new BluetoothGattService(DIS_SERVICE_UUID, SERVICE_TYPE_PRIMARY);
        when(server.addService(any(BluetoothGattService.clreplaced))).thenReturn(true);
        peripheralManager.add(service);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(server).addService(service);
        replacedertEquals(1, peripheralManager.commandQueue.size());
        peripheralManager.bluetoothGattServerCallback.onServiceAdded(GattStatus.SUCCESS.value, service);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(peripheralManagerCallback).onServiceAdded(GattStatus.SUCCESS, service);
        replacedertEquals(0, peripheralManager.commandQueue.size());
    }

    @Test
    public void When_removeService_is_called_then_the_service_is_removed() {
        // When
        BluetoothGattService service = new BluetoothGattService(DIS_SERVICE_UUID, SERVICE_TYPE_PRIMARY);
        peripheralManager.remove(service);
        // Then
        verify(server).removeService(service);
    }

    @Test
    public void When_removeAllServices_is_called_then_all_services_are_removed() {
        // When
        peripheralManager.removeAllServices();
        // Then
        verify(server).clearServices();
    }

    @Test
    public void When_getServices_is_called_then_all_services_are_returned() {
        // When
        peripheralManager.getServices();
        // Then
        verify(server).getServices();
    }

    @Test
    public void When_close_is_called_then_advertising_is_stopped_and_the_server_is_closed() {
        // When
        peripheralManager.close();
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(bluetoothLeAdvertiser).stopAdvertising(any(AdvertiseCallback.clreplaced));
        verify(peripheralManagerCallback).onAdvertisingStopped();
        verify(server).close();
    }

    @Test
    public void When_startAdvertising_is_called_then_advertising_is_started() {
        // Given
        when(bluetoothAdapter.isMultipleAdvertisementSupported()).thenReturn(true);
        AdvertiseSettings advertiseSettings = new AdvertiseSettings.Builder().setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED).setConnectable(true).setTimeout(0).setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM).build();
        AdvertiseData advertiseData = new AdvertiseData.Builder().setIncludeTxPowerLevel(true).addServiceUuid(new ParcelUuid(DIS_SERVICE_UUID)).build();
        AdvertiseData scanResponse = new AdvertiseData.Builder().setIncludeDeviceName(true).build();
        // When
        peripheralManager.startAdvertising(advertiseSettings, advertiseData, scanResponse);
        // Then
        verify(bluetoothLeAdvertiser).startAdvertising(advertiseSettings, advertiseData, scanResponse, peripheralManager.advertiseCallback);
    }

    @Test
    public void When_a_read_characteristic_request_is_received_then_onCharacteristicRead_is_called() {
        // When
        peripheralManager.bluetoothGattServerCallback.onCharacteristicReadRequest(device, 1, 0, characteristic);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralManagerCallback).onCharacteristicRead(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced));
    }

    @Test
    public void When_a_read_characteristic_request_is_received_then_characteristic_value_is_returned() {
        // Given
        byte[] value = new byte[] { 0x00, 0x01, 0x02 };
        when(characteristic.getValue()).thenReturn(value);
        // When
        peripheralManager.bluetoothGattServerCallback.onCharacteristicReadRequest(device, 1, 0, characteristic);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.SUCCESS.value, 0, value);
    }

    @Test
    public void When_a_long_read_characteristic_request_is_received_then_characteristic_value_is_returned_in_chunks() {
        // Given
        byte[] value = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
        byte[] firstChunk = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 };
        byte[] secondChunk = new byte[] { 23, 24 };
        when(characteristic.getValue()).thenReturn(value);
        // When
        peripheralManager.bluetoothGattServerCallback.onCharacteristicReadRequest(device, 1, 0, characteristic);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.SUCCESS.value, 0, firstChunk);
        // When
        peripheralManager.bluetoothGattServerCallback.onCharacteristicReadRequest(device, 2, 22, characteristic);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 2, GattStatus.SUCCESS.value, 22, secondChunk);
    }

    @Test
    public void When_a_read_descriptor_request_is_received_then_onDescriptorRead_is_called() {
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorReadRequest(device, 1, 0, descriptor);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralManagerCallback).onDescriptorRead(any(BluetoothCentral.clreplaced), any(BluetoothGattDescriptor.clreplaced));
    }

    @Test
    public void When_a_read_descriptor_request_is_received_then_descriptor_value_is_returned() {
        // Given
        byte[] value = new byte[] { 0x00, 0x01, 0x02 };
        when(descriptor.getValue()).thenReturn(value);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorReadRequest(device, 1, 0, descriptor);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.SUCCESS.value, 0, value);
    }

    @Test
    public void When_a_long_read_descriptor_request_is_received_then_Descriptor_value_is_returned_in_chunks() {
        // Given
        byte[] value = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
        byte[] firstChunk = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 };
        byte[] secondChunk = new byte[] { 23, 24 };
        when(descriptor.getValue()).thenReturn(value);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorReadRequest(device, 1, 0, descriptor);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.SUCCESS.value, 0, firstChunk);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorReadRequest(device, 2, 22, descriptor);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 2, GattStatus.SUCCESS.value, 22, secondChunk);
    }

    @Test
    public void When_a_write_characteristic_request_is_received_then_onCharacteristicWrite_is_called() {
        // Given
        byte[] value = new byte[] { 0x00, 0x01, 0x02 };
        when(peripheralManagerCallback.onCharacteristicWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced), any(byte[].clreplaced))).thenReturn(GattStatus.SUCCESS);
        // When
        peripheralManager.bluetoothGattServerCallback.onCharacteristicWriteRequest(device, 1, characteristic, false, true, 0, value);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralManagerCallback).onCharacteristicWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced), any(byte[].clreplaced));
    }

    @Test
    public void When_a_write_characteristic_request_is_received_and_approved_then_characteristic_value_is_set_and_confirmed() {
        // Given
        byte[] value = new byte[] { 0x00, 0x01, 0x02 };
        when(characteristic.getValue()).thenReturn(value);
        when(peripheralManagerCallback.onCharacteristicWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced), any(byte[].clreplaced))).thenReturn(GattStatus.SUCCESS);
        // When
        peripheralManager.bluetoothGattServerCallback.onCharacteristicWriteRequest(device, 1, characteristic, false, true, 0, value);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(characteristic).setValue(value);
        verify(server).sendResponse(device, 1, GattStatus.SUCCESS.value, 0, value);
    }

    @Test
    public void When_a_write_characteristic_request_is_received_and_not_approved_then_characteristic_value_is_not_set_and_confirmed() {
        // Given
        byte[] value = new byte[] { 0x00, 0x01, 0x02 };
        when(characteristic.getValue()).thenReturn(value);
        when(peripheralManagerCallback.onCharacteristicWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced), any(byte[].clreplaced))).thenReturn(GattStatus.VALUE_NOT_ALLOWED);
        // When
        peripheralManager.bluetoothGattServerCallback.onCharacteristicWriteRequest(device, 1, characteristic, false, true, 0, value);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(characteristic, never()).setValue(value);
        verify(server).sendResponse(device, 1, GattStatus.VALUE_NOT_ALLOWED.value, 0, value);
    }

    @Test
    public void When_a_long_write_characteristic_requests_are_received_and_approved_then_characteristic_value_is_set_and_confirmed() {
        // Given
        byte[] value = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
        byte[] firstChunk = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
        byte[] secondChunk = new byte[] { 19, 20, 21, 22, 23, 24 };
        when(characteristic.getValue()).thenReturn(value);
        when(peripheralManagerCallback.onCharacteristicWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced), any(byte[].clreplaced))).thenReturn(GattStatus.SUCCESS);
        // When
        peripheralManager.bluetoothGattServerCallback.onCharacteristicWriteRequest(device, 1, characteristic, true, true, 0, firstChunk);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.SUCCESS.value, 0, firstChunk);
        // When
        peripheralManager.bluetoothGattServerCallback.onCharacteristicWriteRequest(device, 2, characteristic, true, true, 18, secondChunk);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 2, GattStatus.SUCCESS.value, 18, secondChunk);
        // When
        peripheralManager.bluetoothGattServerCallback.onExecuteWrite(device, 3, true);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralManagerCallback).onCharacteristicWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced), any(byte[].clreplaced));
        verify(characteristic).setValue(value);
        verify(server).sendResponse(device, 3, GattStatus.SUCCESS.value, 0, null);
    }

    @Test
    public void When_a_long_write_characteristic_requests_are_received_with_incorrect_offset_then_the_error_invalid_offset_is_given() {
        // Given
        byte[] value = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
        byte[] firstChunk = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
        byte[] secondChunk = new byte[] { 19, 20, 21, 22, 23, 24 };
        when(characteristic.getValue()).thenReturn(value);
        when(peripheralManagerCallback.onCharacteristicWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced), any(byte[].clreplaced))).thenReturn(GattStatus.SUCCESS);
        // When
        peripheralManager.bluetoothGattServerCallback.onCharacteristicWriteRequest(device, 1, characteristic, true, true, 0, firstChunk);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.SUCCESS.value, 0, firstChunk);
        // When
        peripheralManager.bluetoothGattServerCallback.onCharacteristicWriteRequest(device, 2, characteristic, true, true, 19, secondChunk);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 2, GattStatus.INVALID_OFFSET.value, 19, secondChunk);
    }

    @Test
    public void When_a_CCC_descriptor_is_written_with_valid_indicate_value_then_it_is_set_and_onNotifyEnabled_is_called() {
        // Given
        when(descriptor.getCharacteristic()).thenReturn(characteristic);
        when(characteristic.getProperties()).thenReturn(BluetoothGattCharacteristic.PROPERTY_INDICATE);
        when(descriptor.getPermissions()).thenReturn(BluetoothGattDescriptor.PERMISSION_WRITE);
        when(descriptor.getUuid()).thenReturn(CCC_DESCRIPTOR_UUID);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 1, descriptor, false, true, 0, BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(descriptor).setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
        verify(peripheralManagerCallback).onNotifyingEnabled(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced));
    }

    @Test
    public void When_a_CCC_descriptor_is_written_with_valid_notify_value_then_it_is_set_and_onNotifyEnabled_is_called() {
        // Given
        when(descriptor.getCharacteristic()).thenReturn(characteristic);
        when(characteristic.getProperties()).thenReturn(BluetoothGattCharacteristic.PROPERTY_NOTIFY);
        when(descriptor.getPermissions()).thenReturn(BluetoothGattDescriptor.PERMISSION_WRITE);
        when(descriptor.getUuid()).thenReturn(CCC_DESCRIPTOR_UUID);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 1, descriptor, false, true, 0, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(descriptor).setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        verify(peripheralManagerCallback).onNotifyingEnabled(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced));
    }

    @Test
    public void When_a_CCC_descriptor_is_written_with_valid_disable_value_then_it_is_set_and_onNotifyDisable_is_called() {
        // Given
        when(descriptor.getCharacteristic()).thenReturn(characteristic);
        when(characteristic.getProperties()).thenReturn(BluetoothGattCharacteristic.PROPERTY_NOTIFY);
        when(descriptor.getPermissions()).thenReturn(BluetoothGattDescriptor.PERMISSION_WRITE);
        when(descriptor.getUuid()).thenReturn(CCC_DESCRIPTOR_UUID);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 1, descriptor, false, true, 0, BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(descriptor).setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        verify(peripheralManagerCallback).onNotifyingDisabled(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced));
    }

    @Test
    public void When_a_CCC_descriptor_for_a_indicate_characteristic_is_written_with_invalid_value_then_an_error_is_given() {
        // Given
        when(descriptor.getCharacteristic()).thenReturn(characteristic);
        when(characteristic.getProperties()).thenReturn(BluetoothGattCharacteristic.PROPERTY_INDICATE);
        when(descriptor.getPermissions()).thenReturn(BluetoothGattDescriptor.PERMISSION_WRITE);
        when(descriptor.getUuid()).thenReturn(CCC_DESCRIPTOR_UUID);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 1, descriptor, false, true, 0, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.REQUEST_NOT_SUPPORTED.value, 0, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
    }

    @Test
    public void When_a_CCC_descriptor_for_a_notify_characteristic_is_written_with_invalid_value_then_an_error_is_given() {
        // Given
        when(descriptor.getCharacteristic()).thenReturn(characteristic);
        when(characteristic.getProperties()).thenReturn(BluetoothGattCharacteristic.PROPERTY_NOTIFY);
        when(descriptor.getPermissions()).thenReturn(BluetoothGattDescriptor.PERMISSION_WRITE);
        when(descriptor.getUuid()).thenReturn(CCC_DESCRIPTOR_UUID);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 1, descriptor, false, true, 0, BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.REQUEST_NOT_SUPPORTED.value, 0, BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
    }

    @Test
    public void When_a_CCC_descriptor_is_written_with_invalid_length_value_then_an_error_is_given() {
        // Given
        when(descriptor.getCharacteristic()).thenReturn(characteristic);
        when(characteristic.getProperties()).thenReturn(BluetoothGattCharacteristic.PROPERTY_NOTIFY);
        when(descriptor.getPermissions()).thenReturn(BluetoothGattDescriptor.PERMISSION_WRITE);
        when(descriptor.getUuid()).thenReturn(CCC_DESCRIPTOR_UUID);
        byte[] value = new byte[] { 0x00 };
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 1, descriptor, false, true, 0, value);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.INVALID_ATTRIBUTE_VALUE_LENGTH.value, 0, value);
    }

    @Test
    public void When_a_CCC_descriptor_is_written_with_invalid_value_then_an_error_is_given() {
        // Given
        when(descriptor.getCharacteristic()).thenReturn(characteristic);
        when(characteristic.getProperties()).thenReturn(BluetoothGattCharacteristic.PROPERTY_NOTIFY);
        when(descriptor.getPermissions()).thenReturn(BluetoothGattDescriptor.PERMISSION_WRITE);
        when(descriptor.getUuid()).thenReturn(CCC_DESCRIPTOR_UUID);
        byte[] value = new byte[] { 0x02, 0x01 };
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 1, descriptor, false, true, 0, value);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.VALUE_NOT_ALLOWED.value, 0, value);
    }

    @Test
    public void When_a_long_write_descriptor_requests_are_received_and_approved_then_descriptor_value_is_set_and_confirmed() {
        // Given
        byte[] value = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
        byte[] firstChunk = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
        byte[] secondChunk = new byte[] { 19, 20, 21, 22, 23, 24 };
        when(descriptor.getCharacteristic()).thenReturn(characteristic);
        when(descriptor.getValue()).thenReturn(value);
        when(descriptor.getUuid()).thenReturn(UUID.fromString("00002901-0000-1000-8000-00805f9b34fb"));
        when(peripheralManagerCallback.onDescriptorWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattDescriptor.clreplaced), any(byte[].clreplaced))).thenReturn(GattStatus.SUCCESS);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 1, descriptor, true, true, 0, firstChunk);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.SUCCESS.value, 0, firstChunk);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 2, descriptor, true, true, 18, secondChunk);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 2, GattStatus.SUCCESS.value, 18, secondChunk);
        // When
        peripheralManager.bluetoothGattServerCallback.onExecuteWrite(device, 3, true);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralManagerCallback).onDescriptorWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattDescriptor.clreplaced), any(byte[].clreplaced));
        verify(descriptor).setValue(value);
        verify(server).sendResponse(device, 3, GattStatus.SUCCESS.value, 0, null);
    }

    @Test
    public void When_a_long_write_descriptor_requests_are_received_with_incorrect_offset_then_the_error_invalid_offset_is_given() {
        // Given
        byte[] value = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
        byte[] firstChunk = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
        byte[] secondChunk = new byte[] { 19, 20, 21, 22, 23, 24 };
        when(descriptor.getCharacteristic()).thenReturn(characteristic);
        when(descriptor.getValue()).thenReturn(value);
        when(descriptor.getUuid()).thenReturn(UUID.fromString("00002901-0000-1000-8000-00805f9b34fb"));
        when(peripheralManagerCallback.onCharacteristicWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattCharacteristic.clreplaced), any(byte[].clreplaced))).thenReturn(GattStatus.SUCCESS);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 1, descriptor, true, true, 0, firstChunk);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.SUCCESS.value, 0, firstChunk);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 2, descriptor, true, true, 19, secondChunk);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 2, GattStatus.INVALID_OFFSET.value, 19, secondChunk);
    }

    @Test
    public void When_a_write_descriptor_request_is_received_and_approved_then_descriptor_value_is_set_and_confirmed() {
        // Given
        byte[] value = new byte[] { 0x00, 0x01, 0x02 };
        when(descriptor.getValue()).thenReturn(value);
        when(descriptor.getCharacteristic()).thenReturn(characteristic);
        when(descriptor.getUuid()).thenReturn(UUID.fromString("00002901-0000-1000-8000-00805f9b34fb"));
        when(peripheralManagerCallback.onDescriptorWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattDescriptor.clreplaced), any(byte[].clreplaced))).thenReturn(GattStatus.SUCCESS);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 1, descriptor, false, true, 0, value);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(descriptor).setValue(value);
        verify(server).sendResponse(device, 1, GattStatus.SUCCESS.value, 0, value);
    }

    @Test
    public void When_long_write_descriptor_requests_are_received_and_cancelled_then_descriptor_value_is_not_set() {
        // Given
        byte[] value = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
        byte[] firstChunk = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
        when(descriptor.getCharacteristic()).thenReturn(characteristic);
        when(descriptor.getValue()).thenReturn(value);
        when(descriptor.getUuid()).thenReturn(UUID.fromString("00002901-0000-1000-8000-00805f9b34fb"));
        when(peripheralManagerCallback.onDescriptorWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattDescriptor.clreplaced), any(byte[].clreplaced))).thenReturn(GattStatus.SUCCESS);
        // When
        peripheralManager.bluetoothGattServerCallback.onDescriptorWriteRequest(device, 1, descriptor, true, true, 0, firstChunk);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).sendResponse(device, 1, GattStatus.SUCCESS.value, 0, firstChunk);
        // When
        peripheralManager.bluetoothGattServerCallback.onExecuteWrite(device, 3, false);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralManagerCallback, never()).onDescriptorWrite(any(BluetoothCentral.clreplaced), any(BluetoothGattDescriptor.clreplaced), any(byte[].clreplaced));
        verify(descriptor, never()).setValue(value);
        verify(server).sendResponse(device, 3, GattStatus.SUCCESS.value, 0, null);
    }

    @Test
    public void When_notifyCharacteristicChanged_is_called_for_a_characteristic_that_does_not_notify_then_false_is_returned() {
        // Given
        when(characteristic.getProperties()).thenReturn(BluetoothGattCharacteristic.PROPERTY_READ);
        byte[] value = new byte[] { 0x00, 0x01, 0x02 };
        // When
        boolean result = peripheralManager.notifyCharacteristicChanged(value, characteristic);
        // Then
        replacedertFalse(result);
    }

    @Test
    public void When_notifyCharacteristicChanged_is_called_for_a_notify_characteristic_that_supports_notify_then_a_notification_is_sent() {
        // Given
        when(characteristic.getProperties()).thenReturn(BluetoothGattCharacteristic.PROPERTY_NOTIFY);
        when(characteristic.getValue()).thenReturn(new byte[] { 0x00 });
        byte[] value = new byte[] { 0x00, 0x01, 0x02 };
        // When
        peripheralManager.bluetoothGattServerCallback.onConnectionStateChange(device, GattStatus.SUCCESS.value, BluetoothProfile.STATE_CONNECTED);
        when(bluetoothManager.getConnectedDevices(BluetoothGattServer.GATT)).thenReturn(Collections.singletonList(device));
        boolean result = peripheralManager.notifyCharacteristicChanged(value, characteristic);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        replacedertTrue(result);
        verify(characteristic).setValue(value);
        when(characteristic.getValue()).thenReturn(value);
        verify(server).notifyCharacteristicChanged(device, characteristic, false);
    }

    @Test
    public void When_notifyCharacteristicChanged_is_called_for_a_indicate_characteristic_that_supports_notify_then_a_notification_is_sent() {
        // Given
        when(characteristic.getProperties()).thenReturn(BluetoothGattCharacteristic.PROPERTY_INDICATE);
        when(characteristic.getValue()).thenReturn(new byte[] { 0x00 });
        byte[] value = new byte[] { 0x00, 0x01, 0x02 };
        // When
        peripheralManager.bluetoothGattServerCallback.onConnectionStateChange(device, GattStatus.SUCCESS.value, BluetoothProfile.STATE_CONNECTED);
        when(bluetoothManager.getConnectedDevices(BluetoothGattServer.GATT)).thenReturn(Collections.singletonList(device));
        boolean result = peripheralManager.notifyCharacteristicChanged(value, characteristic);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        replacedertTrue(result);
        verify(characteristic).setValue(value);
        when(characteristic.getValue()).thenReturn(value);
        verify(server).notifyCharacteristicChanged(device, characteristic, true);
    }

    @Test
    public void When_a_notification_has_been_sent_then_onNotificationSent_is_sent() {
        // Given
        byte[] value = new byte[] { 0x00, 0x01, 0x02 };
        when(characteristic.getValue()).thenReturn(value);
        when(characteristic.getProperties()).thenReturn(BluetoothGattCharacteristic.PROPERTY_INDICATE);
        peripheralManager.bluetoothGattServerCallback.onConnectionStateChange(device, GattStatus.SUCCESS.value, BluetoothProfile.STATE_CONNECTED);
        when(bluetoothManager.getConnectedDevices(BluetoothGattServer.GATT)).thenReturn(Collections.singletonList(device));
        // When
        peripheralManager.notifyCharacteristicChanged(value, characteristic);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(server).notifyCharacteristicChanged(device, characteristic, true);
        peripheralManager.bluetoothGattServerCallback.onNotificationSent(device, GattStatus.SUCCESS.value);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(peripheralManagerCallback).onNotificationSent(any(BluetoothCentral.clreplaced), any(byte[].clreplaced), any(BluetoothGattCharacteristic.clreplaced), any(GattStatus.clreplaced));
    }

    @Test
    public void When_a_central_connects_then_onCentralConnected_is_called() {
        // When
        peripheralManager.bluetoothGattServerCallback.onConnectionStateChange(device, GattStatus.SUCCESS.value, BluetoothProfile.STATE_CONNECTED);
        when(bluetoothManager.getConnectedDevices(BluetoothGattServer.GATT)).thenReturn(Collections.singletonList(device));
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralManagerCallback).onCentralConnected(any(BluetoothCentral.clreplaced));
    }

    @Test
    public void Given_a_connected_central_when_cancelConnection_is_called_then_it_is_disconnected_and_onCentralDisconnected_is_called() {
        // Given
        when(bluetoothAdapter.getRemoteDevice(device.getAddress())).thenReturn(device);
        peripheralManager.bluetoothGattServerCallback.onConnectionStateChange(device, GattStatus.SUCCESS.value, BluetoothProfile.STATE_CONNECTED);
        when(bluetoothManager.getConnectedDevices(BluetoothGattServer.GATT)).thenReturn(Collections.singletonList(device));
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        BluetoothCentral central = peripheralManager.getCentral(device.getAddress());
        // When
        peripheralManager.cancelConnection(central);
        // Then
        verify(server).cancelConnection(device);
        // When
        peripheralManager.bluetoothGattServerCallback.onConnectionStateChange(device, 0, GattStatus.SUCCESS.value);
        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        // Then
        verify(peripheralManagerCallback).onCentralDisconnected(central);
    }
}

19 Source : BluetoothCentralManagerTest.java
with MIT License
from weliem

@Test
public void scanForPeripheralsWithServicesTest() {
    application.grantPermissions(Manifest.permission.ACCESS_COARSE_LOCATION);
    UUID BLP_SERVICE_UUID = UUID.fromString("00001810-0000-1000-8000-00805f9b34fb");
    central.scanForPeripheralsWithServices(new UUID[] { BLP_SERVICE_UUID });
    // Make sure startScan is called
    ArgumentCaptor<ScanSettings> scanSettingsCaptor = ArgumentCaptor.forClreplaced(ScanSettings.clreplaced);
    ArgumentCaptor<ScanCallback> scanCallbackCaptor = ArgumentCaptor.forClreplaced(ScanCallback.clreplaced);
    verify(scanner).startScan(scanFiltersCaptor.capture(), scanSettingsCaptor.capture(), scanCallbackCaptor.capture());
    // Verify there is only 1 filter set
    List<ScanFilter> filters = scanFiltersCaptor.getValue();
    replacedertEquals(1, filters.size());
    // Verify the filter contains the UUID we added
    ScanFilter uuidFilter = filters.get(0);
    ParcelUuid parcelUuid = uuidFilter.getServiceUuid();
    UUID uuid = parcelUuid.getUuid();
    replacedertEquals(BLP_SERVICE_UUID.toString(), uuid.toString());
    // Fake scan result
    ScanResult scanResult = mock(ScanResult.clreplaced);
    BluetoothDevice device = mock(BluetoothDevice.clreplaced);
    when(device.getAddress()).thenReturn("12:23:34:98:76:54");
    when(scanResult.getDevice()).thenReturn(device);
    bluetoothAdapter.addDevice(device);
    central.defaultScanCallback.onScanResult(CALLBACK_TYPE_ALL_MATCHES, scanResult);
    ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
    // See if we get it back
    ArgumentCaptor<BluetoothPeripheral> bluetoothPeripheralCaptor = ArgumentCaptor.forClreplaced(BluetoothPeripheral.clreplaced);
    ArgumentCaptor<ScanResult> scanResultCaptor = ArgumentCaptor.forClreplaced(ScanResult.clreplaced);
    verify(callback).onDiscoveredPeripheral(bluetoothPeripheralCaptor.capture(), scanResultCaptor.capture());
    replacedertEquals(scanResultCaptor.getValue(), scanResult);
    replacedertEquals(bluetoothPeripheralCaptor.getValue().getAddress(), "12:23:34:98:76:54");
}

19 Source : BluetoothCentralManagerTest.java
with MIT License
from weliem

@Test
public void getPeripheralValidMacAddressTest() {
    // Given
    BluetoothDevice device = mock(BluetoothDevice.clreplaced);
    when(device.getAddress()).thenReturn("AC:DE:EF:12:34:56");
    bluetoothAdapter.addDevice(device);
    // Get peripheral and supply lowercase mac address
    BluetoothPeripheral peripheral = central.getPeripheral("AC:DE:EF:12:34:56");
    replacedertNotNull(peripheral);
}

19 Source : BluetoothCentralManagerTest.java
with MIT License
from weliem

@Test
public void autoconnectTestUnCached() {
    application.grantPermissions(Manifest.permission.ACCESS_COARSE_LOCATION);
    BluetoothDevice device = mock(BluetoothDevice.clreplaced);
    when(device.getAddress()).thenReturn("12:23:34:98:76:54");
    when(device.getType()).thenReturn(BluetoothDevice.DEVICE_TYPE_LE);
    bluetoothAdapter.addDevice(device);
    BluetoothPeripheral peripheral = mock(BluetoothPeripheral.clreplaced);
    when(peripheral.getAddress()).thenReturn("12:23:34:98:76:54");
    when(peripheral.getType()).thenReturn(PeripheralType.UNKNOWN);
    central.autoConnectPeripheral(peripheral, peripheralCallback);
    verify(peripheral, never()).autoConnect();
    verify(scanner).startScan(ArgumentMatchers.<ScanFilter>anyList(), any(ScanSettings.clreplaced), any(ScanCallback.clreplaced));
    // Fake scan result
    ScanResult scanResult = mock(ScanResult.clreplaced);
    when(scanResult.getDevice()).thenReturn(device);
    central.autoConnectScanCallback.onScanResult(CALLBACK_TYPE_ALL_MATCHES, scanResult);
    verify(peripheral).connect();
}

19 Source : BluetoothCentralManagerTest.java
with MIT License
from weliem

@Test
public void scanForPeripheralsWithNamesTest() {
    application.grantPermissions(Manifest.permission.ACCESS_COARSE_LOCATION);
    String myAddress = "12:23:34:98:76:54";
    String myName = "Polar";
    central.scanForPeripheralsWithNames(new String[] { myName });
    // Make sure startScan is called
    ArgumentCaptor<ScanSettings> scanSettingsCaptor = ArgumentCaptor.forClreplaced(ScanSettings.clreplaced);
    ArgumentCaptor<ScanCallback> scanCallbackCaptor = ArgumentCaptor.forClreplaced(ScanCallback.clreplaced);
    verify(scanner).startScan(scanFiltersCaptor.capture(), scanSettingsCaptor.capture(), scanCallbackCaptor.capture());
    // Verify there is no filter set
    List<ScanFilter> filters = scanFiltersCaptor.getValue();
    replacedertEquals(0, filters.size());
    // Fake scan result
    ScanResult scanResult = mock(ScanResult.clreplaced);
    BluetoothDevice device = mock(BluetoothDevice.clreplaced);
    when(device.getAddress()).thenReturn(myAddress);
    when(device.getName()).thenReturn("Polar H7");
    when(scanResult.getDevice()).thenReturn(device);
    bluetoothAdapter.addDevice(device);
    central.scanByNameCallback.onScanResult(CALLBACK_TYPE_ALL_MATCHES, scanResult);
    ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
    // See if we get it back
    ArgumentCaptor<BluetoothPeripheral> bluetoothPeripheralCaptor = ArgumentCaptor.forClreplaced(BluetoothPeripheral.clreplaced);
    ArgumentCaptor<ScanResult> scanResultCaptor = ArgumentCaptor.forClreplaced(ScanResult.clreplaced);
    verify(callback).onDiscoveredPeripheral(bluetoothPeripheralCaptor.capture(), scanResultCaptor.capture());
    replacedertEquals(scanResultCaptor.getValue(), scanResult);
    replacedertEquals(bluetoothPeripheralCaptor.getValue().getName(), "Polar H7");
}

19 Source : BluetoothCentralManagerTest.java
with MIT License
from weliem

@Test
public void scanForPeripheralsTest() {
    application.grantPermissions(Manifest.permission.ACCESS_COARSE_LOCATION);
    central.scanForPeripherals();
    verify(scanner).startScan(ArgumentMatchers.<ScanFilter>anyList(), any(ScanSettings.clreplaced), any(ScanCallback.clreplaced));
    // Fake scan result
    ScanResult scanResult = mock(ScanResult.clreplaced);
    BluetoothDevice device = mock(BluetoothDevice.clreplaced);
    when(device.getAddress()).thenReturn("12:23:34:98:76:54");
    when(scanResult.getDevice()).thenReturn(device);
    bluetoothAdapter.addDevice(device);
    central.defaultScanCallback.onScanResult(CALLBACK_TYPE_ALL_MATCHES, scanResult);
    ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
    // See if we get it back
    ArgumentCaptor<BluetoothPeripheral> bluetoothPeripheralCaptor = ArgumentCaptor.forClreplaced(BluetoothPeripheral.clreplaced);
    ArgumentCaptor<ScanResult> scanResultCaptor = ArgumentCaptor.forClreplaced(ScanResult.clreplaced);
    verify(callback).onDiscoveredPeripheral(bluetoothPeripheralCaptor.capture(), scanResultCaptor.capture());
    replacedertEquals(scanResultCaptor.getValue(), scanResult);
    replacedertEquals(bluetoothPeripheralCaptor.getValue().getAddress(), "12:23:34:98:76:54");
}

19 Source : BluetoothCentralManagerTest.java
with MIT License
from weliem

@Test
public void scanForPeripheralsWithAddressesTest() {
    application.grantPermissions(Manifest.permission.ACCESS_COARSE_LOCATION);
    String myAddress = "12:23:34:98:76:54";
    central.scanForPeripheralsWithAddresses(new String[] { myAddress });
    // Make sure startScan is called
    ArgumentCaptor<ScanSettings> scanSettingsCaptor = ArgumentCaptor.forClreplaced(ScanSettings.clreplaced);
    ArgumentCaptor<ScanCallback> scanCallbackCaptor = ArgumentCaptor.forClreplaced(ScanCallback.clreplaced);
    verify(scanner).startScan(scanFiltersCaptor.capture(), scanSettingsCaptor.capture(), scanCallbackCaptor.capture());
    // Verify there is only 1 filter set
    List<ScanFilter> filters = scanFiltersCaptor.getValue();
    replacedertEquals(1, filters.size());
    // Verify the filter contains the address we added
    ScanFilter addressFilter = filters.get(0);
    String address = addressFilter.getDeviceAddress();
    replacedertEquals(myAddress, address);
    // Fake scan result
    ScanResult scanResult = mock(ScanResult.clreplaced);
    BluetoothDevice device = mock(BluetoothDevice.clreplaced);
    when(device.getAddress()).thenReturn(myAddress);
    when(scanResult.getDevice()).thenReturn(device);
    bluetoothAdapter.addDevice(device);
    central.defaultScanCallback.onScanResult(CALLBACK_TYPE_ALL_MATCHES, scanResult);
    ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
    // See if we get it back
    ArgumentCaptor<BluetoothPeripheral> bluetoothPeripheralCaptor = ArgumentCaptor.forClreplaced(BluetoothPeripheral.clreplaced);
    ArgumentCaptor<ScanResult> scanResultCaptor = ArgumentCaptor.forClreplaced(ScanResult.clreplaced);
    verify(callback).onDiscoveredPeripheral(bluetoothPeripheralCaptor.capture(), scanResultCaptor.capture());
    replacedertEquals(scanResultCaptor.getValue(), scanResult);
    replacedertEquals(bluetoothPeripheralCaptor.getValue().getAddress(), myAddress);
}

19 Source : BluetoothPeripheralManager.java
with MIT License
from weliem

private void cancelConnection(@NotNull final BluetoothDevice bluetoothDevice) {
    Objects.requireNonNull(bluetoothDevice, DEVICE_IS_NULL);
    Timber.i("cancelConnection with '%s' (%s)", bluetoothDevice.getName(), bluetoothDevice.getAddress());
    bluetoothGattServer.cancelConnection(bluetoothDevice);
}

19 Source : BluetoothPeripheralManager.java
with MIT License
from weliem

private void removeCentral(@NotNull final BluetoothDevice device) {
    Objects.requireNonNull(device, DEVICE_IS_NULL);
    connectedCentralsMap.remove(device.getAddress());
}

19 Source : BluetoothPeripheralManager.java
with MIT License
from weliem

@NotNull
private BluetoothCentral getCentral(@NotNull final BluetoothDevice device) {
    Objects.requireNonNull(device, DEVICE_IS_NULL);
    BluetoothCentral result = connectedCentralsMap.get(device.getAddress());
    if (result == null) {
        result = new BluetoothCentral(device.getAddress(), device.getName());
    }
    return result;
}

19 Source : BluetoothPeripheralManager.java
with MIT License
from weliem

/**
 * Send a notification or indication that a local characteristic has been
 * updated
 *
 * <p>A notification or indication is sent to all remote centrals to signal
 * that the characteristic has been updated.
 *
 * @param characteristic the characteristic for which to send a notification
 * @return true if the operation was enqueued, otherwise false
 */
public boolean notifyCharacteristicChanged(@NotNull final byte[] value, @NotNull final BluetoothGattCharacteristic characteristic) {
    Objects.requireNonNull(value, CHARACTERISTIC_VALUE_IS_NULL);
    Objects.requireNonNull(characteristic, CHARACTERISTIC_IS_NULL);
    if (doesNotSupportNotifying(characteristic))
        return false;
    boolean result = true;
    for (BluetoothDevice device : getConnectedDevices()) {
        if (!notifyCharacteristicChanged(copyOf(value), device, characteristic)) {
            result = false;
        }
    }
    return result;
}

19 Source : BluetoothPeripheralManager.java
with MIT License
from weliem

private boolean notifyCharacteristicChanged(@NotNull final byte[] value, @NotNull final BluetoothDevice bluetoothDevice, @NotNull final BluetoothGattCharacteristic characteristic) {
    Objects.requireNonNull(value, CHARACTERISTIC_VALUE_IS_NULL);
    Objects.requireNonNull(bluetoothDevice, DEVICE_IS_NULL);
    Objects.requireNonNull(characteristic, CHARACTERISTIC_IS_NULL);
    Objects.requireNonNull(characteristic.getValue(), CHARACTERISTIC_VALUE_IS_NULL);
    if (doesNotSupportNotifying(characteristic))
        return false;
    final boolean confirm = supportsIndicate(characteristic);
    final boolean result = commandQueue.add(new Runnable() {

        @Override
        public void run() {
            currentNotifyValue = value;
            currentNotifyCharacteristic = characteristic;
            characteristic.setValue(value);
            if (!bluetoothGattServer.notifyCharacteristicChanged(bluetoothDevice, characteristic, confirm)) {
                Timber.e("notifying characteristic changed failed for <%s>", characteristic.getUuid());
                BluetoothPeripheralManager.this.completedCommand();
            }
        }
    });
    if (result) {
        nextCommand();
    } else {
        Timber.e("could not enqueue notify command");
    }
    return result;
}

19 Source : BluetoothCentralManager.java
with MIT License
from weliem

/**
 * Remove bond for a peripheral.
 *
 * @param peripheralAddress the address of the peripheral
 * @return true if the peripheral was succesfully unpaired or it wasn't paired, false if it was paired and removing it failed
 */
public boolean removeBond(@NotNull final String peripheralAddress) {
    Objects.requireNonNull(peripheralAddress, NO_PERIPHERAL_ADDRESS_PROVIDED);
    // Get the set of bonded devices
    final Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
    // See if the device is bonded
    BluetoothDevice peripheralToUnBond = null;
    if (bondedDevices.size() > 0) {
        for (BluetoothDevice device : bondedDevices) {
            if (device.getAddress().equals(peripheralAddress)) {
                peripheralToUnBond = device;
            }
        }
    } else {
        return true;
    }
    // Try to remove the bond
    if (peripheralToUnBond != null) {
        try {
            Method method = peripheralToUnBond.getClreplaced().getMethod("removeBond", (Clreplaced[]) null);
            boolean result = (boolean) method.invoke(peripheralToUnBond, (Object[]) null);
            if (result) {
                Timber.i("Succesfully removed bond for '%s'", peripheralToUnBond.getName());
            }
            return result;
        } catch (Exception e) {
            Timber.i("could not remove bond");
            e.printStackTrace();
            return false;
        }
    } else {
        return true;
    }
}

19 Source : LegacyScanner.java
with Apache License 2.0
from wandersnail

@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
    parseScanResult(device, false, null, rssi, scanRecord);
}

19 Source : EasyBLE.java
with Apache License 2.0
from wandersnail

/**
 * 创建连接
 *
 * @param address       蓝牙地址
 * @param configuration 连接配置
 * @param observer      伴生观察者
 * @return 返回创建的连接实例,创建失败则返回null
 */
@Nullable
public Connection connect(@NonNull String address, @Nullable ConnectionConfiguration configuration, @Nullable EventObserver observer) {
    if (checkStatus()) {
        Inspector.requireNonNull(address, "address can't be null");
        BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(address);
        if (remoteDevice != null) {
            return connect(new Device(remoteDevice), configuration, observer);
        }
    }
    return null;
}

19 Source : EasyBLE.java
with Apache License 2.0
from wandersnail

/**
 * 开始配对
 *
 * @param address 设备地址
 */
public boolean createBond(@NonNull String address) {
    checkStatus();
    try {
        BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(address);
        return remoteDevice.getBondState() != BluetoothDevice.BOND_NONE || remoteDevice.createBond();
    } catch (Exception ignore) {
        return false;
    }
}

19 Source : Device.java
with Apache License 2.0
from wandersnail

/**
 * BLE设备实体类
 * <p>
 * date: 2019/8/3 00:08
 * author: zengfansheng
 */
public clreplaced Device implements Comparable<Device>, Cloneable, Parcelable {

    private BluetoothDevice originDevice;

    ConnectionState connectionState = ConnectionState.DISCONNECTED;

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    @Nullable
    ScanResult scanResult;

    @Nullable
    byte[] scanRecord;

    String name;

    String address;

    int rssi;

    public Device(@NonNull BluetoothDevice originDevice) {
        this.originDevice = originDevice;
        this.name = originDevice.getName() == null ? "" : originDevice.getName();
        this.address = originDevice.getAddress();
    }

    @NonNull
    public BluetoothDevice getOriginDevice() {
        return originDevice;
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    @Nullable
    public ScanResult getScanResult() {
        return scanResult;
    }

    @Nullable
    public byte[] getScanRecord() {
        return scanRecord;
    }

    public void setRssi(int rssi) {
        this.rssi = rssi;
    }

    @NonNull
    public String getName() {
        return name;
    }

    public void setName(@NonNull String name) {
        this.name = name;
    }

    @NonNull
    public String getAddress() {
        return address;
    }

    public int getRssi() {
        return rssi;
    }

    @NonNull
    public ConnectionState getConnectionState() {
        Connection connection = EasyBLE.getInstance().getConnection(this);
        return connection == null ? connectionState : connection.getConnectionState();
    }

    @Nullable
    public Boolean isConnectable() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (scanResult != null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    return scanResult.isConnectable();
                }
            }
        }
        return null;
    }

    /**
     * 是否已连接并成功发现服务
     */
    public boolean isConnected() {
        return getConnectionState() == ConnectionState.SERVICE_DISCOVERED;
    }

    /**
     * 是否已断开连接
     */
    public boolean isDisconnected() {
        ConnectionState state = getConnectionState();
        return state == ConnectionState.DISCONNECTED || state == ConnectionState.RELEASED;
    }

    /**
     * 是否正在连接
     */
    public boolean isConnecting() {
        ConnectionState state = getConnectionState();
        return state != ConnectionState.DISCONNECTED && state != ConnectionState.SERVICE_DISCOVERED && state != ConnectionState.RELEASED;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (!(o instanceof Device))
            return false;
        Device device = (Device) o;
        return address.equals(device.address);
    }

    @Override
    public int hashCode() {
        return address.hashCode();
    }

    @Override
    public int compareTo(@NonNull Device other) {
        if (rssi == 0) {
            return -1;
        } else if (other.rssi == 0) {
            return 1;
        } else {
            int result = Integer.compare(other.rssi, rssi);
            if (result == 0) {
                result = name.compareTo(other.name);
            }
            return result;
        }
    }

    @NonNull
    @Override
    public String toString() {
        return "Device{" + "name='" + name + '\'' + ", address='" + address + '\'' + '}';
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(this.originDevice, flags);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            dest.writeParcelable(this.scanResult, flags);
        }
        if (this.scanRecord != null) {
            dest.writeInt(this.scanRecord.length);
            dest.writeByteArray(this.scanRecord);
        } else {
            dest.writeInt(-1);
        }
        dest.writeString(this.name);
        dest.writeString(this.address);
        dest.writeInt(this.rssi);
        for (ConnectionState state : ConnectionState.values()) {
            if (state == connectionState) {
                dest.writeString(this.connectionState.name());
                break;
            }
        }
    }

    protected Device(Parcel in) {
        this.originDevice = in.readParcelable(BluetoothDevice.clreplaced.getClreplacedLoader());
        readFromParcel(in);
    }

    public void readFromParcel(Parcel in) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            this.scanResult = in.readParcelable(ScanResult.clreplaced.getClreplacedLoader());
        }
        int scanRecordLen = in.readInt();
        if (scanRecordLen > 0) {
            this.scanRecord = new byte[scanRecordLen];
            in.readByteArray(this.scanRecord);
        }
        String inName = in.readString();
        this.name = inName == null ? "" : inName;
        this.address = Objects.requireNonNull(in.readString());
        this.rssi = in.readInt();
        this.connectionState = ConnectionState.valueOf(in.readString());
    }

    public static final Creator<Device> CREATOR = new Creator<Device>() {

        @Override
        public Device createFromParcel(Parcel source) {
            return new Device(source);
        }

        @Override
        public Device[] newArray(int size) {
            return new Device[size];
        }
    };
}

19 Source : DefaultDeviceCreator.java
with Apache License 2.0
from wandersnail

@Nullable
@Override
public Device create(@NonNull BluetoothDevice device, @Nullable ScanResult scanResult) {
    return new Device(device);
}

19 Source : AbstractScanner.java
with Apache License 2.0
from wandersnail

// 如果系统已配对连接,那么是无法搜索到的,所以尝试获取已连接的设备
@SuppressWarnings("all")
private void getSystemConnectedDevices(Context context) {
    try {
        Method method = bluetoothAdapter.getClreplaced().getDeclaredMethod("getConnectionState");
        method.setAccessible(true);
        int state = (int) method.invoke(bluetoothAdapter);
        if (state == BluetoothAdapter.STATE_CONNECTED) {
            Set<BluetoothDevice> devices = bluetoothAdapter.getBondedDevices();
            for (BluetoothDevice device : devices) {
                Method isConnectedMethod = device.getClreplaced().getDeclaredMethod("isConnected");
                isConnectedMethod.setAccessible(true);
                boolean isConnected = (boolean) isConnectedMethod.invoke(device);
                if (isConnected) {
                    parseScanResult(device, true);
                }
            }
        }
    } catch (Exception ignore) {
    }
    // 遍历支持的,获取所有连接的
    for (int i = 1; i <= 21; i++) {
        try {
            getSystemConnectedDevices(context, i);
        } catch (Exception ignore) {
        }
    }
}

19 Source : AbstractScanner.java
with Apache License 2.0
from wandersnail

private void parseScanResult(BluetoothDevice device, boolean isConnectedBySys) {
    parseScanResult(device, isConnectedBySys, null, -120, null);
}

19 Source : AbstractScanner.java
with Apache License 2.0
from wandersnail

void parseScanResult(BluetoothDevice device, boolean isConnectedBySys, @Nullable ScanResult result, int rssi, byte[] scanRecord) {
    if ((configuration.onlyAcceptBleDevice && device.getType() != BluetoothDevice.DEVICE_TYPE_LE) || !device.getAddress().matches("^[0-9A-F]{2}(:[0-9A-F]{2}){5}$")) {
        return;
    }
    String name = device.getName() == null ? "" : device.getName();
    if (configuration.rssiLowLimit <= rssi) {
        // 通过构建器实例化Device
        Device dev = deviceCreator.create(device, result);
        if (dev != null) {
            dev.name = TextUtils.isEmpty(dev.getName()) ? name : dev.getName();
            dev.rssi = rssi;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                dev.scanResult = result;
            }
            dev.scanRecord = scanRecord;
            handleScanCallback(false, dev, isConnectedBySys, -1, "");
        }
    }
    String msg = String.format(Locale.US, "found device! [name: %s, addr: %s]", TextUtils.isEmpty(name) ? "N/A" : name, device.getAddress());
    logger.log(Log.DEBUG, Logger.TYPE_SCAN_STATE, msg);
}

See More Examples