Data sometimes needs to be transferred to another device, but to one where there is no network infrastructure. We may therefore want to integrate Bluetooth into our app to transfer data or to interact with various devices that cannot be accessed via the Internet or a local network.
To interact with the various Bluetooth services, we need the BluetoothAdapter
instance:
[assembly: UsesPermission(Manifest.Permission.Bluetooth)]
[assembly: UsesPermission( Manifest.Permission.BluetoothAdmin)]
BluetoothAdapter
instance:var bluetooth = BluetoothAdapter.DefaultAdapter; if (bluetooth == null) { // device does not support Bluetooth } else { State state = bluetooth.State; }
const string RequestToEnableBluetooth = 1; // any ID if (!bluetooth.IsEnabled) { var intent = new Intent( BluetoothAdapter.ActionRequestEnable); StartActivityForResult(intent, RequestToEnableBluetooth); }
OnActivityResult()
method:protected override void OnActivityResult( int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); if (requestCode == RequestToEnableBluetooth) { bool success = resultCode == Result.Ok; } }
var pairedDevices = bluetooth.BondedDevices; foreach (var device in pairedDevices) { var name = device.Name; }
bool started = bluetooth.StartDiscovery();
if (bluetooth.IsDiscovering) { bool canceled = bluetooth.CancelDiscovery(); }
int interval = 300; // seconds var intent = new Intent( BluetoothAdapter.ActionRequestDiscoverable); intent.PutExtra( BluetoothAdapter.ExtraDiscoverableDuration, interval); StartActivity(intent);
If we want to listen for changes to the Bluetooth state or to be notified when a new device is found, we register a broadcast receiver with the activity or service:
private class BluetoothReceiver : BroadcastReceiver { public override void OnReceive( Context context, Intent intent) { string action = intent.Action; if (action == BluetoothAdapter.ActionStateChanged) { var newState = (State)intent.GetIntExtra( BluetoothAdapter.ExtraState, 0); } if (action == BluetoothAdapter.ActionScanModeChanged) { var newScanMode = (ScanMode)intent.GetIntExtra( BluetoothAdapter.ExtraScanMode, 0); } if (action == BluetoothDevice.ActionFound) { var newDevice = intent.GetParcelableExtra( BluetoothDevice.ExtraDevice) as BluetoothDevice; } } }
receiver = new BluetoothReceiver(); RegisterReceiver(receiver, new IntentFilter(BluetoothAdapter.ActionStateChanged)); RegisterReceiver(receiver, new IntentFilter(BluetoothAdapter.ActionScanModeChanged)); RegisterReceiver(receiver, new IntentFilter(BluetoothDevice.ActionFound));
if (receiver != null) { UnregisterReceiver (receiver); }
Bluetooth is a wireless technology for transmitting and receiving data over short distances. There are three classes of Bluetooth radios, each with a different range. Typically, Class 3 radios have a very short range of less than one meter, Class 2 radios have a range of 10 meters, and Class 3 radios about 100 meters.
More information on how Bluetooth works can be found on the official Bluetooth website: http://www.bluetooth.com/Pages/Basics.aspx.
We can use the Android Bluetooth API to scan for and connect to other Bluetooth devices, as well as to send data to other devices. But before we start using the Bluetooth adapter, we need to request permission to do so from Android.
If we want to interact with the Bluetooth adapter, we need to obtain the current adapter by using the DefaultAdapter
property on the BluetoothAdapter
type. We need to first verify that there is a Bluetooth adapter, and if there is one, that it is enabled.
We can request that the user enable the adapter by starting an activity with the ActionRequestEnable
action intent. This will display a popup requesting permission for the app to enable Bluetooth.
Once we have the adapter, we can view the paired devices as well as scan for other devices. We use the StartDiscovery()
method to scan for devices, and we make the device discoverable using the ActionRequestDiscoverable
action intent.
A device will only be discovered by other devices if that device has been made discoverable. Before scanning for devices, it may be worth querying the collection of paired devices to see if the device is already known.
When we want to discover other devices, we initiate the scan with the StartDiscovery()
method and then listen for an ActionFound
action intent using a broadcast receiver. The scan interval is usually short, around 12 seconds.
We can also make the device discoverable by starting an activity with the ActionRequestDiscoverable
action intent. A device can be made discoverable for a slightly longer period than a scan. A value between 0 and 3,600 seconds can be specified by the ExtraDiscoverableDuration
intent extra. By default, and for any value outside those bounds, the device will become discoverable for 120 seconds.
Similar to listening for network state changes, we can listen for events from the Bluetooth adapter. We are able to listen to several events, including when the Bluetooth state has changed, when the scan mode has changed, or when a new device has been discovered. In each type of broadcast, we can access the relevant information in the extras of the intent.
In addition to normal Bluetooth, the device may also support Bluetooth Low Energy (BLE). BLE is available on Android versions 4.3 and above, and has lower power consumption compared to classic Bluetooth. BLE is used for devices that have low power requirements such as proximity sensors or health and fitness monitors.
To check to see if a device has BLE, we can ask the PackageManager
instance:
bool hasBLE = PackageManager.HasSystemFeature( PackageManager.FeatureBluetoothLe);
Once we have determined that the device supports BLE, we can then use slightly different mechanisms to scan, connect, and communicate. Instead of StartDiscovery
, we would invoke StartLeScan
, and instead of the usual RFCOMM channel, we connect to a GATT server.