Implementation Using Android APIs
The following details how to implement the general Bluetooth process on the interactive, from when the seatback monitor boots up to device connection. During implementation, ensure each operation is fully completed before executing the next one.
For design guidelines and standards, refer to Bluetooth Heading Pairing on the IFE.
Interactive Bluetooth Implementation Flow
This flow assumes that only audio devices are allowed to connect to the interactive and only one device can be connected at a time.

Check if there are any paired devices.
If there are no paired devices:
Display an option on the interactive to connect.
Passenger selects the option to connect.
Passenger turns on their device and sets it to pairing mode.
Passenger sees and selects their device in the list of of discovered devices.
If there is a paired device:
Display an option on the interactive to reconnect.
Passenger selects option to reconnect.
Passenger turns on their device and sets it to pairing mode.
Passenger chooses to either reconnect to the paired device or connect to a different device.
If passenger chooses to reconnect to the paired device:
If passenger chooses to connect to a different device:
Passenger sees and selects their device in the list of of discovered devices.
If a device gets disconnected or is unpaired from the interactive, be sure to set the audio output device to another available audio device, if any. For more information, refer to Set Audio Output Device.
If the passenger is in the process of pairing and connecting their Bluetooth device to the seatback monitor while a Passenger Announcement (PA) or Video PA (VPA) is being played, be sure to continue handling all Bluetooth events. This includes setting the audio output device and volume accordingly when the device successfully connects to ensure audio is routed properly to the Bluetooth device after the PA or VPA finishes.
Functionality
The following are functionality implemented in the Bluetooth flow.
Code samples are provided in Kotlin.
Check If Bluetooth Is Enabled
Check if Bluetooth is enabled by doing the following:
Make sure Bluetooth is allowed.
Use the PAC IO
registerEventAPI to register for theBLUETOOTH_CONTROLevent. IfBLUETOOTH_CONTROLis set to1, Bluetooth is allowed. Otherwise if it's set to0, Bluetooth is disallowed.For more information on allowing or disallowing Bluetooth, refer to Allow and Disallow Bluetooth.
For information on the PAC IO
registerEvent, refer to the PAC IO JSON API Reference For Interactives.Make sure the following required permissions are in the
AndroidManifest.xmlfile of the interactive:For NEXT seatback monitors, use
PrivilegeBrokerto set the following on bootup before any Bluetooth operations:For more information on using
PrivilegeBrokerand code samples, refer to the PAC IO Android Developer Guide.
If Bluetooth is not enabled, disable the Bluetooth option or exclude Bluetooth from the interactive entirely.
Initialize Bluetooth
Initialize Bluetooth by getting the BluetoothAdapter
object and the BluetoothProfile
proxy object.
Example:
private val mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
private fun getA2dpProfile(bluetoothDevice: BluetoothDevice) {
if (mIsProfileReady) return
var deviceA2dp = false
var uuids = bluetoothDevice.getUuids()
if (uuids == null) {
Log.i(TAG, "UUID list is empty ...")
} else {
for (uuid in uuids) {
Log.i(TAG, "Found UUID: " + uuid.toString())
if (uuid == AUDIO_SINK_UUID) {
Log.i(TAG, "Found A2DP sink device")
deviceA2dp = true
break
}
}
}
if (deviceA2dp) {
mBluetoothAdapter?.getProfileProxy(application, object : BluetoothProfile.ServiceListener {
override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
mBluetoothProfile = proxy as BluetoothA2dp
mIsProfileReady = true
val connectedDevices =
mBluetoothProfile!!.connectedDevices
if (connectedDevices != null) {
for (device in connectedDevices) {
handleAclConnectionChanged(device, true)
}
}
Log.d(
TAG, "onServiceConnected connectedDevices.size = " +
connectedDevices.size
)
}
override fun onServiceDisconnected(profile: Int) {
Log.d(TAG, "Bluetooth service disconnected");
mBluetoothProfile = null
mIsProfileReady = false;
}
},
BluetoothProfile.A2DP
)
}
}Check For Paired Devices
To determine if there are any paired devices on the
interactive, use getBondedDevices.
Example:
Turn On Bluetooth
Check if Bluetooth is turned on by calling isEnabled
or getState.
If Bluetooth is off, call enable
to turn it on.
Never assume Bluetooth is on. Bluetooth is automatically turned off when there is no activity.
Start Device Scanning
Start the device scanning process using startDiscovery
to discover and display nearby Bluetooth devices.
Bluetooth scanning uses resources in both the Bluetooth stack and Bluetooth radio. If scanning is on while audio is streaming through Bluetooth, there will be connection and audio quality issues such as dropouts.
To avoid this, scanning should be on only during the Bluetooth process while the passenger is actively searching for their device to pair with the monitor. Otherwise, ensure scanning is off.
Monitor when scanning process has started or finished
During the scanning process process, register and listen
for the ACTION_DISCOVERY_STARTED
and ACTION_DISCOVERY_FINISHED
broadcast events to monitor when the discovery process has
started or finished.
The Android scanning process lasts 12 seconds by default.
After 12 seconds, the ACTION_DISCOVERY_FINISHED
event will be broadcasted and scanning stops. To extend the
scanning period, call startDiscovery() again.
Continue this extension process until the passenger has
selected a device to pair or the required scanning duration
is reached.
For example, if program requirements specify the scanning duration to be 60 seconds instead of the default 12, do the following:
Start an internal 60 second timer.
Call
startDiscovery().When the
ACTION_DISCOVERY_FINISHEDevent is received but the internal timer is still running, callstartDiscovery()again.Once the internal timer has completed, call
cancelDiscovery().
Listen for when devices are found
Register and continually listen for ACTION_FOUND
events, which are broadcast whenever a device is found, and
display devices as they are discovered.
Display only Bluetooth audio devices
Additionally, filter out devices that are not audio devices. Currently, only audio devices can be paired to the seatback monitor. For more information on filtering logic, refer to Filter for Bluetooth Audio Devices Only.
Sort list of discovered devices by signal strength
The ACTION_FOUND event may broadcast
multiple times for each device with potentially updated
extra fields. One field is the EXTRA_RSSI
field, whose value indicates the signal strength of the
discovered device. To help the passenger more easily find
their device, use this field to continually sort the list of
discovered devices and placing devices with a stronger
signal at the top. Devices with a signal strength value
closer to zero have the strongest signal and are closest to
the seatback monitor.
Example:
val rssi : Short? = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE)
data class PacBluetoothDevice(
var bluetoothDevice : BluetoothDevice,
var deviceName: String = "",
var deviceMacAddress : String = "",
var lastRssi : Short,
var deviceType : String = "",
var deviceMajorType : String = "",
var deviceAudioType : String = "",
var devicedPaired : Boolean,
var deviceConnected : Boolean,
var deviceA2DPSinkUUIDFound : Boolean
)
private fun sortDeviceList(deviceList : List<PacBluetoothDevice>) {
Collections.sort(deviceList, Comparator { device1 : PacBluetoothDevice, device2 : PacBluetoothDevice
-> if (device1.lastRssi < device2.lastRssi)
1
else if (device1.lastRssi > device2.lastRssi)
-1
else
0
} )
}Discontinue Device Scanning
Discontinue scanning with cancelDiscovery,
then wait and listen for the
ACTION_DISCOVERY_FINISHED broadcast to ensure
scanning has stopped before continuing to pairing.
Pair Device
Start pairing the passenger's device by calling createBond.
To determine the pairing status, listen for the following bonding states:
BOND_BONDING— Indicates that pairing is in progress with the passenger's device.BOND_BONDED— Indicates that the passenger's device was successfully paired.BOND_NONE— Indicates that the passenger's device may have failed to pair.
If the bonding state immediately goes from
BOND_BONDING to BOND_NONE within
one second, retry pairing again with createBond
until a BOND_BONDED is received. However, if
this situation occurs three times without receiving a
BOND_BONDED state, stop the pairing process,
notify the passenger that their device was unable to be
paired, and advise that they ensure their device is on, in
pairing mode, and within range of the seatback monitor.
Example:
fun pairDevice(bluetoothDevice: BluetoothDevice) {
mPairingAttempt = 0
mConnectionAttempt = 0
mLastPairingDevice = bluetoothDevice
performPairDevice(bluetoothDevice)
}
private fun performPairDevice(bluetoothDevice: BluetoothDevice) {
mPairingAttempt++
val result = bluetoothDevice.createBond()
Log.d(TAG, "Pair to device " + bluetoothDevice.name + " ret = " + result)
}
val mReceiver = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val action = intent?.action
Log.d(TAG, "action = ${action}")
when (action) {
BluetoothAdapter.ACTION_STATE_CHANGED -> {
val state =
intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
if (state == BluetoothAdapter.STATE_ON) {
_displayMessage.tryEmit(BtUserMessage(MessageType.MessageToast, "Bluetooth Enabled"))
updateBluetoothState(true)
} else if (state == BluetoothAdapter.STATE_OFF) {
_displayMessage.tryEmit(BtUserMessage(MessageType.MessageToast,"Bluetooth Disabled"))
updateBluetoothState(false)
}
}
BluetoothAdapter.ACTION_DISCOVERY_STARTED -> {
Log.i(TAG, "ACTION_DISCOVERY_STARTED");
mUncategorizedDeviceList.clear()
btDeviceList.clear()
// updatePairedDeviceList()
updateBluetoothScanningInProgress(true)
mHandler.removeCallbacks(mDiscoveryCancelRunnable)
mHandler.postDelayed(
mDiscoveryCancelRunnable,
(MAX_DISCOVERY_TIME_SECONDS * 1000).toLong()
)
}
BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> {
Log.i(TAG, "ACTION_DISCOVERY_FINISHED");
mHandler.removeCallbacks(mDiscoveryCancelRunnable)
updateBluetoothScanningInProgress(false)
checkUncategorizedDevices()
}
BluetoothDevice.ACTION_FOUND -> {
handleFoundDevice(intent)
}
BluetoothDevice.ACTION_BOND_STATE_CHANGED -> {
handleDevicePairStateChanged(intent)
}
BluetoothDevice.ACTION_ACL_CONNECTED -> {
val device : BluetoothDevice? = intent?.getParcelableExtra (BluetoothDevice.EXTRA_DEVICE)
handleAclConnectionChanged(device!!, true)
}
BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
val device : BluetoothDevice? = intent?.getParcelableExtra (BluetoothDevice.EXTRA_DEVICE)
handleAclConnectionChanged(device!!, false)
}
BluetoothDevice.ACTION_UUID -> {
handleUuid(intent)
}
BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED -> {
handleA2dpConnectionStateChanged(intent)
}
}
}
}
private fun handleDevicePairStateChanged(intent : Intent) {
val device : BluetoothDevice? = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device == null) return
val state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
val prevState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.ERROR);
Log.d(TAG, "handleDevicePairStateChanged device = $device state = $state prevState = $prevState")
if (state == BluetoothDevice.BOND_BONDED && prevState == BluetoothDevice.BOND_BONDING) {
_displayMessage.tryEmit(BtUserMessage(MessageType.MessageToast, "Paired"))
updatePairedDeviceList();
removeDeviceFromScanList(device)
Log.i(TAG, "attempt to connect after pairing ...");
connectDevice(device);
} else if (state == BluetoothDevice.BOND_NONE && prevState == BluetoothDevice.BOND_BONDED){
updatePairedDeviceList()
_displayMessage.tryEmit(BtUserMessage(MessageType.MessageToast,"Unpaired"))
}
else if (state == BluetoothDevice.BOND_NONE && prevState == BluetoothDevice.BOND_BONDING) {
// add retry logic
if (mPairingAttempt <= MAX_BOND_RETRIES && mLastPairingDevice != null) {
Log.d(TAG, "Attempt to bond again")
performPairDevice(mLastPairingDevice!!)
}
else {
if (mLastPairingDevice != null) {
_displayMessage.tryEmit(BtUserMessage(MessageType.MessageToast,
"Unable to pair ${mLastPairingDevice?.name}. Make sure device is in pairing mode"))
}
mLastPairingDevice = null
}
}
}Example of retrying pairing logic:
private fun handleDevicePairStateChanged(intent : Intent) {
val device : BluetoothDevice? = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device == null) return
val state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
val prevState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.ERROR);
Log.d(TAG, "handleDevicePairStateChanged device = $device state = $state prevState = $prevState")
if (state == BluetoothDevice.BOND_BONDED && prevState == BluetoothDevice.BOND_BONDING) {
_displayMessage.tryEmit(BtUserMessage(MessageType.MessageToast, "Paired"))
updatePairedDeviceList();
removeDeviceFromScanList(device)
Log.i(TAG, "attempt to connect after pairing ...");
connectDevice(device);
} else if (state == BluetoothDevice.BOND_NONE && prevState == BluetoothDevice.BOND_BONDED){
updatePairedDeviceList()
}
else if (state == BluetoothDevice.BOND_NONE && prevState == BluetoothDevice.BOND_BONDING) {
// add retry logic
if (mPairingAttempt <= MAX_BOND_RETRIES && mLastPairingDevice != null) {
Log.d(TAG, "Attempt to bond again")
performPairDevice(mLastPairingDevice!!)
}
else {
mLastPairingDevice = null
}
}
}
private fun performPairDevice(bluetoothDevice: BluetoothDevice) {
mPairingAttempt++
val result = bluetoothDevice.createBond()
Log.d(TAG, "Pair to device " + bluetoothDevice.name + " ret = " + result)
}Unpair Device
When the passenger wants to unpair their device completely from the seatback monitor, allow them the option to do so from the interactive.
Example:
fun unpairDevice(bluetoothDevice: BluetoothDevice) {
try {
if (mLastPairingDevice != null && mLastPairingDevice?.address.equals(bluetoothDevice.address)) {
mKeepConnectionFlag = false
}
Log.d(TAG, "unpairDevice ${bluetoothDevice.name}")
val method =
bluetoothDevice.javaClass.getMethod("removeBond")
method.invoke(bluetoothDevice)
Log.d(TAG, "unpairDevice ${bluetoothDevice.name} succeeds")
} catch (e: Exception) {
e.printStackTrace()
}
}Connect Paired Device
Once pairing is confirmed, connect the device through the
Advanced Audio Distribution Profile (A2DP) profile using the
BluetoothA2dp
class.
The BluetoothA2dp class does not directly provide APIs
for connecting or disconnecting devices. The interactive
must get references to connect and
disconnect using getMethod.
The device may automatically connect if it supports the A2DP profile or the Audio/Video Remote Control Profile (AVRCP). However, this is not guaranteed, so the interactive should always try to connect.
Example:
fun connectDevice(bluetoothDevice: BluetoothDevice) {
Log.d(TAG, "connectDevice ${bluetoothDevice.name}")
mKeepConnectionFlag = true
mConnectionAttempt = 0
mLastPairingDevice = bluetoothDevice
connectA2DP(bluetoothDevice)
}
private fun connectA2DP(device : BluetoothDevice) {
Log.i(TAG, "connectA2DP")
if (!mIsProfileReady) {
Log.i(TAG, "profile is not ready, starting thread to connect ...")
GlobalScope.launch {
getA2dpProfile(device)
for (attempt in 0..5 step 1) {
try {
Thread.sleep(500)
} catch (e : InterruptedException) {
e.printStackTrace()
}
if (!mIsProfileReady) {
getA2dpProfile(device)
} else {
break
}
}
Log.i(TAG, "Attempting to connect ...");
connectToA2DPProfile(device)
}
} else {
Log.i(TAG, "profile ready, attempt to connect ...");
connectToA2DPProfile(device)
}
}
private fun connectToA2DPProfile(device : BluetoothDevice) : Boolean {
var result = false
Log.i(TAG, "Connect A2DP to $device")
try {
if (mBluetoothProfile != null) {
Log.i(TAG,"Attempting to connect ...")
mConnectionAttempt++
mHandler.removeCallbacks(mConnectionRetryRunnable)
mHandler.postDelayed(mConnectionRetryRunnable, MAX_CONNECTION_TIMEOUT)
mBluetoothProfile!!.javaClass.getMethod("connect", BluetoothDevice::class.java).invoke(mBluetoothProfile, device)
result = true
} else {
Log.e(TAG, "mBluetoothProfile is null")
}
} catch (e : IllegalAccessException) {
e.printStackTrace()
} catch (e : InvocationTargetException) {
e.printStackTrace()
} catch (e : NoSuchMethodException) {
e.printStackTrace()
}
return result
}If the device fails to connect, attempt to connect two more times. After three failed attempts, stop the connection process and notify the passenger that their device was unable to connect.
Example:
private val MAX_CONNECTION_TIMEOUT: Long = 8 * 1000
private val mConnectionRetryRunnable = object : Runnable {
override fun run() {
Log.d(TAG, "Connection attempt = $mConnectionAttempt")
if (mConnectionAttempt <= MAX_CONNECT_RETRIES && mLastPairingDevice != null) {
connectToA2DPProfile(mLastPairingDevice!!)
}
}
}Disconnect Paired Device
The following is an example implementation of disconnecting a paired device:
private fun disconnectA2DP(device : BluetoothDevice) : Boolean {
var result = false
Log.i(TAG, "Disconnect A2DP from ${device}")
try {
if (mBluetoothProfile != null) {
mBluetoothProfile!!.javaClass.getMethod("disconnect", BluetoothDevice::class.java).invoke(mBluetoothProfile, device)
mBluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, mBluetoothProfile)
}
mIsProfileReady = false
result = true
} catch (e : IllegalAccessException) {
e.printStackTrace()
} catch (e : InvocationTargetException) {
e.printStackTrace()
} catch (e : NoSuchMethodException) {
e.printStackTrace()
}
return result
}Allow and Disallow Bluetooth
Bluetooth can be allowed by setting
TD 315 TD_ID_BLUETOOTH_CONTROL to
1 or disallowed by setting it to
0. The crew can change this setting from the
crew terminal to allow or disallow Bluetooth during a
flight.
During development, TD 315 can be configured on the headend to allow Bluetooth without using the crew terminal. Example:
Set Audio Output Device
Whenever the Bluetooth connection status changes, such as when a Bluetooth audio device is connected, disconnected, or unpaired, the interactive should always set the audio output device accordingly by doing the following:
Get a list of available audio output devices by calling the PAC IO
getAudioDevicesAPI.Call the PAC IO
setAudioDevicesAPI to redirect the audio output to the appropriate device from the list.If a Bluetooth audio device was just connected, set the audio output device to the newly connected device. If a Bluetooth audio device was disconnected or unpaired, set the audio output device to another available audio device. The default output device is the audio jack when no other device is connected.
Additionally, be sure to update the volume level. Refer to Set Volume Level.
For information on the above APIs, refer to the PAC IO JSON API Reference for Interactives.
Set Volume Level
Update the volume by retrieving the current volume level
using getStreamVolume,
then setting the volume level in the interactive using setStreamVolume
for Android 8.1 and higher and adjustStreamVolume
for Android 5.1.
Filter for Bluetooth Audio Devices Only
During the Bluetooth device discovery phase, scanning will search for nearby Bluetooth devices and return all types, including mobile phones and computers. However, only audio devices are currently allowed to be paired. Because of this, be sure to include only audio devices in the discovered device list to the passenger and exclude all other devices.
The following defines conditions where a device should be filtered out.
Android 8.1 or higher
Filter out a device if:
Device type is neither
BluetoothDevice.DEVICE_TYPE_DUALnorBluetoothDevice.DEVICE_TYPE_CLASSIC.Device friendly name is empty.
Device friendly name starts with "LE-".
Device service type is not
BluetoothClass.Service.AUDIO.Device major class is not
BluetoothClass.Device.Major.AUDIO_VIDEO.Device class is not one of the following:
BluetoothClass.Device.AUDIO_VIDEO_HEADPHONESBluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKERBluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSETBluetoothClass.Device.AUDIO_VIDEO_HANDSFREEBluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO
Android 5.1
Filter out a device if:
Device type is neither
BluetoothDevice.DEVICE_TYPE_DUALnorBluetoothDevice.DEVICE_TYPE_CLASSIC.Device friendly name is empty.
Device friendly name starts with "LE-".
Device major class is not
BluetoothClass.Device.Major.UNCATEGORIZED.Device service type is not
BluetoothClass.Service.AUDIO:Device service type is
BluetoothClass.Service.AUDIO, but:Device major class is NOT
BluetoothClass.Device.Major.AUDIO_VIDEO, orDevice class is not one of the following:
BluetoothClass.Device.AUDIO_VIDEO_HEADPHONESBluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKERBluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSETBluetoothClass.Device.AUDIO_VIDEO_HANDSFREEBluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO
Example
fun isDeviceValidAudioDevice(device: BluetoothDevice?): Boolean {
if (device == null) {
return false
}
val deviceName = device.name
val deviceClass = device.bluetoothClass
// filter out non-classic and non-dual mode devices
var validType = (device.type == BluetoothDevice.DEVICE_TYPE_CLASSIC) || (device.type == BluetoothDevice.DEVICE_TYPE_DUAL)
if (validType == false) {
if (Build.VERSION.SDK_INT < 27 && device.type != BluetoothDevice.DEVICE_TYPE_UNKNOWN) {
Log.d(TAG, "isDeviceValidAudioDevice invalid type = ${device.type}")
return false
}
}
// filter out devices without a "friendly name"
if ((deviceName == null) || (deviceName.isEmpty() == true)) {
return false
}
// filter out devices with a "friendly name" beginning with "LE-"
if (deviceName.startsWith("LE-") == true) {
Log.i(
TAG,
"filtering out devices with a friending name($deviceName) beginning with 'LE-' ..."
)
return false
}
if (deviceClass == null) {
return false
}
var validMajorDeviceClass = (deviceClass.majorDeviceClass == BluetoothClass.Device.Major.AUDIO_VIDEO)
Log.d(TAG, "isDeviceValidAudioDevice validMajorDeviceClass = $validMajorDeviceClass")
if (!validMajorDeviceClass) {
if (Build.VERSION.SDK_INT < 27 && deviceClass.majorDeviceClass == BluetoothClass.Device.Major.UNCATEGORIZED) {
Log.d(TAG, "isDeviceValidAudioDevice found uncategorized device")
return true
}
}
if (validMajorDeviceClass && deviceClass.hasService(BluetoothClass.Service.AUDIO)) {
Log.i(
TAG,
"Device with audio service found: " + device.name + "( " + device.address + " ) with device class: " + deviceClass.deviceClass
)
if (((deviceClass.deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES)
|| (deviceClass.deviceClass == BluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKER)
|| (deviceClass.deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)
|| (deviceClass.deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE)
|| (deviceClass.deviceClass == BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO))
) {
Log.i(
TAG,
"Audio device found: " + device.name + "( " + device.address + " ) with device class: " + deviceClass.deviceClass
)
return true
}
}
return false
}Example Bluetooth Interactive Screens
Option to Connect Device (No Paired Devices Found)

