Introduction

This document is an introduction to the BlueParrott SDK that allows access to the programmable Parrott Button™ on selected BlueParrott headsets.

The Parrott Button on the headset has an initial factory setting that allows the user to mute the headset microphone. This Parrott Button can be accessed from a mobile application to program alternative functions.

The BlueParrott SDK enables developers to create Android and IOS apps which interact with this Parrott Button thus allowing the headset user to access functions of your application by pressing the Parrott Button.

We expect the reader to be familiar with the chosen programming language. For specific syntax refer to the programming guide:

SDK Purpose

The purpose of the BlueParrott SDK is to let you, a corporate or independent developer, develop applications that allow the headset user to benefit from alternative functions for the Parrott Button found on BlueParrott headsets.

Through use of the BlueParrott SDK you can access the programmable Parrott Button. When your mobile application has been published the headset user may then control programmed activities within your mobile application directly from the headset via the Parrott Button.

Typical uses of the BlueParrott SDK include integration with:

  • Push to Talk and Voice Messaging Applications, where recording is triggered by pressing the Parrott Button
  • Voice Recognition and custom Voice Assistant applications, where the Voice Assistant is triggered by tapping the Parrott button
  • Other Enterprise Applications, where custom features can be triggered based on one or more button event

The Parrott Button can be configured for up to five Button Events:

  • Press (for example to start a Push to Talk Call)
  • Release (for example to end a Push to Talk Call)
  • Single Tap (to invoke a voice recognition or other enterprise application)
  • Double Tap
  • Long Press

You may program each of these events for individual functions within your mobile application.

You may limit your application to operating in the foreground only or you may wish to offer a smoother more integrated experience for the headset user by extending your application to offer handling of button events even when your applications is in the background.

SDK Purpose

The purpose of the BlueParrott SDK is to let you, a corporate or independent developer, develop applications that allow the headset user to benefit from alternative functions for the Parrott Button found on BlueParrott headsets.

Through use of the BlueParrott SDK you can access the programmable Parrott Button. When your mobile application has been published the headset user may then control programmed activities within your mobile application directly from the headset via the Parrott Button.

Typical uses of the BlueParrott SDK include integration with:

  • Push to Talk and Voice Messaging Applications, where recording is triggered by pressing the Parrott Button
  • Voice Recognition and custom Voice Assistant applications, where the Voice Assistant is triggered by tapping the Parrott button
  • Other Enterprise Applications, where custom features can be triggered based on one or more button event

The Parrott Button can be configured for up to five Button Events:

  • Press (for example to start a Push to Talk Call)
  • Release (for example to end a Push to Talk Call)
  • Single Tap (to invoke a voice recognition or other enterprise application)
  • Double Tap
  • Long Press

You may program each of these events for individual functions within your mobile application.

You may limit your application to operating in the foreground only or you may wish to offer a smoother more integrated experience for the headset user by extending your application to offer handling of button events even when your applications is in the background.

SDK Scope

This documents covers BlueParrott Android SDK V1.3.1.06 and BlueParrott iOS 1.0.11.4.

The BlueParrott SDK provides interfaces to the following functions in compatible BlueParrott devices:

  • Configuration of the Parrott Button for use with the application.
  • Setting the BlueParrott Button into 'SDK Mode', this will result in button events being sent to your application.
  • Event Handlers for Parrott Button events.

Android

BlueParrott Android SDK.

The package includes the following development tools:

  • SDK Library
  • Example test application to show connectivity and connected device Parrott Button state
  • Example test application to additionally show foreground and background processing and utilise audio.
  • Notes and documentation.

iOS

BlueParrott iOS SDK.

The package includes the following development tools:

  • SDK Library.
  • Example test application to show connectivity and connected device Parrott Button state.
  • Notes and documentation.

View our current platform support Jabra and BlueParrott Developer Zone

Not in Scope

This document does not cover Android or IOS programming specifics, the developer should access the relevant sites for the development language.

Audio recording and playback is not part of the BlueParrott SDK, however some considerations for audio applications are discussed with reference to the sample application under Advanced Android Integration.

Updates

The BlueParrott SDK will be updated from time to time, please check for updates.

Supported Headsets

The following is a list of devices which have a Parrott Button and are supported by the BlueParrott SDK.

Headset
BlueParrott B550-XT
BlueParrott B450-XT
BlueParrott B350-XT
BlueParrott C400-XT
BlueParrott Reveal Pro
BlueParrott S450-XT

Supported Operating Systems

The BlueParrott SDK supports both Android (minimum version 4.4) and iOS (minimum version 9.1).

Android On Android, the capabilities vary slightly depending on the Android version as follows

Android 4.4 – SDK supports integration with the BlueParrott B550-XT only
Android 5 and greater – SDK supports integration with all headsets listed above.

Getting Started - Android

How the SDK Works

Communication between the handset and headset is via Bluetooth and can be over Classic Bluetooth or Bluetooth Low Energy (BLE).

Different headsets support different Bluetooth protocols,. This can be transparent to the developer, although in certain circumstances you may wish to force connection to the Parrott Button over Classic Bluetooth. On some Android versions this is more stable, and also requires less Permissions, making it easier to integrate into Enterprise Applications. Note that currently only the B550-XT headset supports connection to the Parrott Button over Bluetooth Classic. All headsets support connection over Bluetooth Low Energy.

