Android Bluetooth App Development
Android Package
android.bluetooth.le
Manifest
1 | <manifest> |
Phone Bluetooth State
- BluetoothAdapter
Pop up warning message if bluetooth setting is turned off.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25fun checkBLESetting(): Boolean{
//Check if phone support bluetooth and bluetooth is on
val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
if (!bluetoothAdapter.isEnabled){
mAlertDlg = AlertDialog.Builder(this)
.setMessage("Please turn on Bluetooth setting!")
.setTitle("")
.setPositiveButton("OK") { _, _ ->
startActivity(Intent(Settings.ACTION_BLUETOOTH_SETTINGS))
mAlertDlg = null
}
.setNeutralButton("Cancel") { _, _ ->
mAlertDlg = null
}
.create()
mAlertDlg?.show()
mAlertDlg?.getButton(AlertDialog.BUTTON_NEUTRAL)?.setTextColor(ContextCompat.getColor(this, R.color.blue));
mAlertDlg?.getButton(AlertDialog.BUTTON_POSITIVE)?.setTextColor(ContextCompat.getColor(this, R.color.blue));
return false
}
return true
}
Check & request for Permission
Request for BLE permission
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18fun requestPermissions(requestCode: Int) {
if (Build.VERSION.SDK_INT > 30) {
requirePermission(
arrayOf(
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.BLUETOOTH_SCAN,
), requestCode = requestCode
)
} else {
requirePermission(
arrayOf(
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.ACCESS_FINE_LOCATION
), requestCode = requestCode
)
}
}Check for BLE permission
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41fun checkBLEPermission(): Boolean{
//Check permissions for ACCESS_FINE_LOCATION if API < 30
//Check permissions for BLUETOOTH_SCAN if API > 30
if (Build.VERSION.SDK_INT > 30){
when (PermissionChecker.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_SCAN
)) {
PackageManager.PERMISSION_GRANTED -> {
return true
}
else -> {
if (shouldShowRequestPermissionRationale(Manifest.permission.BLUETOOTH_SCAN)) {
// ask user to grant the permission and redirect to the app setting
return false
}
requestPermissions(1)
}
}
}else {
when (PermissionChecker.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
)) {
PackageManager.PERMISSION_GRANTED -> {
return true
}
else -> {
if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
// ask user to grant the permission and redirect to the app setting
return false
}
requestPermissions(1)
}
}
}
return false
}
Start & Stop Scan
BluetoothLeScanner
1
2
3
4
5
6private val mBluetoothLeScanner: BluetoothLeScanner
get() {
val bluetoothManager = applicationContext.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val bluetoothAdapter = bluetoothManager.adapter
return bluetoothAdapter.bluetoothLeScanner
}ScanCallback
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21private val mScanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult?) {
super.onScanResult(callbackType, result)
val device = result?.device
val deviceName = result?.device?.name
if (deviceName != null && deviceName != ""){
Log.d(
"ScanDeviceActivity",
"onScanResult(): ${result?.device?.address} - ${result?.device?.name} ${result.rssi}"
)
}
...
}
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
Log.d("ttt", "onScanFailed: $errorCode")
}
}Start scan
1
mBluetoothLeScanner.startScan(mScanCallback)
Stop scan
1
mBluetoothLeScanner.stopScan(mScanCallback)
Connect & Get servers & characteristics
BluetoothGattServerCallback
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68private val gattCallback = object : BluetoothGattCallback() {
override fun onConnectionStateChange(
gatt: BluetoothGatt,
status: Int,
newState: Int
) {
val intentAction: String
when (newState) {
BluetoothProfile.STATE_CONNECTED -> {
gatt.discoverServices()
}
BluetoothProfile.STATE_DISCONNECTED -> {
}
}
}
// New services discovered
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
when (status) {
BluetoothGatt.GATT_SUCCESS -> {
val gattServices = gatt.services
gattServices.forEach { gattService ->
val uuid = gattService.uuid.toString()
val gattCharacteristics = gattService.characteristics
gattCharacteristics.forEach { gattCharacteristic ->
uuid = gattCharacteristic.uuid.toString()
}
}
}
}
}
// Result of a characteristic read operation
override fun onCharacteristicRead(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic,
status: Int
) {
when (status) {
BluetoothGatt.GATT_SUCCESS -> {
}
}
}
override fun onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, byte[] value, int status){
}
override fun onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, byte[] value){
}
override fun onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status){
}
}Connect
1
val bluetoothGatt = device.connectGatt(this, false, gattCallback)
Reconnect
1
2
3bluetoothGatt?.let { gatt ->
gatt.connect()
}Disconnect
1
2
3bluetoothGatt?.let { gatt ->
gatt.disconnect()
}Close
1
2
3
4bluetoothGatt?.let { gatt ->
gatt.close()
bluetoothGatt = null
}
Read & Write operations
Read
1
2
3bluetoothGatt?.let{ gatt ->
gatt.readCharacteristic(rxChar)
}Write
1
2
3bluetoothGatt?.let{ gatt ->
gatt.writeCharacteristic(txChar, value, WRITE_TYPE_DEFAULT)
}Set notification
1
2
3bluetoothGatt?.let{ gatt ->
gatt.setCharacteristicNotification(rxChar, true)
}
References
https://developer.android.com/reference/android/bluetooth/le/package-summary
https://developer.android.com/reference/android/bluetooth/BluetoothGatt
https://developer.android.com/reference/android/bluetooth/BluetoothGattCallback
https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner
https://developer.android.com/reference/android/bluetooth/le/ScanCallback
https://developer.android.com/reference/android/bluetooth/BluetoothManager
https://developer.android.com/reference/android/bluetooth/BluetoothGattServerCallback
Comment