Skip to content

Commit

Permalink
Merge pull request #185 from jquick-axway/TIMOB-28482
Browse files Browse the repository at this point in the history
chore(android): update for Android 12
  • Loading branch information
lokeshchdhry committed Oct 5, 2021
2 parents 87b74b5 + 364bb68 commit d39f4c0
Show file tree
Hide file tree
Showing 31 changed files with 12,669 additions and 260 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/android.yml
Expand Up @@ -17,7 +17,7 @@ jobs:
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache
USE_CCACHE: 1
SDK_VERSION: 9.3.2.GA
SDK_VERSION: 10.1.0.v20210820083427
MODULE_ID: appcelerator.ble
steps:
- uses: actions/checkout@v2
Expand All @@ -27,6 +27,12 @@ jobs:
with:
node-version: '12.x'

- name: Use JDK 11
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11'

- name: Cache Node.js modules
id: node-cache
uses: actions/cache@v2
Expand Down
4 changes: 2 additions & 2 deletions Jenkinsfile
Expand Up @@ -2,9 +2,9 @@
library 'pipeline-library'

buildModule {
sdkVersion = '9.3.1.GA'
sdkVersion = '10.1.0.v20210820083427'
npmPublish = false // By default it'll do github release on master anyways too
iosLabels = 'osx && xcode-12'
androidBuildToolsVersion = '30.0.2'
androidAPILevel = '30' // unit-tests of BLE module are executable on emulator with api level 30.
}
}
32 changes: 9 additions & 23 deletions README.md
Expand Up @@ -17,20 +17,6 @@ Peripherals that supports Bluetooth Low Energy.

### Android

- Edit the manifest with following uses-permission element to the Android manifest section of the tiapp.xml file.
``` xml
<ti:app>
<android xmlns:android="http://schemas.android.com/apk/res/android">
<manifest>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
</manifest>
</android>
</ti:app>
```

