Example usage for android.bluetooth BluetoothGatt getService

List of usage examples for android.bluetooth BluetoothGatt getService

Introduction

In this page you can find the example usage for android.bluetooth BluetoothGatt getService.

Prototype

public BluetoothGattService getService(UUID uuid) 

Source Link

Document

Returns a BluetoothGattService , if the requested UUID is supported by the remote device.

Usage

From source file:no.nordicsemi.android.nrftoolbox.dfu.DfuService.java

/**
 * Disconnects from the device and cleans local variables in case of error. This method is SYNCHRONOUS and wait until the disconnecting process will be completed.
 * /*from   w w  w . j  a v a2s.  com*/
 * @param gatt
 *            the GATT device to be disconnected
 * @param error
 *            error number
 */
private void terminateConnection(final BluetoothGatt gatt, final int error) {
    if (mConnectionState != STATE_DISCONNECTED) {
        updateProgressNotification(PROGRESS_DISCONNECTING);

        // disable notifications
        try {
            final BluetoothGattService dfuService = gatt.getService(DFU_SERVICE_UUID);
            if (dfuService != null) {
                final BluetoothGattCharacteristic controlPointCharacteristic = dfuService
                        .getCharacteristic(DFU_CONTROL_POINT_UUID);
                setCharacteristicNotification(gatt, controlPointCharacteristic, false);
                sendLogBroadcast(Level.INFO, "Notifications disabled");
            }
        } catch (final DeviceDisconnectedException e) {
            // do nothing
        } catch (final DfuException e) {
            // do nothing
        } catch (final Exception e) {
            // do nothing
        }

        // Disconnect from the device
        disconnect(gatt);
        sendLogBroadcast(Level.INFO, "Disconnected");
    }

    // Close the device
    refreshDeviceCache(gatt);
    close(gatt);
    updateProgressNotification(error);
}

From source file:no.nordicsemi.android.nrftoolbox.dfu.DfuService.java