Option to Reconnect Device (Paired Device Exists)

Device is Currently Connected

Displaying Discovered Devices During Device Scanning

Device Scanning Timed Out

Device Selected For Connection

Connecting to Device In Progress

Connected to Device Successfully

When the passenger selects Disconnect in the interactive, the interactive should unpair the device instead of just disconnecting it.
Device Connection Lost Alert

Reconnect to Previously Paired Device

Reconnecting to Previously Paired Device In

Reconnection to Previously Paired Device Failed

Interactive Android Bluetooth APIs
The following are Android APIs that are used to implement
Bluetooth on the interactive, using the BluetoothAdapter,
BluetoothDevice,
BluetoothA2dp,
and AudioManager
classes. For other Android Bluetooth APIs, refer to the
Android Bluetooth
Guide and Bluetooth
Reference.
Methods
| Method | Class | Usage |
|---|---|---|
cancelDiscovery | BluetoothAdapter | Used to discontinue device scanning during the device discovery phase. |
createBond | BluetoothDevice | Starts the pairing process with a Bluetooth device. To
determine pairing status, listen for the BOND_BONDING,
BOND_BONDED,
and BOND_NONE
states. |
enable | BluetoothAdapter | Turns on Bluetooth. |
getBondedDevices | BluetoothAdapter | Used to retrieve a list of Bluetooth devices that are paired with the seatback monitor. |
getState | BluetoothAdapter | Checks if Bluetooth is turned on. |
getStreamVolume | AudioManager | Retrieves current volume level. |
setStreamVolume | AudioManager | Sets volume level. |
startDiscovery | BluetoothAdapter | Starts device scanning process to discover nearby Bluetooth devices. |
Constants
| Constant | Class | Usage |
|---|---|---|
ACTION_CONNECTION_STATE_CHANGED | BluetoothA2dp | Used to detect a change in Bluetooth connection to determine if Bluetooth is on or off. |
ACTION_DISCOVERY_FINISHED | BluetoothAdapter | Indicates when device scanning has finished. Broadcasts during the device discovery phase. |
ACTION_DISCOVERY_STARTED | BluetoothAdapter | Indicates when device scanning has started. Broadcasts during device discovery phase. |
ACTION_FOUND | BluetoothDevice | Used to detect a change in Bluetooth connection to
determine if Bluetooth is on or off. Containts the EXTRA_RSSI
field, which indicates the signal strength of the
device. |
ACTION_STATE_CHANGED | BluetoothAdapter | Acquires the state of the Bluetooth connection. Used on
NEXT seatback monitors when disabling Bluetooth through TD
315 does not send the ACTION_CONNECTION_STATE_CHANGED
intent to signal a Bluetooth device disconnection. |
BOND_BONDED | BluetoothDevice | Indicates that a Bluetooth device was successfully paired. |
BOND_BONDING | BluetoothDevice | Indicates that pairing is in progress with a Bluetooth device. |
BOND_NONE | BluetoothDevice | Indicates that a Bluetooth device may have failed to pair. |
EXTRA_RSSI | BluetoothDevice | Indicates the signal strength of a discovered device. Used for sorting the list of discovered devices to place devices with the strongest signal at the top to help passengers find their device more easily. Devices with a signal strength value closer to zero have the strongest signal and are closest to the seatback monitor. This
field is found in |