Skip to content

Commit d39f4c0

Browse files
authored
Merge pull request #185 from jquick-axway/TIMOB-28482
chore(android): update for Android 12
2 parents 87b74b5 + 364bb68 commit d39f4c0

31 files changed

+12669
-260
lines changed

.github/workflows/android.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
env:
1818
CCACHE_DIR: ${{ github.workspace }}/.ccache
1919
USE_CCACHE: 1
20-
SDK_VERSION: 9.3.2.GA
20+
SDK_VERSION: 10.1.0.v20210820083427
2121
MODULE_ID: appcelerator.ble
2222
steps:
2323
- uses: actions/checkout@v2
@@ -27,6 +27,12 @@ jobs:
2727
with:
2828
node-version: '12.x'
2929

30+
- name: Use JDK 11
31+
uses: actions/setup-java@v2
32+
with:
33+
distribution: 'adopt'
34+
java-version: '11'
35+
3036
- name: Cache Node.js modules
3137
id: node-cache
3238
uses: actions/cache@v2

Jenkinsfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
library 'pipeline-library'
33

44
buildModule {
5-
sdkVersion = '9.3.1.GA'
5+
sdkVersion = '10.1.0.v20210820083427'
66
npmPublish = false // By default it'll do github release on master anyways too
77
iosLabels = 'osx && xcode-12'
88
androidBuildToolsVersion = '30.0.2'
99
androidAPILevel = '30' // unit-tests of BLE module are executable on emulator with api level 30.
10-
}
10+
}

README.md

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,6 @@ Peripherals that supports Bluetooth Low Energy.
1717

1818
### Android
1919

