Skip to content

Commit

Permalink
Merge pull request #730 from Cyb0org/master
Browse files Browse the repository at this point in the history
Android 12 support #718
  • Loading branch information
randdusing authored Aug 18, 2022
2 parents f0cf7fc + 6a8e90c commit 16438be
Show file tree
Hide file tree
Showing 6 changed files with 338 additions and 4 deletions.
2 changes: 2 additions & 0 deletions plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</config-file>
Expand Down
127 changes: 124 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ This plugin allows you to interact with Bluetooth LE devices on Android, iOS, an
- [isDiscovered](#isdiscovered)
- [hasPermission](#haspermission)
- [requestPermission](#requestpermission)
- [hasPermissionBtScan](#haspermissionBtScan)
- [requestPermissionBtScan](#requestpermissionBtScan)
- [hasPermissionBtConnect](#haspermissionBtConnect)
- [requestPermissionBtConnect](#requestpermissionBtConnect)
- [hasPermissionBtAdvertise](#haspermissionBtAdvertise)
- [requestPermissionBtAdvertise](#requestpermissionBtAdvertise)
- [isLocationEnabled](#islocationenabled)
- [requestLocation](#requestlocation)
- [setPin](#setPin)
Expand Down Expand Up @@ -240,6 +246,12 @@ Neither Android nor iOS support Bluetooth on emulators, so you'll need to test o
* [bluetoothle.isDiscovered](#isdiscovered)
* [bluetoothle.hasPermission](#haspermission) (Android 6+)
* [bluetoothle.requestPermission](#requestpermission) (Android 6+)
* [bluetoothle.hasPermissionBtScan](#haspermissionBtScan) (Android 31+)
* [bluetoothle.requestPermissionBtScan](#requestpermissionBtScan) (Android 31+)
* [bluetoothle.hasPermissionBtConnect](#haspermissionBtConnect) (Android 31+)
* [bluetoothle.requestPermissionBtConnect](#requestpermissionBtConnect) (Android 31+)
* [bluetoothle.hasPermissionBtAdvertise](#haspermissionBtAdvertise) (Android 31+)
* [bluetoothle.requestPermissionBtAdvertise](#requestpermissionBtAdvertise) (Android 31+)
* [bluetoothle.isLocationEnabled](#islocationenabled) (Android 6+)
* [bluetoothle.requestLocation](#requestlocation) (Android 6+)
* [bluetoothle.retrievePeripheralsByAddress](#retrievePeripheralsByAddress) (iOS)
Expand Down Expand Up @@ -417,7 +429,7 @@ The successCallback contains the following properties:


### startScan ###
Scan for Bluetooth LE devices. Since scanning is expensive, stop as soon as possible. The Cordova app should use a timer to limit the scan interval. Also, Android uses an AND operator for filtering, while iOS uses an OR operator. Android API >= 23 requires ACCESS_COARSE_LOCATION permissions to find unpaired devices. Permissions can be requested by using the hasPermission and requestPermission functions. Android API >= 23 also requires location services to be enabled. Use ```isLocationEnabled``` to determine whether location services are enabled. If not enabled, use ```requestLocation``` to prompt the location services settings page.
Scan for Bluetooth LE devices. Since scanning is expensive, stop as soon as possible. The Cordova app should use a timer to limit the scan interval. Also, Android uses an AND operator for filtering, while iOS uses an OR operator. Android API >= 23 requires ACCESS_COARSE_LOCATION permissions to find unpaired devices. Permissions can be requested by using the hasPermission and requestPermission functions. Android API >= 23 also requires location services to be enabled. Use ```isLocationEnabled``` to determine whether location services are enabled. If not enabled, use ```requestLocation``` to prompt the location services settings page. Android API >= 31 also requires BLUETOOTH_SCAN permissions to perform scanning. You can use ```hasPermissionBtScan``` to determine whether scanning permission is granted or use ```requestPermissionBtScan``` to prompt for it.

```javascript
bluetoothle.startScan(startScanSuccess, startScanError, params);
Expand Down Expand Up @@ -616,7 +628,7 @@ bluetoothle.unbond(unbondSuccess, unbondError, params);


### connect ###
Connect to a Bluetooth LE device. The app should use a timer to limit the connecting time in case connecting is never successful. Once a device is connected, it may disconnect without user intervention. The original connection callback will be called again and receive an object with status => disconnected. To reconnect to the device, use the reconnect method. If a timeout occurs, the connection attempt should be canceled using disconnect(). For simplicity, I recommend just using connect() and close(), don't use reconnect() or disconnect().
Connect to a Bluetooth LE device. The app should use a timer to limit the connecting time in case connecting is never successful. Once a device is connected, it may disconnect without user intervention. The original connection callback will be called again and receive an object with status => disconnected. To reconnect to the device, use the reconnect method. If a timeout occurs, the connection attempt should be canceled using disconnect(). For simplicity, I recommend just using connect() and close(), don't use reconnect() or disconnect(). Android API >= 31 requires BLUETOOTH_CONNECT permissions to connect to devices. You can use ```hasPermissionBtConnect``` to determine whether connect permission is granted or use ```requestPermissionBtConnect``` to prompt for it.

```javascript
bluetoothle.connect(connectSuccess, connectError, params);
Expand Down Expand Up @@ -1739,6 +1751,114 @@ bluetoothle.requestPermission(requestPermissionSuccess, requestPermissionError);



### hasPermissionBtScan ###
Determine whether Bluetooth scanning privileges are granted since scanning for unpaired devices requies it in Android API 31

```javascript
bluetoothle.hasPermissionBtScan(hasPermissionSuccess);
```

##### Success #####
* status => hasPermission = true/false

```javascript
{
"hasPermission": true
}
```



### requestPermissionBtScan ###
Request Bluetooth scanning privileges since scanning for unpaired devices requires it in Android API 31. Will return an error if called on iOS or Android versions prior to 6.0.

```javascript
bluetoothle.requestPermissionBtScan(requestPermissionSuccess, requestPermissionError);
```

##### Success #####
* status => requestPermission = true/false

```javascript
{
"requestPermission": true
}
```



### hasPermissionBtConnect ###
Determine whether Bluetooth connect privileges are granted since connecting to unpaired devices requies it in Android API 31

```javascript
bluetoothle.hasPermissionBtConnect(hasPermissionSuccess);
```

##### Success #####
* status => hasPermission = true/false

```javascript
{
"hasPermission": true
}
```



### requestPermissionBtConnect ###
Request Bluetooth connect privileges since connecting to unpaired devices requires it in Android API 31. Will return an error if called on iOS or Android versions prior to 6.0.

```javascript
bluetoothle.requestPermissionBtConnect(requestPermissionSuccess, requestPermissionError);
```

##### Success #####
* status => requestPermission = true/false

```javascript
{
"requestPermission": true
}
```



### hasPermissionBtAdvertise ###
Determine whether Bluetooth advertise privileges are granted since making the current device discoverable requies it in Android API 31

```javascript
bluetoothle.hasPermissionBtAdvertise(hasPermissionSuccess);
```

##### Success #####
* status => hasPermission = true/false

```javascript
{
"hasPermission": true
}
```



### requestPermissionBtAdvertise ###
Request Bluetooth advertise privileges since making the current device discoverable requires it in Android API 31. Will return an error if called on iOS or Android versions prior to 6.0.

```javascript
bluetoothle.requestPermissionBtAdvertise(requestPermissionSuccess, requestPermissionError);
```

##### Success #####
* status => requestPermission = true/false

```javascript
{
"requestPermission": true
}
```



### isLocationEnabled ###
Determine if location services are enabled or not. Location Services are required to find devices in Android API 23.

Expand Down Expand Up @@ -2041,7 +2161,8 @@ bluetoothle.removeAllServices(success, error);

### startAdvertising ###
Start advertising as a BLE device. Note: This needs to be improved so services can be used for both Android and iOS.
On iOS, the advertising devices likes to rename itself back to the name of the device, i.e. Rand' iPhone
On iOS, the advertising devices likes to rename itself back to the name of the device, i.e. Rand' iPhone.
Android API >= 31 also requires BLUETOOTH_ADVERTISE permissions to perform advertising. You can use ```hasPermissionBtAdvertise``` to determine whether advertise permission is granted or use ```requestPermissionBtAdvertise``` to prompt for it.

```javascript
bluetoothle.startAdvertising(success, error, params);
Expand Down
114 changes: 113 additions & 1 deletion src/android/BluetoothLePlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ public class BluetoothLePlugin extends CordovaPlugin {
private final int REQUEST_BT_ENABLE = 59627; /*Random integer*/
private final int REQUEST_ACCESS_FINE_LOCATION = 59628;
private final int REQUEST_LOCATION_SOURCE_SETTINGS = 59629;
private final int REQUEST_BLUETOOTH_SCAN = 59630;
private final int REQUEST_BLUETOOTH_ADVERTISE = 59631;
private final int REQUEST_BLUETOOTH_CONNECT = 59632;
private BluetoothAdapter bluetoothAdapter;
private boolean isReceiverRegistered = false;
private boolean isBondReceiverRegistered = false;
Expand Down Expand Up @@ -393,6 +396,18 @@ public boolean execute(String action, final JSONArray args, final CallbackContex
hasPermissionAction(callbackContext);
} else if ("requestPermission".equals(action)) {
requestPermissionAction(callbackContext);
} else if ("hasPermissionBtScan".equals(action)) {
hasPermissionBtScanAction(callbackContext);
} else if ("requestPermissionBtScan".equals(action)) {
requestPermissionBtScanAction(callbackContext);
} else if ("hasPermissionBtConnect".equals(action)) {
hasPermissionBtConnectAction(callbackContext);
} else if ("requestPermissionBtConnect".equals(action)) {
requestPermissionBtConnectAction(callbackContext);
} else if ("hasPermissionBtAdvertise".equals(action)) {
hasPermissionBtAdvertiseAction(callbackContext);
} else if ("requestPermissionBtAdvertise".equals(action)) {
requestPermissionBtAdvertiseAction(callbackContext);
} else if ("isLocationEnabled".equals(action)) {
isLocationEnabledAction(callbackContext);
} else if ("requestLocation".equals(action)) {
Expand Down Expand Up @@ -879,6 +894,10 @@ private void notifyAction(JSONArray args, CallbackContext callbackContext) {
}
}

/**
* ACCESS_FINE_LOCATION
*/

public void hasPermissionAction(CallbackContext callbackContext) {
JSONObject returnObj = new JSONObject();

Expand All @@ -900,6 +919,81 @@ public void requestPermissionAction(CallbackContext callbackContext) {
cordova.requestPermission(this, REQUEST_ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION);
}

/**
* BLUETOOTH_SCAN
*/

public void hasPermissionBtScanAction(CallbackContext callbackContext) {
JSONObject returnObj = new JSONObject();

addProperty(returnObj, "hasPermission", cordova.hasPermission(Manifest.permission.BLUETOOTH_SCAN));

callbackContext.success(returnObj);
}

public void requestPermissionBtScanAction(CallbackContext callbackContext) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
JSONObject returnObj = new JSONObject();
addProperty(returnObj, keyError, "requestPermission");
addProperty(returnObj, keyMessage, logOperationUnsupported);
callbackContext.error(returnObj);
return;
}

permissionsCallback = callbackContext;
cordova.requestPermission(this, REQUEST_BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_SCAN);
}

/**
* BLUETOOTH_CONNECT
*/

public void hasPermissionBtConnectAction(CallbackContext callbackContext) {
JSONObject returnObj = new JSONObject();

addProperty(returnObj, "hasPermission", cordova.hasPermission(Manifest.permission.BLUETOOTH_CONNECT));

callbackContext.success(returnObj);
}

public void requestPermissionBtConnectAction(CallbackContext callbackContext) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
JSONObject returnObj = new JSONObject();
addProperty(returnObj, keyError, "requestPermission");
addProperty(returnObj, keyMessage, logOperationUnsupported);
callbackContext.error(returnObj);
return;
}

permissionsCallback = callbackContext;
cordova.requestPermission(this, REQUEST_BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_CONNECT);
}

/**
* BLUETOOTH_ADVERTISE
*/

public void hasPermissionBtAdvertiseAction(CallbackContext callbackContext) {
JSONObject returnObj = new JSONObject();

addProperty(returnObj, "hasPermission", cordova.hasPermission(Manifest.permission.BLUETOOTH_ADVERTISE));

callbackContext.success(returnObj);
}

public void requestPermissionBtAdvertiseAction(CallbackContext callbackContext) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
JSONObject returnObj = new JSONObject();
addProperty(returnObj, keyError, "requestPermission");
addProperty(returnObj, keyMessage, logOperationUnsupported);
callbackContext.error(returnObj);
return;
}

permissionsCallback = callbackContext;
cordova.requestPermission(this, REQUEST_BLUETOOTH_ADVERTISE, Manifest.permission.BLUETOOTH_ADVERTISE);
}

public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException {
if (permissionsCallback == null) {
return;
Expand All @@ -908,7 +1002,25 @@ public void onRequestPermissionResult(int requestCode, String[] permissions, int
//Just call hasPermission again to verify
JSONObject returnObj = new JSONObject();

addProperty(returnObj, "requestPermission", cordova.hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
switch (requestCode) {
case REQUEST_ACCESS_FINE_LOCATION:
addProperty(returnObj, "requestPermission", cordova.hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
break;
case REQUEST_BLUETOOTH_SCAN:
addProperty(returnObj, "requestPermission", cordova.hasPermission(Manifest.permission.BLUETOOTH_SCAN));
break;
case REQUEST_BLUETOOTH_CONNECT:
addProperty(returnObj, "requestPermission", cordova.hasPermission(Manifest.permission.BLUETOOTH_CONNECT));
break;
case REQUEST_BLUETOOTH_ADVERTISE:
addProperty(returnObj, "requestPermission", cordova.hasPermission(Manifest.permission.BLUETOOTH_ADVERTISE));
break;
default:
addProperty(returnObj, keyError, "requestPermission");
addProperty(returnObj, keyMessage, logOperationUnsupported);
permissionsCallback.error(returnObj);
return;
}

permissionsCallback.success(returnObj);
}
Expand Down
36 changes: 36 additions & 0 deletions types/ble.ext.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,42 @@ BluetoothlePlugin.Bluetoothle.prototype.hasPermission = function (success) { };
BluetoothlePlugin.Bluetoothle.prototype.requestPermission = function (success) { };


/**
* @param {function(result:[object Object])} success
*/
BluetoothlePlugin.Bluetoothle.prototype.hasPermissionBtScan = function (success) { };


/**
* @param {function(result:[object Object])} success
*/
BluetoothlePlugin.Bluetoothle.prototype.requestPermissionBtScan = function (success) { };


/**
* @param {function(result:[object Object])} success
*/
BluetoothlePlugin.Bluetoothle.prototype.hasPermissionBtConnect = function (success) { };


/**
* @param {function(result:[object Object])} success
*/
BluetoothlePlugin.Bluetoothle.prototype.requestPermissionBtConnect = function (success) { };


/**
* @param {function(result:[object Object])} success
*/
BluetoothlePlugin.Bluetoothle.prototype.hasPermissionBtAdvertise = function (success) { };


/**
* @param {function(result:[object Object])} success
*/
BluetoothlePlugin.Bluetoothle.prototype.requestPermissionBtAdvertise = function (success) { };


/**
* @param {function(result:[object Object])} isLocationEnabledSuccess
* @param {function(error:BluetoothlePlugin.Error)} isLocationEnabledError
Expand Down
Loading

0 comments on commit 16438be

Please sign in to comment.