Bluetooth

This document describes how to use the Bluetooth API to communicate with Bluetooth and Bluetooth Low Energy devices.

For background information about Bluetooth, see the official Bluetooth specifications.

Manifest requirements

For Chrome Apps that use Bluetooth, add the bluetooth entry to the manifest and specify, if appropriate, the UUIDs of profiles, protocols or services you wish to implement. For example:

"bluetooth": {
  "uuids": [ "1105", "1106" ]
}

To only access adapter state, discover nearby devices, and obtain basic information about devices, omit the uuids list.

Obtaining adapter state

To obtain the state of the Bluetooth adapter, use the chrome.bluetooth.getAdapterState method:

chrome.bluetooth.getAdapterState(function(adapter) {
  console.log("Adapter " + adapter.address + ": " + adapter.name);
});

The chrome.bluetooth.onAdapterStateChanged event is sent whenever this state changes. This can be used, for example, to determine when the adapter radio is powered on or off.

var powered = false;
chrome.bluetooth.getAdapterState(function(adapter) {
  powered = adapter.powered;
});

chrome.bluetooth.onAdapterStateChanged.addListener(
  function(adapter) {
    if (adapter.powered != powered) {
      powered = adapter.powered;
      if (powered) {
        console.log("Adapter radio is on");
      } else {
        console.log("Adapter radio is off");
      }
    }
  });

Listing known devices

To get a list of the devices known to the Bluetooth adapter, use the chrome.bluetooth.getDevices method:

chrome.bluetooth.getDevices(function(devices) {
  for (var i = 0; i < devices.length; i++) {
    console.log(devices[i].address);
  }
});

All devices are returned, including paired devices and devices recently discovered. It will not begin discovery of new devices (see Discovering nearby devices).

Receiving device notifications

Instead of repeatedly calling chrome.bluetooth.getDevices, you can use the chrome.bluetooth.onDeviceAdded, chrome.bluetooth.onDeviceChanged and chrome.bluetooth.onDeviceRemoved events to receive notifications.

The chrome.bluetooth.onDeviceAdded event is sent whenever a device is discovered by the adapter or makes a connection to the adapter:

chrome.bluetooth.onDeviceAdded.addListener(function(device) {
  console.log(device.address);
});

Adding a listener for this event does not begin discovery of devices (see Discovering nearby devices).

Changes to devices, including previously discovered devices becoming paired, are notified by the chrome.bluetooth.onDeviceChanged event:

chrome.bluetooth.onDeviceChanged.addListener(function(device) {
  console.log(device.address);
});

Finally the chrome.bluetooth.onDeviceRemoved event is sent whenever a paired device is removed from the system, or a discovered device has not been seen recently:

chrome.bluetooth.onDeviceRemoved.addListener(function(device) {
  console.log(device.address);
});

Discovering nearby devices

To begin discovery of nearby devices, use the chrome.bluetooth.startDiscovery method. Discovery can be resource intensive so you should call chrome.bluetooth.stopDiscovery when done.

You should call chrome.bletooth.startDiscovery whenever your app needs to discover nearby devices. Do not check the discovering property of AdapterState. The call to start discovery will succeed even if another app is discovering nearby devices, and will ensure the adapter continues to perform discovery after that other app has stopped.

Information about each newly discovered device is received using the chrome.bluetooth.onDeviceAdded event. For devices that have already been discovered recently, or have been previously paired with or connected to, the event will not be sent. Instead you should call chrome.bluetooth.getDevices to obtain the current information, and use the chrome.bluetooth.onDeviceChanged event to be notified of changes to that information as a result of discovery.

Example:

var device_names = {};
var updateDeviceName = function(device) {
  device_names[device.address] = device.name;
};
var removeDeviceName = function(device) {
  delete device_names[device.address];
}

// Add listeners to receive newly found devices and updates
// to the previously known devices.
chrome.bluetooth.onDeviceAdded.addListener(updateDeviceName);
chrome.bluetooth.onDeviceChanged.addListener(updateDeviceName);
chrome.bluetooth.onDeviceRemoved.addListener(removeDeviceName);

// With the listeners in place, get the list of devices found in
// previous discovery sessions, or any currently active ones,
// along with paired devices.
chrome.bluetooth.getDevices(function(devices) {
  for (var i = 0; i < devices.length; i++) {
    updateDeviceName(devices[i]);
  }
});

// Now begin the discovery process.
chrome.bluetooth.startDiscovery(function() {
  // Stop discovery after 30 seconds.
  setTimeout(function() {
    chrome.bluetooth.stopDiscovery(function() {});
  }, 30000);
});

If the user turns off the Bluetooth radio, all discovery sessions will be ended and not resumed automatically when the radio is switched on. If this matters to your app, you should watch the chrome.bluetooth.onAdapterStateChanged event. If the discovering property changes to false, then your app will need to call chrome.bluetooth.startDiscovery again to resume. Be cautious of the resource intensive nature of discovery.

Identifying devices

A number of different options are provided for identifying devices returned by chrome.bluetooth.getDevices and the related events.

If the device supports the Bluetooth Device ID specification, several properties are added to the Device object containing the fields defined by that specification. Example:

chrome.bluetooth.getDevices(function(devices) {
  for (var i = 0; i < devices.length; i++) {
    if (devices[0].vendorIdSource != undefined) {
      console.log(devices[0].address + ' = ' +
                  devices[0].vendorIdSource + ':' +
                  devices[0].vendorId.toString(16) + ':' +
                  devices[0].productId.toString(16) + ':' +
                  devices[0].deviceId.toString(16));
    }
  }
});

The Device ID specification is usually sufficient to identify a particular model, and even revision, of a device from a vendor. Where it is not present, you must instead rely on information about the class or type of the device, optionally combined with the manufacturer prefix in the address.

Most Bluetooth devices provide Class of Device information as a bit-field interpreted according to the Baseband Assigned Numbers document. This bit-field is available in the deviceClass property.

chrome.bluetooth.getDevices(function(devices) {
  for (var i = 0; i < devices.length; i++) {
    if (devices[0].vendorIdSource != undefined) {
      console.log(devices[0].address + ' = ' +
                  devices[0].deviceClass.toString(16));
    }
  }
});

Parsing the field can be complex so for the most common device types Chrome handles this for you and sets the type field. Where this is not available, or insufficient for your needs, you'll need to parse the deviceClass yourself.

chrome.bluetooth.getDevices(function(devices) {
  for (var i = 0; i < devices.length; i++) {
    if (devices[0].vendorIdSource != undefined) {
      console.log(devices[0].address + ' = ' + devices[0].type);
    }
  }
});