- Set the ``` <module> ``` element in tiapp.xml, such as this:
``` xml
<modules>
Expand All @@ -53,10 +39,10 @@ The BLE variable is a reference to the Module object.
<ti:app>
<ios>
<plist>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>usage description string</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>usage description string</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>usage description string</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>usage description string</string>
</plist>
</ios>
</ti:app>
Expand All @@ -68,11 +54,11 @@ The BLE variable is a reference to the Module object.
<ti:app>
<ios>
<plist>
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
<string>bluetooth-peripheral</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
<string>bluetooth-peripheral</string>
</array>
</plist>
</ios>
</ti:app>
Expand Down
4 changes: 2 additions & 2 deletions android/manifest
Expand Up @@ -2,7 +2,7 @@
# this is your module manifest and used by Titanium
# during compilation, packaging, distribution, etc.
#
version: 1.1.0
version: 2.0.0
apiversion: 4
architectures: arm64-v8a armeabi-v7a x86 x86_64
description: Provides BluetoothLowEnergy module for Titanium applications.
Expand All @@ -15,4 +15,4 @@ name: BluetoothLowEnergy
moduleid: appcelerator.ble
guid: 8d0b486f-27ff-4029-a989-56e4a6755e6f
platform: android
minsdk: 9.0.0
minsdk: 10.0.0
145 changes: 120 additions & 25 deletions android/src/appcelerator/ble/AppceleratorBleModule.java
Expand Up @@ -13,22 +13,30 @@
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import appcelerator.ble.peripheral.TiBLEMutableCharacteristicProxy;
import appcelerator.ble.peripheral.TiBLEPeripheralManagerProxy;
import java.util.ArrayList;
import org.appcelerator.kroll.KrollDict;
import org.appcelerator.kroll.KrollFunction;
import org.appcelerator.kroll.KrollModule;
import org.appcelerator.kroll.KrollObject;
import org.appcelerator.kroll.KrollPromise;
import org.appcelerator.kroll.KrollRuntime;
import org.appcelerator.kroll.annotations.Kroll;
import org.appcelerator.titanium.TiApplication;
import org.appcelerator.titanium.TiBaseActivity;
import org.appcelerator.titanium.TiC;
import ti.modules.titanium.BufferProxy;

@SuppressLint("MissingPermission")
@Kroll.module(name = "AppceleratorBleModule", id = "appcelerator.ble")
public class AppceleratorBleModule extends KrollModule
{

private final BluetoothAdapter btAdapter;
private BluetoothAdapter btAdapter;
private TiBLECentralManagerProxy centralManagerProxy;
private TiBLEPeripheralManagerProxy peripheralManagerProxy;

Expand Down Expand Up @@ -134,7 +142,30 @@ public class AppceleratorBleModule extends KrollModule
public AppceleratorBleModule()
{
super();
btAdapter = BluetoothAdapter.getDefaultAdapter();

// Fetch bluetooth adapter.
final Context context = TiApplication.getInstance();
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager != null) {
this.btAdapter = bluetoothManager.getAdapter();
}

// Release resources when the JS runtime is about to terminate.
KrollRuntime.addOnDisposingListener(new KrollRuntime.OnDisposingListener() {
@Override
public void onDisposing(KrollRuntime runtime)
{
KrollRuntime.removeOnDisposingListener(this);
if (centralManagerProxy != null) {
centralManagerProxy.cleanup();
centralManagerProxy = null;
}
if (peripheralManagerProxy != null) {
peripheralManagerProxy.cleanup();
peripheralManagerProxy = null;
}
}
});
}

@Override
Expand Down Expand Up @@ -164,45 +195,121 @@ public BufferProxy getDisableNotificationValue()
@Kroll.method
public boolean isBluetoothAndBluetoothAdminPermissionsGranted()
{
return getActivity().getPackageManager().checkPermission(Manifest.permission.BLUETOOTH,
getActivity().getPackageName())
== PackageManager.PERMISSION_GRANTED
&& getActivity().getPackageManager().checkPermission(Manifest.permission.BLUETOOTH_ADMIN,
getActivity().getPackageName())
== PackageManager.PERMISSION_GRANTED;
// Create the permission list.
ArrayList<String> permissionList = new ArrayList<>(3);
if (Build.VERSION.SDK_INT >= 31) {
permissionList.add(Manifest.permission.BLUETOOTH_ADVERTISE);
permissionList.add(Manifest.permission.BLUETOOTH_CONNECT);
permissionList.add(Manifest.permission.BLUETOOTH_SCAN);
} else {
permissionList.add(Manifest.permission.BLUETOOTH);
permissionList.add(Manifest.permission.BLUETOOTH_ADMIN);
}

// Determine if permissions are granted.
// Note: On OS versions older than Android 6.0, check if permission is defined in manifest.
TiApplication context = TiApplication.getInstance();
PackageManager packageManager = context.getPackageManager();
String packageName = context.getPackageName();
for (String permissionName : permissionList) {
if (Build.VERSION.SDK_INT >= 23) {
if (context.checkSelfPermission(permissionName) != PackageManager.PERMISSION_GRANTED) {
return false;
}
} else if (packageManager.checkPermission(permissionName, packageName)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}

@Kroll.method
public KrollPromise<KrollDict>
requestBluetoothPermissions(@Kroll.argument(optional = true) KrollFunction permissionCallback)
{
final KrollObject krollObject = getKrollObject();
return KrollPromise.create((promise) -> {
// Do not continue if we already have permission.
if (isBluetoothAndBluetoothAdminPermissionsGranted()) {
KrollDict responseData = new KrollDict();
responseData.putCodeAndMessage(0, null);
if (permissionCallback != null) {
permissionCallback.callAsync(krollObject, responseData);
}
promise.resolve(responseData);
return;
} else if (Build.VERSION.SDK_INT < 31) {
KrollDict responseData = new KrollDict();
responseData.putCodeAndMessage(-1, "Bluetooth permissions not defined in manifest.");
if (permissionCallback != null) {
permissionCallback.callAsync(krollObject, responseData);
}
promise.reject(new Throwable(responseData.getString(TiC.EVENT_PROPERTY_ERROR)));
return;
}

// Do not continue if there is no activity to host the request dialog.
Activity activity = TiApplication.getInstance().getCurrentActivity();
if (activity == null) {
KrollDict responseData = new KrollDict();
responseData.putCodeAndMessage(-1, "There are no activities to host the permission request dialog.");
if (permissionCallback != null) {
permissionCallback.callAsync(krollObject, responseData);
}
promise.reject(new Throwable(responseData.getString(TiC.EVENT_PROPERTY_ERROR)));
return;
}

// Show dialog requesting permission.
String[] permissionsArray = { Manifest.permission.BLUETOOTH_ADVERTISE,
Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN };
TiBaseActivity.registerPermissionRequestCallback(TiC.PERMISSION_CODE_LOCATION, permissionCallback,
krollObject, promise);
activity.requestPermissions(permissionsArray, TiC.PERMISSION_CODE_LOCATION);
});
}

@Kroll.method
public boolean isSupported()
{
return getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
return TiApplication.getInstance().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
}

@Kroll.method
public boolean isEnabled()
{
if (btAdapter == null) {
return false;
}
return btAdapter.isEnabled();
}

@Kroll.method
public boolean enable()
{
if (btAdapter == null) {
return false;
}
return btAdapter.enable();
}

@Kroll.method
public boolean disable()
{
if (btAdapter == null) {
return false;
}
return btAdapter.disable();
}

@Kroll.method
public boolean isAdvertisingSupported()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return btAdapter.getBluetoothLeAdvertiser() != null;
if (btAdapter == null) {
return false;
}
return false;
return btAdapter.getBluetoothLeAdvertiser() != null;
}

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

@Override
public void onDestroy(Activity activity)
{
super.onDestroy(activity);
if (centralManagerProxy != null && activity == TiApplication.getInstance().getRootActivity()) {
centralManagerProxy.cleanup();
}
if (peripheralManagerProxy != null && activity == TiApplication.getInstance().getRootActivity()) {
peripheralManagerProxy.cleanup();
}
}

@Kroll.method
public TiBLEMutableCharacteristicProxy createMutableCharacteristic(KrollDict dict)
{
Expand Down

0 comments on commit d39f4c0

Please sign in to comment.