Your may choose to force your application to connect to the Parrott Button via Classic or BLE Bluetooth or allow it to select the protocol using the Auto option.

The Auto option attempts to connect via Classic Bluetooth first and if that fails will attempt to connect over BLE.

Including the SDK

If using the gradle build tool the following will need to be included in the app build gradle


dependencies {
    compile(name: 'blueparrottsdk-release', ext: 'aar')

In addition the following will be required in the project build gradle


repositories {
        flatDir {
            dirs 'libs'
        }

Android

The minimum Android version is 19, although the current target android version is 27.

In order to include the BlueParrott SDK in your application copy the blueparrottsdk-release.aar SDK in to the Android library.

Depending on your build configuration appropriate changes will have to be made in order to include the compiled SDK in your project.

Permissions

Bluetooth

<!-- required for bluetooth -->

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

Connection between the handset and headset is via Bluetooth. The BlueParrott SDK allows three methods for bluetooth connection:

  • auto
  • classic
  • ble

For Android programming you must include specific permissions for Bluetooth connection, the Bluetooth connection is managed by the BlueParrott SDK but your program must include the uses-permission for Bluetooth.

Enable Bluetooth

The BlueParrott SDK manages the Bluetooth connection but you must manage the enabling of Bluetooth in your code. An approach to this is to alert the application user if Bluetooth is not available and ask the user to turn Bluetooth on in their handset settings, you must then provide another opportunity to connect.

Location

<!-- the following is only required if supporting BLE Versions of the Parrott Button -->
<!-- required on android 6.0 or greater to get at ble-->

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

If your Android program is targeting a BLE BlueParrott headset and the target android API is level 23 or greater then you must ask your user for permission to access location.

There are two options for access to location permission ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION. Either access permission will work for BLE access and the one you choose will be a consideration for you based on other functionality of your application.

Location permission prompt

If required you should prompt your user for permission to use location and handle their response appropriately. If access to location is denied you may need to advise of the limitations for use of your application if location use is not allowed for BLE. You can avoid the need for this permission by selecting CLASSIC as the connection method if you are just targeting the B550-XT headset.

     if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
     //place your code here

Connect to the Parrott Button

The first step is to get a handle to the Parrott Button on the BlueParrott Headset.

Now you have the ability to check the connection and connect or disconnect to the headset.

There are a number of methods to connect depending on the headset being used. Auto attempts to connect via classic Bluetooth first and if that fails will attempt to connect over BLE.

CONNECT_METHOD_ Value
AUTO 0
CLASSIC 1
BLE 2

The BlueParrott SDK method connect manages the Parrott Button connection and ensures that the relevant Bluetooth connection is available.

import com.blueparrott.blueparrottsdk.BPSdk;
import com.blueparrott.blueparrottsdk.BPHeadset;

BPHeadset headset;

    // Get a handle to the Parrott Button on the headset
    headset = BPSdk.getBPHeadset(this);

    if (!headset.connected()) {
               logStatus("Connecting");
               headset.connect(CONNECT_METHOD_AUTO);
                // perform your own code
    }

Listen for Connection Events

Through the BlueParrott SDK your app can get a handle to the Parrott Button on the headset, you can then add a Blue Parrott Headset Listener.

import com.blueparrott.blueparrottsdk.BPHeadsetListener;


public class BpSDKDemo extends AppCompatActivity implements BPHeadsetListener {

    BPHeadset headset;

    //get a handle to the Parrott Button on the headset
    headset = BPSdk.getBPHeadset(this)

    //add a BPHeadsetListener
    headset.addListener(this);

    @Override
    public void onConnect() {
        logStatus("Connected");
        //place your code here
    }

The BlueParrott listener allows your application to listen for the stages associated with establishing a connection to the Parrott Button:

Connected

When your app is successfully connected to the Parrott Button a connected event is triggered.

Connection Progress

You may retrieve the status of progress during the connection process, and optionally keep your user informed of progress.


Method from class : com.blueparrott.blueparrottsdk.BPHeadsetListener
--------------------------------------------------------------------

@Override
public void onConnectProgress(int progressCode) {
    logStatus(getStatusDescription(progressCode));
}

Note: Constants from class BPHeadsetListener are in the format PROGRESS_WAITING_TO_CONNECT as per table

PROGRESS_ Value Meaning
WAITING_TO_CONNECT 0 Connection attempt will commence shortly
STARTED 1 Connection attempt has started
FOUND_CLASSIC_HEADSET 2 A Bluetooth headset has been found
REUSING_CONNECTION 3 Another app is connected over BLE, attempting to re-use connection
BLE_SCANNING_ 4 Scanning for BLE services
FOUND_BP_SERVICE 5 The BlueParrott service has been found
CONNECTING_TO_BLE 6 Attempting to connect to the BlueParrott service over BLE
READING_HEADSET_VALUES 7 BLE connection established, reading settings from headset
USING_BT_CLASSIC 8 Checking to see if Classic is available

Connection Failure

Method from class : com.blueparrott.blueparrottsdk.BPHeadsetListener
--------------------------------------------------------------------

@Override
If the connection attempt fails the following error codes may be returned and should be handled in your code.

public void onConnectFailure(int errorCode) {
    //handle the connection failure here
    //this may include instruction "Retry or turn headset off then on"
}

Note: Constants from class BPHeadsetListener are in the format CONNECT_ERROR_UPDATE_ANDROID as per table
CONNECT_ERROR_ Value Meaning
UPDATE_ANDROID 1 Android OS 4.4 or greater required for Classic Connection
BLUETOOTH_NOT_AVAILABLE 2 Bluetooth is not turned on
ALREADY_CONNECTED 3 Parrott Button is already connected
ALREADY_CONNECTING 4 Another connection attempt is already under way
NO_HEADSET_CONNECTED 5 There is no Bluetooth headset connected
HEADSET_NOT_SUPPORTED 6 Headset may not support Parrott Button
UPDATE_YOUR_FIRMWARE 7 Firmware on the headset is not offering Parrott Button Service. Firmware may be too old
UPDATE_YOUR_SDK_APP 8 This SDK/App is too old to connect to the firmware version on headset
HEADSET_DISCONNECTED 9 Headset classic connection disconnected during BLE connection attempt
TIMEOUT 10 Unknown error, connection attempt has timed out
BLE_REQUIRES_LOLLIPOP 11 Android OS 5.0/Lollipop or greater required for BLE Connection

Setting the Parrott Button Mode

Once connected to the Parrott Button the next step is to enable the Parrott Button in order to send events from the Parrott Button on the headset to your application on the handset. It is possible to check to see if the Parrott Button has been enabled previously and if not you may proceed to enable it.

If required by your program you may also disable the Parrott Button SDK this would reset the Parrott Button to the factory setting of a mute button.

if (!headset.sdkModeEnabled()) {
    logStatus("Enabling SDK...");
    headset.enableSDKMode();
}

if (headset.sdkModeEnabled()) {
    headset.disableSDKMode();
    //do something...
}

Listen for Parrott Button Mode Update

You can monitor the success of enabling the SDK using the mode update methods from the BlueParrott Headset Listener.

Methods from class : com.blueparrott.blueparrottsdk.BPHeadsetListener
---------------------------------------------------------------------

@Override
public void onModeUpdate() {
    logStatus("Mode Updated");
}      

Listen for Parrott Button Mode Update Failure

Methods from class : com.blueparrott.blueparrottsdk.BPHeadsetListener
---------------------------------------------------------------------

@Override
public void onModeUpdateFailure (int reasonCode) {
    logStatus("Mode Update Failed. Reason" +getUpdateErrorDescription(reasonCode));
    //handle error
}

If mode update fails you may look for one of the following update errors to provide feedback to the user.

UPDATE_ERROR_ Value Meaning
NOT_CONNECTED 1 BLE connection not available
WRITE_FAILED 2 Writing to headset over BLE failed
TIMEOUT 3 Operation timed out

Once you enable the SDK on the Parrott Button data can be sent over bluetooth from the headset to your app for Parrott Button events.

You can then use BlueParrott Headset listener to monitor the traffic from the headset.


if (headset.sdkModeEnabled()) {
    logStatus("Disabling SDK...");
    headset.disableSDKMode();
}

Listening for Parrott Button Events

Once connected to the Parrott Button, with the button enabled to send events the BlueParrott Listener for the BlueParrott SDK may be used to monitor clicks of the Parrott Button.

When the user clicks on the headset Parrott Button your app will receive an event and can react to the users interactions.

The BlueParrott Listener provides methods to allow your code to interact with the users headset Parrott Button clicks:

  • Button Down - button has been pressed
  • Button Up - button has been released
  • Tap - single tap
  • Double Tap
  • Long Press
Methods from class : com.blueparrott.blueparrottsdk.BPHeadsetListener
---------------------------------------------------------------------

@Override
public void onButtonDown(int buttonId) {
    logStatus("Button Down");
    //your code goes here
}

@Override
public void onButtonUp(int buttonId) {
    logStatus("Button Up");
     //your code goes here
}

@Override
public void onTap(int buttonId) {
    logStatus("Tap");
    //your code goes here
}

@Override
public void onDoubleTap(int buttonId) {
    logStatus("DoubleTap");
    //your code goes here

@Override
public void onLongPress(int buttonId) {
    logStatus("Long Press");
    //your code goes here
}

Disconnecting from the Parrott Button

Generally at this point you will have established a handle to the BlueParrott Headset Button in order to connect to the Parrott Button.

Now you have the ability to check if the Parrott Button is connected and you can disconnect the Parrott Button in your code if required.

import com.blueparrott.blueparrottsdk.BPSdk;
import com.blueparrott.blueparrottsdk.BPHeadset;

BPHeadset headset;

//get a handle to the headset
    headset = BPSdk.getBPHeadset(this);

    if (headset.connected()) {
               logStatus("Disconnecting..");
               headset.disconnect();
           }

It is appropriate that at a point where the app is running in the foreground only and the UI is being shutdown that the app would disconnect from the Parrott Button.

    //in onDestroy
    if (headset != null) {
                headset.disconnect();
            }

Listen to Disconnect

Using the BlueParrott Headset Listener you may listen for a disconnect event in your program and carry out any appropriate actions and housekeeping at this point.

import com.blueparrott.blueparrottsdk.BPHeadsetListener;


public class BpSDKDemo extends AppCompatActivity implements BPHeadsetListener {

    //add a BPHeadsetListener
    headset.addListener(this);

        @Override
        public void onDisconnect() {
            logStatus("Disconnected");
             //do stuff here
        }

Simple Sample Application

There are two sample apps available for Android, this is a sample of a simple integration. Allowing the developer to get up and running quickly while using the BlueParrott SDK.

The blueParrottSDKdemo sample application runs in the foreground only. It allows you to connect to and disconnect from the Parrott Button. You may enable and disable the SDK on the Parrott Button. When the SDK is enabled it gives you feedback on the clicks of the Parrott Button.

This simple demo includes the following features:

  • Connects to headset Parrott Button
  • Includes a choice of connection via classic Bluetooth, BLE or Auto connection
    • including obtaining required Bluetooth permission
  • Enables BlueParrott SDK
  • Utilises BlueParrott listener recognising the Parrott Button clicks
  • Disables BlueParrott SDK
  • Disconnects from the headset Parrott Button

This is a sample screen from the application:

Screenshot BPSDKDemo

Getting Started - iOS

Including the SDK

The minimum iOS version is 9.1.

Add the BlueParrott SDK to your project by dragging the framework file into your project.

In your project's Target, enable Background Modes and tick 'Uses Bluetooth LE accessories' if you will be using the button while the app is in the background.

Permissions

Bluetooth

Enable Bluetooth

The BlueParrott SDK manages the Bluetooth connection but you must manage the enabling of Bluetooth in your code. An approach to this is to alert the application user if Bluetooth is not available and ask the user to turn Bluetooth on in their handset settings, you must then provide another opportunity to connect.

Use specific permissions

There are many different permissions depending on the function of the application program in question it is up to the programmer to ensure that all other permissions for your program are included (e.g. microphone).

Connect to the Parrott Button

Connect to the Parrott Button using methods from the BlueParrott SDK.

The first step is to get a handle to the Parrott Button on the BlueParrott Headset.

Now you have the ability to check the connection and connect or disconnect to the headset.

The BlueParrott SDK method connect manages the Parrott Button connection and ensures that the Bluetooth LE connection is available.

    // ViewController.h

    #import <BPHeadset/BPHeadset.h>
    @interface ViewController : UIViewController <BPHeadsetListener>
    // ...
    @end
    // ViewController.m

    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        // To instantiate, just use `sharedInstance`:
        headset = [BPHeadset sharedInstance];
        [headset addListener:self];
    }

    // To connect, set a listener that conforms to the BPHeadsetListener protocol, then call connect:
    - (IBAction)connectButtonTouched:(id)sender {
        [headset connect];
    }
    @end

Listen for Connection Events

Through the BlueParrott SDK your app can get a handle to the Parrott Button on the headset, you can then add a Blue Parrott Headset Listener.

    // ViewController.h

    #import <BPHeadset/BPHeadset.h>
    @interface ViewController : UIViewController <BPHeadsetListener>
    // ...
    @end
    // ViewController.m

    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        // To instantiate, just use `sharedInstance`:
        headset = [BPHeadset sharedInstance];
        [headset addListener:self];
    }

    // To connect, set a listener that conforms to the BPHeadsetListener protocol, then call connect:
    - (void) onConnect {
        NSLog(@"Connected");
        // place your code here
    }
    @end

The Blue Parrott listener allows your app to listen and manage activities associated with establishing a connection to the Parrott Button:

Connected

When your app is successfully connected to the Parrott Button a connected event is triggered.

Connection Progress

You may retrieve the status of progress during the connection process, as connection may take time it is advisable to keep your user informed of progress.

Method from protocol: BPHeadsetListener
--------------------------------------------------------------------

public void onConnectProgress:(BPConnectProgress) status {
    logStatus(getStatusDescription(progressCode));
}

Note: Constants from BPConnectProgress are as per table
Status Value Meaning
BPConnectProgressStarted 0 Connection attempt has started
BPConnectProgressScanning 1 Scanning for BLE services
BPConnectProgressFound 2 The BlueParrott service has been found
BPConnectProgressReading 3 BLE connection established, reading settings from headset

Connection Failure

If the connection attempt fails the following error codes may be returned and should be handled in your code.

Method from protocol: BPHeadsetListener
--------------------------------------------------------------------

- (void) onConnectFailure:(BPConnectError) reasonCode {
    //handle the connection failure here
    //this may include instruction "Retry or turn headset off then on"
}

Note: Constants from BPConnectError are as per table
Reason Code Value Meaning
BPConnectErrorUnknown 0 Unknown error occurred
BPConnectErrorBluetoothDisabled 1 Bluetooth is not turned on
BPConnectErrorFirmwareTooOld 2 Firmware on the headset is not offering Parrott Button Service. Firmware may be too old
BPConnectErrorSDKTooOld 3 This SDK/App is too old to connect to the firmware version on headset

Setting the Parrott Button Mode

Once connected to the Parrott Button the next step is to enable the Parrott Button in order to send events from the Parrott Button on the headset to your application on the handset. It is possible to check to see if the Parrott Button has been enabled previously and if not you may proceed to enable it.

    // ViewController.m
    // Enable SDK Mode
    if (!headset.sdkModeEnabled) {
        [headset enableSDKMode];
    }

    // Disable SDK Mode
    if (headset.sdkModeEnabled) {
        [headset disableSDKMode];
    }

If required by your program you may also disable the Parrott Button SDK this would reset the Parrott Button to the factory setting of a mute button.

Listen for Parrott Button Mode Update

You can monitor the success of enabling the SDK using the mode update methods from the BlueParrott Headset Listener.

Methods from protocol: BPHeadsetListener
---------------------------------------------------------------------

    - (void) onModeUpdate {
        NSLog(@"Mode Updated");
    }

Listen for Parrott Button Mode Update Failure

If mode update fails you may look for one of the following update errors to provide feedback to the user.

Methods from protocol: BPHeadsetListener
---------------------------------------------------------------------

    - (void) onModeUpdateFailure:(BPModeUpdateError) reasonCode {
        NSLog(@"Mode Update Failed. Reason %@", [self getUpdateErrorDescription:reasonCode]);
        //handle error
    }
Reason Code Value Meaning
BPModeUpdateErrorUnknown 0 Writing to headset over BLE failed
BPModeUpdateErrorDisconnected 1 BLE connection not available

Once you enable the SDK on the Parrott Button data can be sent over Bluetooth from the headset to your app for Parrott Button events.

You can then use BlueParrott Headset listener to monitor the traffic from the headset.

Listening for Parrott Button Events

Once connected to the Parrott Button, with the button enabled to send events the BlueParrott Listener for the BlueParrottSDK may be used to monitor clicks of the Parrott Button.

When the user clicks on the headset Parrott Button your app will receive an event and can react to the users interactions.

The BlueParrott Listener provides methods to allow your code to interact with the users headset Parrott Button clicks:

  • Button Down - button has been pressed

  • Button Up - button has been released

  • Tap - single tap

  • Double Tap

  • Long Press

Methods from protocol: BPHeadsetListener
---------------------------------------------------------------------

- (void) onButtonDown:(BPButtonID) buttonID {
    NSLog(@"Button Down");
     //your code goes here
}

- (void) onButtonUp:(BPButtonID) buttonID {
    NSLog(@"Button Up");
     //your code goes here
}

- (void) onTap:(BPButtonID) buttonID {
    NSLog(@"Tap");
    //your code goes here
}

- (void) onDoubleTap:(BPButtonID) buttonID {
    NSLog(@"Double Tap");
    //your code goes here
}

- (void) onLongPress:(BPButtonID)buttonID {
    NSLog(@"Long Press");
     //your code goes here
}

Disconnecting from the Parrott Button

Generally at this point you will have established a handle to the BlueParrott Headset Button in order to connect to the Parrott Button.

Now you have the ability to check if the Parrott Button is connected and you can disconnect the Parrott Button in your code if required.

    // ViewController.m

    - (IBAction)disconnectButtonTouched:(id)sender {
        if (headset.connected) {
            [headset disconnect];
        }
    }
    @end

Listen to Disconnect

Using the BlueParrott Headset Listener you may listen for a disconnect event in your program and carry out any appropriate actions and housekeeping at this point.

    // ViewController.h

    #import <BPHeadset/BPHeadset.h>
    @interface ViewController : UIViewController <BPHeadsetListener>
    // ...
    @end
    // ViewController.m

    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        // To instantiate, just use `sharedInstance`:
        headset = [BPHeadset sharedInstance];
        [headset addListener:self];
    }

    // Called when the headset is disconnected (e.g. out of range)
    - (void) onDisconnect {
        // Notify the user
    }
    @end

Simple Sample Application

The iOS SDK Sample Application is a sample of a simple integration, allowing the developer to get up and running quickly while using the BlueParrott SDK.

The BPSDKSample application runs in the foreground only. It allows you to connect to and disconnect from the Parrott Button. You may enable and disable the sdk on the Parrott Button. When the SDK is enabled it gives you feedback on the clicks of the Parrott Button.

This simple demo includes the following features:

  • Connects to headset Parrott Button
  • Enables BlueParrott SDK mode
  • Utilises BlueParrott listener recognising the Parrott Button clicks
  • Disables BlueParrott SDK mode
  • Disconnects from the headset Parrott Button

This is a sample screen from the application:

Screenshot BPSDKDemo

Advanced Android

This section covers additional integration considerations and suggestions when developing audio applications that will use the Parrott Button on the Android platform

Sample Application

An additional sample application, blueParrottSDKaudiodemo, is included with the SDK that has code samples for the topics covered in this section.

This demo application demonstrates many of the techniques necessary to integrate the Parrott Button into a Push To Talk or other voice application. The example implements a simple voice-echo feature. When the user presses the Parrott Button, it records audio in a temporary file and when the Parrott Button is released, the audio is replayed.

The feature works in both foreground (with a full user interface) and background (with the user actions shown in the Notification Bar).

The application includes the following features:

  • Ensures required permissions are obtained
  • Automatically maintains a connection to the Parrott Button
  • Sets Parrott Button into SDK Mode
  • Users Services to run in background keeps foreground UI in synch with Parrott Button
  • Records audio when the Parrott Button is depressed
  • Playback of audio when Parrott Button is released
  • The Noficiation Bar is updated with an icon to indicate current app state (connected, recording, playing)

This is a sample screen from the application running in the foreground:

Screenshot BPSDKaudiodemo Foreground

This is a sample screen from the application running in background with the Parrott Head icon displayed in Notification Bar:

Screenshot BPSDKaudiodemo Background

Application Structure

The application has the following major Classes

  • MainActivity – This is the main user interface Activity. The user can invoke Record and Playback by touching the on-screen button. This Activity is also where the user is prompted to grant necessary permissions
  • SdkConnectionService – this Service is used to manage the connection to the Parrott Button. It watches for the connection of a headset and attempts to connect to the Parrott Button. Likewise, when it sees a Headset disconnect, it will release the connection to the Parrott Button
  • RecPlayAudioService – this Service is used to record and play back the audio. Audio is recorded to and played back from, a temporary file
  • StartServicesOnBoot – this is a BroadcastReceiver launched when the handset is booted. It is used to launch the SDKConnectionService and RecPlayAudioService

Connection Management

The job of the SdkConnectionService is to automatically maintain a connection to the ParrottButton when a BlueParrott headset is connected to the handset.

The service automatically detects when a bluetooth headset is connected (via the BluetoothDevice.ACTION_ACL_CONNECTED action) and sets up the connection to the Parrott Button via the SDK.

Likewise, when the headset is disconnected (via the BluetoothDevice.ACTION_ACL_DISCONNECTED action), the connection to the Parrott Button is torn down.

Setting up Receivers

When the Service is created it instantiates Receivers to do the work of connecting and disconnecting from the Parrott Button. These receivers will be triggered automatically by headset connection/disconnects. (The receivers are registered later).

//when service is created
public void onCreate() {
    super.onCreate();
    headsetSdk = BPSdk.getBPHeadset(this);
    headsetConnectReceiver = new HeadsetConnectReceiver();
    headsetDisconnectReceiver = new HeadsetDisconnectReceiver();
}

The HeadsetConnectReceiver will be triggered when a Bluetooth Headset is connected, and will result in an attempt to connect to the Parrott Button.

//React to connection of any Bluetooth headset - attempt to connect to SDK
 public class HeadsetConnectReceiver extends BroadcastReceiver {
     public void onReceive(Context context, final Intent intent) {
         String action = intent.getAction();
         BluetoothDevice bluetoothDevice;
         if (action.equals((BluetoothDevice.ACTION_ACL_CONNECTED))){
             bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
             Log.d(LOGTAG, " App received ACL_CONNECTED for "+ bluetoothDevice.getName() );
             deRegisterForConnect();

             //Add a listener to the headsetSDK object
             headsetSdk.addListener(SdkConnectionService.this);

             //use a 1s delay on the runnable to allow Bluetooth complete its business
             handler.postDelayed(runConnectSDK, 1000);
         }
     }
 }

The HeadsetDisconnectReceiver will be triggered when a Bluetooth Headset is diconnected, and will result in an attempt to disconnect from the Parrott Button. It will also register to recieve connect events in the future (so that when user re-connects the headset, the Parrott Button will automatically be connected)

//React to disconnection of any Bluetooth headset - disconnect from SDK
public class HeadsetDisconnectReceiver extends BroadcastReceiver {
    public void onReceive(Context context, final Intent intent) {
        String action = intent.getAction();
        BluetoothDevice bluetoothDevice;
        if (action.equals((BluetoothDevice.ACTION_ACL_DISCONNECTED))){
            bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            Log.d(LOGTAG, bluetoothDevice.getName() + " is disconnected");
            deRegisterForDisconnect();
            registerForConnect();
        }
    }

Registering the Receivers

When the SdkConnectionService starts it checks to see if there is a Headset already connected, and if there is, it attempts to connect to the Parrott Button via the SDK. It will also register to be notified when the headset disconnects by calling registerForDisconnect().

public int onStartCommand(Intent intent, int flags, int startId) {
   if (Utils.isBluetoothHeadsetConnected()) {
       if (!(headsetSdk.connected())) {
           headsetSdk.addListener(SdkConnectionService.this);
           handler.postDelayed(runConnectSDK, 1000);//delay for bluetooth to allow for timing issues (give OS a chance to catch up)
       }
       else{
           registerForDisconnect();
       }
   } else {
       registerForConnect();
   }
   return Service.START_STICKY;  //service will restart automatically
}

After that the recievers are registered and deregistered according to the following pattern.

  1. When a headset is connected

    • Deregister for connect receiver
    • Register for disconnect receiver
  2. Headset disconnected

    • Deregister for disconnect receiver
    • Register for connect receiver

There are some helper methods that will register these receivers based on the pattern described below


    private void registerForConnect() {
        IntentFilter fltr = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
        registerReceiver(headsetConnectReceiver, fltr);
    }


      private void registerForDisconnect() {
          IntentFilter fltr = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
          registerReceiver(headsetDisconnectReceiver, fltr);
      }

      private void deRegisterForDisconnect() {
         try {
             unregisterReceiver(headsetDisconnectReceiver);
             } catch (IllegalArgumentException e) {
                 e.printStackTrace();
                }
      }

      private void deRegisterForConnect() {
         try {
             unregisterReceiver(headsetConnectReceiver);
             } catch (IllegalArgumentException e) {
                  e.printStackTrace();
                 }
      }

Connect to Parrott Button

The runConnectSDK runnable just calls the headsetSdk.connect() method.

    private Runnable runConnectSDK = new Runnable() {
       @Override
       public void run() {
           headsetSdk.connect();
       }
   };

Register for Disconnect Receiver

Once an attempt to connect to the Parrott Button has concluded, we can register for the disconnect broadcast receiver so that you listen for the Bluetooth ACL disconnect action again which will in turn trigger a disconnect from the Parrott Button.

@Override
    public void onConnect() {
        headsetSdk.enableSDKMode();
        //set up recevier to monitor for disconnects
        registerForDisconnect();
    }

    @Override
    public void onConnectFailure(int reasonCode) {
        //set up recevier to monitor for disconnects
        registerForDisconnect();
    }

On Boot Connection

Auto boot refers to automatically running your application when the handset is switched on or rebooted.

// Manifest changes are required to auto boot using a receiver
// which will start services in background.
// The receiver listens for BOOT_COMPLETED action which occurs with a cold start of the handset.
// The receiver also listens for QUICKBOT_POWERON action which occurs with a reboot of the handset
// Then within the broadcast receiver you may start the required services.

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<receiver
    android:name="com.mysay.blueparrottsdkaudiodemo.StartServicesOnBoot"
    android:enabled="true"
    android:exported="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
</receiver>

Notification Icons

The Parrott Head Icon is not part of the BlueParrott SDK, however it is included in the Sample Apps.

It is designed to be displayed in the Notification Bar. It can be used to indicate when the Parrott Button is connected by displaying it. If used you should then clear it from the notification bar when disconnected from the Parrott Button. Through the use of the inverted Parrott Head the icon can be used to indicate to the user when an activity is taking place.

The Parrott Head Icon can be displayed while your application is in the foreground and is particularly useful in giving your user feedback when the application is running in the background.

//we are connected so show that in the notification bar
Utils.createNotification(this, RecPlayAudioService.AUDIO_STATE_IDLE);

//connection has failed, ensure we clear the notification bar
Utils.cancelHeadsetStatusNotification(this);

Icon Description
Parrott Head Parrott Head
Parrott Head invert Parrott Head inverted

Audio Record and Playback

There are various considerations for audio applications. It is beyond the scope of this document to cover all audio methods for recording and playback, however here are a couple of pointers you should consider when recording audio as a result of a Parrott Button Press.

SCO

Synchronous Connection Oriented (SCO) is for real-time narrow band signal which does not require retransmission. Generally applications recording over Bluetooth use SCO for VOIP and audio recording.

In order to record voice from the Bluetooth headset you must wait for the SCO channel to open. The Sample application uses a broadcast receiver to listen for this.

When recording is completed you should stop SCO.

If your application is recording from an alternative non-Bluetooth device you may record without reference to SCO.

//onCreate
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

public void startRecording() {
    if (Utils.isBluetoothHeadsetConnected()) {
    //Setup a receiver to notify us when SCO is connected
     registerReceiver(new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
             if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
                 broadcastAudioState(AUDIO_STATE_RECORDING);
                 isRecording = true;
                 recordThread = new RecordThread();
                 recordThread.start();
                 unregisterReceiver(this);
             }
         }
     }, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
     broadcastAudioState(AUDIO_STATE_WAITING_FOR_SCO);
     audioManager.startBluetoothSco();

public void stopRecording() {
    if (Utils.isBluetoothHeadsetConnected()) {
        audioManager.stopBluetoothSco();
        }

Record Thread

The sample application uses a thread to record to audio to a temporary .pcm file.

Recording is started when the Parrott Button is depressed.

A Buffer Output Stream is used in order to write to the temporary file.

 class RecordThread extends Thread {
     public void run() {
         try {
             byte[] buffer = new byte[mRecBufSize];
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(mPcmFile), mRecBufSize);
             audioRecord.startRecording();
             while (isRecording) {
                 int bufferReadResult = audioRecord.read(buffer, 0, mRecBufSize);
                 byte[] tmpBuf = new byte[bufferReadResult];
                 System.arraycopy(buffer, 0, tmpBuf, 0, bufferReadResult);
                 bos.write(tmpBuf, 0, tmpBuf.length);
             }
             bos.flush();
             bos.close();
             audioRecord.stop();
         } catch (Throwable t) {
             Log.d(LOGTAG, "error:" + t.getMessage());
         }
     }
 }

Stop Recording

When the Parrott Button is released the BlueParrott listener triggers the onButtonUp method, this is programmed to stop recording.

When it is time to stop recording you use a thread.join() to ensure that all the business of the record thread is completed before returning to calling class.

The method to start playing is called from the stop recording method.

   public void stopRecording() {
       // close the SCO channel
       if (Utils.isBluetoothHeadsetConnected()) {
           audioManager.stopBluetoothSco();
       }
       // wind down the thread and get in sync with it
       isRecording = false;
       try {
           if (recordThread != null) recordThread.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       startPlaying();
   }

Play Thread

The sample application uses a thread to play back the contents of the temporary .pcm file.

When the Parrott Button is released the BlueParrott listener triggers the onButtonUp method, in the sample program this is programmed to stop recording and start playback.

Recording is started when the Parrott Button is depressed.

A Buffer Input Stream is used in order to read from the temporary file.

 class PlayThread extends Thread {
     public void run() {
         try {
             sleep(500);//wait a bit
             byte[] buffer = new byte[mPlayBufSize];
             BufferedInputStream bis = new BufferedInputStream(new FileInputStream(mPcmFile), mPlayBufSize);
             audioTrack.play();
             int readSize = -1;
             while (isPlaying && (readSize = bis.read(buffer)) != -1) {
                 audioTrack.write(buffer, 0, readSize);
             }
             audioTrack.stop();
             bis.close();
             broadcastAudioState(AUDIO_STATE_IDLE);
         } catch (Throwable t) {
             Log.d(LOGTAG, "error:" + t.getMessage());
         }
     }
 }

Broadcast Audio state to UI

A broadcast receiver is used in order to communicate to the UI the status of the audio activity.

In the sample application this audio state is used to determine which Parrott Head Icon to display in the Notification Bar, and the color of the Talk Button when the application is in the foreground.

public static final int AUDIO_STATE_IDLE = 0;
public static final int AUDIO_STATE_WAITING_FOR_SCO = 1;
public static final int AUDIO_STATE_RECORDING = 2;
public static final int AUDIO_STATE_PLAYING = 3;

//onCreate
//setup a localbroadcaster that we will use to tell the UI about state changed
broadcaster = LocalBroadcastManager.getInstance(this);

/*
  * Broadcast the audio state to the UI
  */
 public void broadcastAudioState(int audioState) {

     Utils.createNotification(this, audioState);
     Intent intent = new Intent(BP_AUDIO_STATE_BROADCAST);
     intent.putExtra(AUDIO_STATE_MESSAGE, audioState);
     broadcaster.sendBroadcast(intent);
 }

Troubleshooting

Android TroubleShooting

Failure to Connect to Parrott Button

  • Is Headset Connected (check Bluetooth Settings to see that headset is paired and connected)
  • Have you granted necessary Permissions. Check the sample Apps to see the permissions required. Note that for target 27 or greater on Android, your users will need to be prompted to grant Location Permission (this is a feature of BLE implementation on Android)
  • Is Headset in range - ensure that the headset is close enough to the handset to connect to the Parrott Button
  • is the Parrott Button connected to another headset. The Parrott Button can only be used with one headset at a time, and if connected on another handset, your application will not be able to connect.
  • Uninstall any other app that may be trying to connect (e.g. consumer BlueParrott App, other demo apps). Or disable connection in the settings of the other application

Button Event not firing

  • If you have successfully connected, but your BPHeadsetListener is not receiving events, check that the headset is in SDK mode - has your application updated the mode by calling enableSDK(). You can check for successful updates via the onModeUpdate() event.
  • Have you added a listener? You must create your listener object and add it by calling the addListener method.

Further Steps

  • When developing and engaging in a lot of connects, disconnects, the Android stack may become unstable and orphan connections may remain. It may be necessary to restart the BlueParrott headset and/or your handset.

iOS Trouble Shooting

Failure to Connect to Parrott Button

  • If the connect is failing, make sure the BlueParrott app is not also installed on the same phone.
  • When the headset connects, it will request to bond with the phone. This request should be allowed or the headset will disconnect BLE
  • Ensure that only 1 headset is powered on and within range of the app during development/testing.
  • Ensure that only 1 instance of your app is running on one device at a time while testing to avoid multiple apps discovering and attempting to connect to a single headset.

Button Event not firing

  • If you have successfully connected, but your BPHeadsetListener is not receiving events, check that the headset is in SDK mode - has your application updated the mode by calling enableSDK on the headset object. You can check for successful updates via the onModeUpdate callback.
  • Have you added a listener? You must create your listener object and add it by calling the addListener method on the headset.

General

Before reporting an error or problem with the SDK

  • Remove all applications using the SDK from your test device
  • Ensure that you are using a supported Operating system (see the relevant 'Including the SDK' section above)
  • Check the Trouble shooting steps above
  • Install one of the demonstration apps and check that they are failing to connect/function correctly. If they are functioning, compare your code to the sample code.
  • When reporting an error, provide a screenshot of the connection attempt in the sample app. You should also take a screenshot of the Bluetooth screen in the Settings app so that the current connectivity state of the headset is shown.

Reference Documentation

Download the Android BlueParrott SDK Documentation

Download the iOS BlueParrott SDK Documentation

Downloads

Download the Android BlueParrott SDK

Download the iOS BlueParrott SDK

Sample Applications are included in the SDK packages for each platform.