@Override
protected void onHandleIntent(final Intent intent) {
    final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
    // In order to let DfuActivity know whether DFU is in progress, we have to use Shared Preferences 
    final SharedPreferences.Editor editor = preferences.edit();
    editor.putBoolean(PREFS_DFU_IN_PROGRESS, true);
    editor.commit();/*from  ww  w  . j  av  a2s  .c om*/

    initialize();

    final String deviceAddress = intent.getStringExtra(EXTRA_DEVICE_ADDRESS);
    final String deviceName = intent.getStringExtra(EXTRA_DEVICE_NAME);
    final String filePath = intent.getStringExtra(EXTRA_FILE_PATH);
    final Uri fileUri = intent.getParcelableExtra(EXTRA_FILE_URI);
    final Uri logUri = intent.getParcelableExtra(EXTRA_LOG_URI);
    mLogSession = Logger.openSession(this, logUri);

    mDeviceAddress = deviceAddress;
    mDeviceName = deviceName;
    mConnectionState = STATE_DISCONNECTED;

    // read preferences
    final boolean packetReceiptNotificationEnabled = preferences
            .getBoolean(SettingsFragment.SETTINGS_PACKET_RECEIPT_NOTIFICATION_ENABLED, true);
    final String value = preferences.getString(SettingsFragment.SETTINGS_NUMBER_OF_PACKETS,
            String.valueOf(SettingsFragment.SETTINGS_NUMBER_OF_PACKETS_DEFAULT));
    int numberOfPackets = SettingsFragment.SETTINGS_NUMBER_OF_PACKETS_DEFAULT;
    try {
        numberOfPackets = Integer.parseInt(value);
        if (numberOfPackets < 0 || numberOfPackets > 0xFFFF)
            numberOfPackets = SettingsFragment.SETTINGS_NUMBER_OF_PACKETS_DEFAULT;
    } catch (final NumberFormatException e) {
        numberOfPackets = SettingsFragment.SETTINGS_NUMBER_OF_PACKETS_DEFAULT;
    }
    if (!packetReceiptNotificationEnabled)
        numberOfPackets = 0;
    mPacketsBeforeNotification = numberOfPackets;

    sendLogBroadcast(Level.VERBOSE, "Starting DFU service");

    HexInputStream his = null;
    try {
        // Prepare data to send, calculate stream size
        try {
            sendLogBroadcast(Level.VERBOSE, "Opening file...");
            if (fileUri != null)
                his = openInputStream(fileUri);
            else
                his = openInputStream(filePath);

            mImageSizeInBytes = his.sizeInBytes();
            mImageSizeInPackets = his.sizeInPackets(MAX_PACKET_SIZE);
            mHexInputStream = his;
            sendLogBroadcast(Level.INFO, "Image file opened (" + mImageSizeInBytes + " bytes)");
        } catch (final FileNotFoundException e) {
            loge("An exception occured while opening file", e);
            sendErrorBroadcast(ERROR_FILE_NOT_FOUND);
            return;
        } catch (final IOException e) {
            loge("An exception occured while calculating file size", e);
            sendErrorBroadcast(ERROR_FILE_CLOSED);
            return;
        }

        // Let's connect to the device
        sendLogBroadcast(Level.VERBOSE, "Connecting to DFU target...");
        updateProgressNotification(PROGRESS_CONNECTING);

        final BluetoothGatt gatt = connect(deviceAddress);
        // Are we connected?
        if (mErrorState > 0) { // error occurred
            final int error = mErrorState & ~ERROR_CONNECTION_MASK;
            loge("An error occurred while connecting to the device:" + error);
            sendLogBroadcast(Level.ERROR,
                    String.format("Connection failed (0x%02X): %s", error, GattError.parse(error)));
            terminateConnection(gatt, mErrorState);
            return;
        }
        if (mAborted) {
            logi("Upload aborted");
            sendLogBroadcast(Level.WARNING, "Upload aborted");
            terminateConnection(gatt, PROGRESS_ABORTED);
            return;
        }

        // We have connected to DFU device and services are discoverer
        final BluetoothGattService dfuService = gatt.getService(DFU_SERVICE_UUID); // there was a case when the service was null. I don't know why
        if (dfuService == null) {
            loge("DFU service does not exists on the device");
            sendLogBroadcast(Level.WARNING, "Connected. DFU Service not found");
            terminateConnection(gatt, ERROR_SERVICE_NOT_FOUND);
            return;
        }
        final BluetoothGattCharacteristic controlPointCharacteristic = dfuService
                .getCharacteristic(DFU_CONTROL_POINT_UUID);
        final BluetoothGattCharacteristic packetCharacteristic = dfuService.getCharacteristic(DFU_PACKET_UUID);
        if (controlPointCharacteristic == null || packetCharacteristic == null) {
            loge("DFU characteristics not found in the DFU service");
            sendLogBroadcast(Level.WARNING, "Connected. DFU Characteristics not found");
            terminateConnection(gatt, ERROR_CHARACTERISTICS_NOT_FOUND);
            return;
        }

        sendLogBroadcast(Level.INFO, "Connected. Services discovered");
        try {
            // enable notifications
            updateProgressNotification(PROGRESS_STARTING);
            setCharacteristicNotification(gatt, controlPointCharacteristic, true);
            sendLogBroadcast(Level.INFO, "Notifications enabled");

            try {
                // set up the temporary variable that will hold the responses
                byte[] response = null;

                // send Start DFU command to Control Point
                logi("Sending Start DFU command (Op Code = 1)");
                writeOpCode(gatt, controlPointCharacteristic, OP_CODE_START_DFU);
                sendLogBroadcast(Level.INFO, "DFU Start sent (Op Code 1) ");

                // send image size in bytes to DFU Packet
                logi("Sending image size in bytes to DFU Packet");
                writeImageSize(gatt, packetCharacteristic, mImageSizeInBytes);
                sendLogBroadcast(Level.INFO, "Firmware image size sent");

                // a notification will come with confirmation. Let's wait for it a bit
                response = readNotificationResponse();

                /*
                 * The response received from the DFU device contains:
                 * +---------+--------+----------------------------------------------------+
                 * | byte no |  value |                  description                       |
                 * +---------+--------+----------------------------------------------------+
                 * |       0 |     16 | Response code                                      |
                 * |       1 |      1 | The Op Code of a request that this response is for |
                 * |       2 | STATUS | See DFU_STATUS_* for status codes                  |
                 * +---------+--------+----------------------------------------------------+
                 */
                int status = getStatusCode(response, OP_CODE_RECEIVE_START_DFU_KEY);
                sendLogBroadcast(Level.INFO,
                        "Responce received (Op Code: " + response[1] + " Status: " + status + ")");
                if (status != DFU_STATUS_SUCCESS)
                    throw new RemoteDfuException("Starting DFU failed", status);

                // Send the number of packets of firmware before receiving a receipt notification
                final int numberOfPacketsBeforeNotification = mPacketsBeforeNotification;
                if (numberOfPacketsBeforeNotification > 0) {
                    logi("Sending the number of packets before notifications (Op Code = 8)");
                    setNumberOfPackets(OP_CODE_PACKET_RECEIPT_NOTIF_REQ, numberOfPacketsBeforeNotification);
                    writeOpCode(gatt, controlPointCharacteristic, OP_CODE_PACKET_RECEIPT_NOTIF_REQ);
                    sendLogBroadcast(Level.INFO, "Packet Receipt Notif Req (Op Code 8) sent (value: "
                            + mPacketsBeforeNotification + ")");
                }

                // Initialize firmware upload
                logi("Sending Receive Firmware Image request (Op Code = 3)");
                writeOpCode(gatt, controlPointCharacteristic, OP_CODE_RECEIVE_FIRMWARE_IMAGE);
                sendLogBroadcast(Level.INFO, "Receive Firmware Image request sent");

                // This allow us to calculate upload time
                final long startTime = System.currentTimeMillis();
                updateProgressNotification();
                try {
                    sendLogBroadcast(Level.INFO, "Starting upload...");
                    response = uploadFirmwareImage(gatt, packetCharacteristic, his);
                } catch (final DeviceDisconnectedException e) {
                    loge("Disconnected while sending data");
                    throw e;
                    // TODO reconnect?
                }

                final long endTime = System.currentTimeMillis();
                logi("Transfer of " + mBytesSent + " bytes has taken " + (endTime - startTime) + " ms");
                sendLogBroadcast(Level.INFO, "Upload completed in " + (endTime - startTime) + " ms");

                // Check the result of the operation
                status = getStatusCode(response, OP_CODE_RECEIVE_FIRMWARE_IMAGE_KEY);
                sendLogBroadcast(Level.INFO,
                        "Responce received (Op Code: " + response[1] + " Status: " + status + ")");
                logi("Response received. Op Code: " + response[0] + " Req Op Code: " + response[1] + " status: "
                        + response[2]);
                if (status != DFU_STATUS_SUCCESS)
                    throw new RemoteDfuException("Device returned error after sending file", status);

                // Send Validate request
                logi("Sending Validate request (Op Code = 4)");
                writeOpCode(gatt, controlPointCharacteristic, OP_CODE_VALIDATE);
                sendLogBroadcast(Level.INFO, "Validate request sent");

                // A notification will come with status code. Let's wait for it a bit.
                response = readNotificationResponse();
                status = getStatusCode(response, OP_CODE_RECEIVE_VALIDATE_KEY);
                sendLogBroadcast(Level.INFO,
                        "Responce received (Op Code: " + response[1] + " Status: " + status + ")");
                if (status != DFU_STATUS_SUCCESS)
                    throw new RemoteDfuException("Device returned validation error", status);

                // Disable notifications locally (we don't need to disable them on the device, it will reset)
                updateProgressNotification(PROGRESS_DISCONNECTING);
                gatt.setCharacteristicNotification(controlPointCharacteristic, false);
                sendLogBroadcast(Level.INFO, "Notifications disabled");

                // Send Activate and Reset signal.
                logi("Sending Activate and Reset request (Op Code = 5)");
                writeOpCode(gatt, controlPointCharacteristic, OP_CODE_ACTIVATE_AND_RESET);
                sendLogBroadcast(Level.INFO, "Activate and Reset request sent");

                // The device will reset so we don't have to send Disconnect signal.
                waitUntilDisconnected();
                sendLogBroadcast(Level.INFO, "Disconnected by remote device");

                // Close the device
                refreshDeviceCache(gatt);
                close(gatt);
                updateProgressNotification(PROGRESS_COMPLETED);
            } catch (final UnknownResponseException e) {
                final int error = ERROR_INVALID_RESPONSE;
                loge(e.getMessage());
                sendLogBroadcast(Level.ERROR, e.getMessage());

                // This causes GATT_ERROR 0x85 on Nexus 4 (4.4.2)
                //               logi("Sending Reset command (Op Code = 6)");
                //               writeOpCode(gatt, controlPointCharacteristic, OP_CODE_RESET);
                //               sendLogBroadcast(Level.INFO, "Reset request sent");
                terminateConnection(gatt, error);
            } catch (final RemoteDfuException e) {
                final int error = ERROR_REMOTE_MASK | e.getErrorNumber();
                loge(e.getMessage());
                sendLogBroadcast(Level.ERROR, String.format("Remote DFU error: %s", GattError.parse(error)));

                // This causes GATT_ERROR 0x85 on Nexus 4 (4.4.2)
                //               logi("Sending Reset command (Op Code = 6)");
                //               writeOpCode(gatt, controlPointCharacteristic, OP_CODE_RESET);
                //               sendLogBroadcast(Level.INFO, "Reset request sent");
                terminateConnection(gatt, error);
            }
        } catch (final UploadAbortedException e) {
            logi("Upload aborted");
            sendLogBroadcast(Level.WARNING, "Upload aborted");
            if (mConnectionState == STATE_CONNECTED_AND_READY)
                try {
                    mAborted = false;
                    logi("Sending Reset command (Op Code = 6)");
                    writeOpCode(gatt, controlPointCharacteristic, OP_CODE_RESET);
                    sendLogBroadcast(Level.INFO, "Reset request sent");
                } catch (final Exception e1) {
                    // do nothing
                }
            terminateConnection(gatt, PROGRESS_ABORTED);
        } catch (final DeviceDisconnectedException e) {
            sendLogBroadcast(Level.ERROR, "Device has disconneted");
            // TODO reconnect n times?
            loge(e.getMessage());
            if (mNotificationsEnabled)
                gatt.setCharacteristicNotification(controlPointCharacteristic, false);
            close(gatt);
            updateProgressNotification(ERROR_DEVICE_DISCONNECTED);
            return;
        } catch (final DfuException e) {
            final int error = e.getErrorNumber() & ~ERROR_CONNECTION_MASK;
            sendLogBroadcast(Level.ERROR, String.format("Error (0x%02X): %s", error, GattError.parse(error)));
            loge(e.getMessage());
            if (mConnectionState == STATE_CONNECTED_AND_READY)
                try {
                    logi("Sending Reset command (Op Code = 6)");
                    writeOpCode(gatt, controlPointCharacteristic, OP_CODE_RESET);
                } catch (final Exception e1) {
                    // do nothing
                }
            terminateConnection(gatt, e.getErrorNumber());
        }
    } finally {
        try {
            // upload has finished (success of fail)
            editor.putBoolean(PREFS_DFU_IN_PROGRESS, false);
            editor.commit();

            // ensure that input stream is always closed
            mHexInputStream = null;
            if (his != null)
                his.close();
            his = null;
        } catch (IOException e) {
            // do nothing
        }
    }
}