20-
- Edit the manifest with following uses-permission element to the Android manifest section of the tiapp.xml file.
21-
``` xml
22-
<ti:app>
23-
<android xmlns:android="http://schemas.android.com/apk/res/android">
24-
<manifest>
25-
<uses-permission android:name="android.permission.BLUETOOTH" />
26-
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
27-
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
28-
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
29-
</manifest>
30-
</android>
31-
</ti:app>
32-
```
33-
3420
- Set the ``` <module> ``` element in tiapp.xml, such as this:
3521
``` xml
3622
<modules>
@@ -53,10 +39,10 @@ The BLE variable is a reference to the Module object.
5339
<ti:app>
5440
<ios>
5541
<plist>
56-
<key>NSBluetoothAlwaysUsageDescription</key>
57-
<string>usage description string</string>
58-
<key>NSBluetoothPeripheralUsageDescription</key>
59-
<string>usage description string</string>
42+
<key>NSBluetoothAlwaysUsageDescription</key>
43+
<string>usage description string</string>
44+
<key>NSBluetoothPeripheralUsageDescription</key>
45+
<string>usage description string</string>
6046
</plist>
6147
</ios>
6248
</ti:app>
@@ -68,11 +54,11 @@ The BLE variable is a reference to the Module object.
6854
<ti:app>
6955
<ios>
7056
<plist>
71-
<key>UIBackgroundModes</key>
72-
<array>
73-
<string>bluetooth-central</string>
74-
<string>bluetooth-peripheral</string>
75-
</array>
57+
<key>UIBackgroundModes</key>
58+
<array>
59+
<string>bluetooth-central</string>
60+
<string>bluetooth-peripheral</string>
61+
</array>
7662
</plist>
7763
</ios>
7864
</ti:app>

android/manifest

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# this is your module manifest and used by Titanium
33
# during compilation, packaging, distribution, etc.
44
#
5-
version: 1.1.0
5+
version: 2.0.0
66
apiversion: 4
77
architectures: arm64-v8a armeabi-v7a x86 x86_64
88
description: Provides BluetoothLowEnergy module for Titanium applications.
@@ -15,4 +15,4 @@ name: BluetoothLowEnergy
1515
moduleid: appcelerator.ble
1616
guid: 8d0b486f-27ff-4029-a989-56e4a6755e6f
1717
platform: android
18-
minsdk: 9.0.0
18+
minsdk: 10.0.0

android/src/appcelerator/ble/AppceleratorBleModule.java

Lines changed: 120 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,30 @@
1313
import android.bluetooth.BluetoothGatt;
1414
import android.bluetooth.BluetoothGattCharacteristic;
1515
import android.bluetooth.BluetoothGattDescriptor;
16+
import android.bluetooth.BluetoothManager;
17+
import android.content.Context;
1618
import android.content.pm.PackageManager;
1719
import android.os.Build;
1820
import appcelerator.ble.peripheral.TiBLEMutableCharacteristicProxy;
1921
import appcelerator.ble.peripheral.TiBLEPeripheralManagerProxy;
22+
import java.util.ArrayList;
2023
import org.appcelerator.kroll.KrollDict;
24+
import org.appcelerator.kroll.KrollFunction;
2125
import org.appcelerator.kroll.KrollModule;
26+
import org.appcelerator.kroll.KrollObject;
27+
import org.appcelerator.kroll.KrollPromise;
28+
import org.appcelerator.kroll.KrollRuntime;
2229
import org.appcelerator.kroll.annotations.Kroll;
2330
import org.appcelerator.titanium.TiApplication;
31+
import org.appcelerator.titanium.TiBaseActivity;
32+
import org.appcelerator.titanium.TiC;
2433
import ti.modules.titanium.BufferProxy;
2534

2635
@SuppressLint("MissingPermission")
2736
@Kroll.module(name = "AppceleratorBleModule", id = "appcelerator.ble")
2837
public class AppceleratorBleModule extends KrollModule
2938
{
30-
31-
private final BluetoothAdapter btAdapter;
39+
private BluetoothAdapter btAdapter;
3240
private TiBLECentralManagerProxy centralManagerProxy;
3341
private TiBLEPeripheralManagerProxy peripheralManagerProxy;
3442

@@ -134,7 +142,30 @@ public class AppceleratorBleModule extends KrollModule
134142
public AppceleratorBleModule()
135143
{
136144
super();
137-
btAdapter = BluetoothAdapter.getDefaultAdapter();
145+
146+
// Fetch bluetooth adapter.
147+
final Context context = TiApplication.getInstance();
148+
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
149+
if (bluetoothManager != null) {
150+
this.btAdapter = bluetoothManager.getAdapter();
151+
}
152+
153+
// Release resources when the JS runtime is about to terminate.
154+
KrollRuntime.addOnDisposingListener(new KrollRuntime.OnDisposingListener() {
155+
@Override
156+
public void onDisposing(KrollRuntime runtime)
157+
{
158+
KrollRuntime.removeOnDisposingListener(this);
159+
if (centralManagerProxy != null) {
160+
centralManagerProxy.cleanup();
161+
centralManagerProxy = null;
162+
}
163+
if (peripheralManagerProxy != null) {
164+
peripheralManagerProxy.cleanup();
165+
peripheralManagerProxy = null;
166+
}
167+
}
168+
});
138169
}
139170

140171
@Override
@@ -164,45 +195,121 @@ public BufferProxy getDisableNotificationValue()
164195
@Kroll.method
165196
public boolean isBluetoothAndBluetoothAdminPermissionsGranted()
166197
{
167-
return getActivity().getPackageManager().checkPermission(Manifest.permission.BLUETOOTH,
168-
getActivity().getPackageName())
169-
== PackageManager.PERMISSION_GRANTED
170-
&& getActivity().getPackageManager().checkPermission(Manifest.permission.BLUETOOTH_ADMIN,
171-
getActivity().getPackageName())
172-
== PackageManager.PERMISSION_GRANTED;
198+
// Create the permission list.
199+
ArrayList<String> permissionList = new ArrayList<>(3);
200+
if (Build.VERSION.SDK_INT >= 31) {
201+
permissionList.add(Manifest.permission.BLUETOOTH_ADVERTISE);
202+
permissionList.add(Manifest.permission.BLUETOOTH_CONNECT);
203+
permissionList.add(Manifest.permission.BLUETOOTH_SCAN);
204+
} else {
205+
permissionList.add(Manifest.permission.BLUETOOTH);
206+
permissionList.add(Manifest.permission.BLUETOOTH_ADMIN);
207+
}
208+
209+
// Determine if permissions are granted.
210+
// Note: On OS versions older than Android 6.0, check if permission is defined in manifest.
211+
TiApplication context = TiApplication.getInstance();
212+
PackageManager packageManager = context.getPackageManager();
213+
String packageName = context.getPackageName();
214+
for (String permissionName : permissionList) {
215+
if (Build.VERSION.SDK_INT >= 23) {
216+
if (context.checkSelfPermission(permissionName) != PackageManager.PERMISSION_GRANTED) {
217+
return false;
218+
}
219+
} else if (packageManager.checkPermission(permissionName, packageName)
220+
!= PackageManager.PERMISSION_GRANTED) {
221+
return false;
222+
}
223+
}
224+
return true;
225+
}
226+
227+
@Kroll.method
228+
public KrollPromise<KrollDict>
229+
requestBluetoothPermissions(@Kroll.argument(optional = true) KrollFunction permissionCallback)
230+
{
231+
final KrollObject krollObject = getKrollObject();
232+
return KrollPromise.create((promise) -> {
233+
// Do not continue if we already have permission.
234+
if (isBluetoothAndBluetoothAdminPermissionsGranted()) {
235+
KrollDict responseData = new KrollDict();
236+
responseData.putCodeAndMessage(0, null);
237+
if (permissionCallback != null) {
238+
permissionCallback.callAsync(krollObject, responseData);
239+
}
240+
promise.resolve(responseData);
241+
return;
242+
} else if (Build.VERSION.SDK_INT < 31) {
243+
KrollDict responseData = new KrollDict();
244+
responseData.putCodeAndMessage(-1, "Bluetooth permissions not defined in manifest.");
245+
if (permissionCallback != null) {
246+
permissionCallback.callAsync(krollObject, responseData);
247+
}
248+
promise.reject(new Throwable(responseData.getString(TiC.EVENT_PROPERTY_ERROR)));
249+
return;
250+
}
251+
252+
// Do not continue if there is no activity to host the request dialog.
253+
Activity activity = TiApplication.getInstance().getCurrentActivity();
254+
if (activity == null) {
255+
KrollDict responseData = new KrollDict();
256+
responseData.putCodeAndMessage(-1, "There are no activities to host the permission request dialog.");
257+
if (permissionCallback != null) {
258+
permissionCallback.callAsync(krollObject, responseData);
259+
}
260+
promise.reject(new Throwable(responseData.getString(TiC.EVENT_PROPERTY_ERROR)));
261+
return;
262+
}
263+
264+
// Show dialog requesting permission.
265+
String[] permissionsArray = { Manifest.permission.BLUETOOTH_ADVERTISE,
266+
Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN };
267+
TiBaseActivity.registerPermissionRequestCallback(TiC.PERMISSION_CODE_LOCATION, permissionCallback,
268+
krollObject, promise);
269+
activity.requestPermissions(permissionsArray, TiC.PERMISSION_CODE_LOCATION);
270+
});
173271
}
174272

175273
@Kroll.method
176274
public boolean isSupported()
177275
{
178-
return getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
276+
return TiApplication.getInstance().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
179277
}
180278

181279
@Kroll.method
182280
public boolean isEnabled()
183281
{
282+
if (btAdapter == null) {
283+
return false;
284+
}
184285
return btAdapter.isEnabled();
185286
}
186287

187288
@Kroll.method
188289
public boolean enable()
189290
{
291+
if (btAdapter == null) {
292+
return false;
293+
}
190294
return btAdapter.enable();
191295
}
192296

193297
@Kroll.method
194298
public boolean disable()
195299
{
300+
if (btAdapter == null) {
301+
return false;
302+
}
196303
return btAdapter.disable();
197304
}
198305

199306
@Kroll.method
200307
public boolean isAdvertisingSupported()
201308
{
202-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
203-
return btAdapter.getBluetoothLeAdvertiser() != null;
309+
if (btAdapter == null) {
310+
return false;
204311
}
205-
return false;
312+
return btAdapter.getBluetoothLeAdvertiser() != null;
206313
}
207314

208315
@Kroll.method
@@ -217,18 +324,6 @@ public TiBLEPeripheralManagerProxy initPeripheralManager(@Kroll.argument(optiona
217324
return peripheralManagerProxy = new TiBLEPeripheralManagerProxy();
218325
}
219326

220-
@Override
221-
public void onDestroy(Activity activity)
222-
{
223-
super.onDestroy(activity);
224-
if (centralManagerProxy != null && activity == TiApplication.getInstance().getRootActivity()) {
225-
centralManagerProxy.cleanup();
226-
}
227-
if (peripheralManagerProxy != null && activity == TiApplication.getInstance().getRootActivity()) {
228-
peripheralManagerProxy.cleanup();
229-
}
230-
}
231-
232327
@Kroll.method
233328
public TiBLEMutableCharacteristicProxy createMutableCharacteristic(KrollDict dict)
234329
{

0 commit comments

Comments
 (0)