Skip to content

Commit

Permalink
Merge pull request #241 from polarofficial/#240-API-docs-updated-and-…
Browse files Browse the repository at this point in the history
…scanning-fix

#240 documentation enhanced and deprecated backgroundEntered function
  • Loading branch information
JOikarinen authored Feb 21, 2022
2 parents d59fae6 + d1b9b61 commit 219f767
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ public interface BlePowerStateChangedCallback {
void stateChanged(boolean power);
}

/**
* Restarts the scan
*/
public abstract void scanRestart();

/**
* @param filters scan filter list, android specific
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ public boolean bleActive() {
return bluetoothAdapter != null && bluetoothAdapter.isEnabled();
}

@Override
public void scanRestart() {
scanCallback.scanRestart();
}

@Override
public void setScanFilters(@Nullable List<ScanFilter> filters) {
scanCallback.setScanFilters(filters);
Expand Down Expand Up @@ -270,6 +275,7 @@ public boolean isScanningNeeded() {

@Override
public void scanStartError(@NonNull String error) {
BleLogger.e(TAG, "scanStartError " + error);
RxUtils.postError(observers, new BleStartScanError(error));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,40 @@ import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.content.Context
import android.os.Build
import android.os.ParcelUuid
import com.polar.androidcommunications.api.ble.BleLogger
import com.polar.androidcommunications.api.ble.model.gatt.client.BleHrClient
import com.polar.androidcommunications.api.ble.model.gatt.client.psftp.BlePsFtpUtils
import com.polar.androidcommunications.common.ble.BleUtils.EVENT_TYPE
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Scheduler
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers
import java.util.*
import java.util.concurrent.TimeUnit

internal class BDScanCallback(
context: Context,
private val bluetoothAdapter: BluetoothAdapter,
private val scanCallbackInterface: BDScanCallbackInterface
) {
companion object {
private const val TAG = "BDScanCallback"
private const val POLAR_MANUFACTURER_ID = 0x006b

// scan window limit, for android's "is scanning too frequently"
private const val SCAN_WINDOW_LIMIT = 30000
}

private var scanFilter: List<ScanFilter>? = null

init {
val defaultFilter: MutableList<ScanFilter> = ArrayList()
defaultFilter.add(ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(BleHrClient.HR_SERVICE.toString())).build())
defaultFilter.add(ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(BlePsFtpUtils.RFC77_PFTP_SERVICE.toString())).build())
defaultFilter.add(ScanFilter.Builder().setManufacturerData(POLAR_MANUFACTURER_ID, byteArrayOf()).build())
this.scanFilter = defaultFilter
}

private enum class ScanAction {
ENTRY,
Expand All @@ -47,7 +66,7 @@ internal class BDScanCallback(
var lowPowerEnabled = false
var opportunistic = true
private var adminStops = 0
private var filters: List<ScanFilter>? = null

private var delaySubscription: Disposable? = null
private var opportunisticScanTimer: Disposable? = null

Expand All @@ -59,7 +78,12 @@ internal class BDScanCallback(

fun setScanFilters(filters: List<ScanFilter>?) {
stopScan()
this.filters = filters
this.scanFilter = filters
startScan()
}

fun scanRestart() {
stopScan()
startScan()
}

Expand Down Expand Up @@ -297,7 +321,7 @@ internal class BDScanCallback(

private fun callStartScanL(scanSettings: ScanSettings) {
try {
bluetoothAdapter.bluetoothLeScanner.startScan(filters, scanSettings, leScanCallback)
bluetoothAdapter.bluetoothLeScanner.startScan(scanFilter, scanSettings, leScanCallback)
} catch (e: Exception) {
val errorString = "Failed to start scan. Reason: ${e.message}"
BleLogger.e(TAG, errorString)
Expand All @@ -324,10 +348,5 @@ internal class BDScanCallback(
}
}

companion object {
private val TAG = BDScanCallback::class.java.simpleName

// scan window limit, for android's "is scanning too frequently"
private const val SCAN_WINDOW_LIMIT = 30000
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ protected PolarBleApi(final int features) {
* the android component (e.g. Activity or Service) then the shutDown may be called
* on component destroy function. After shutDown the new instance of the SDK is needed:
*
* @see PolarBleApiDefaultImpl#defaultImplementation
* @see PolarBleApiDefaultImpl#defaultImplementation(Context, int)
*/
public abstract void shutDown();

Expand All @@ -145,7 +145,11 @@ protected PolarBleApi(final int features) {
public abstract void cleanup();

/**
* @param enable false disable polar filter which means in all apis identifier can be bt address too
* When enabled only Polar devices are found by the {@link #searchForDevice()}, if set to false
* any BLE devices with HR services are returned by the {@link #searchForDevice()}. The default setting for
* Polar filter is true.
*
* @param enable false disables polar filter
*/
public abstract void setPolarFilter(boolean enable);

Expand All @@ -161,11 +165,18 @@ protected PolarBleApi(final int features) {

/**
* enables scan filter while on background
*
* @deprecated in release 3.2.8. Move to the background is not relevant information for SDK starting from release 3.2.8
*/
@Deprecated
public abstract void backgroundEntered();

/**
* disables scan filter while on foreground
* Optionally call when application enters to the foreground. By calling foregroundEntered() you make
* sure BLE scan is restarted. BLE scan start is not working when Android device display is off
* (related to Android power save). By calling foregroundEntered() helps in some rare situations
* e.g. if connection is lost to the device and {@link #setAutomaticReconnection(boolean)} is enabled,
* reconnection is created when application is back in foreground.
*/
public abstract void foregroundEntered();

Expand All @@ -184,7 +195,7 @@ protected PolarBleApi(final int features) {
public abstract void setApiLogger(@NonNull PolarBleApiLogger logger);

/**
* Enable or disable automatic reconnection feature
* When enabled the reconnection is attempted if device connection is lost. By default automatic reconnection is enabled.
*
* @param enable true = automatic reconnection is enabled, false = automatic reconnection is disabled
*/
Expand Down Expand Up @@ -248,7 +259,7 @@ public abstract Single<PolarSensorSetting> requestFullStreamSettings(@NonNull fi
public abstract Completable autoConnectToDevice(int rssiLimit, @Nullable String service, @Nullable final String polarDeviceType);

/**
* Request a connection to a Polar device. Invokes {@link PolarBleApiCallback#deviceConnected(PolarDeviceInfo)} callback.
* Request a connection to a BLE device. Invokes {@link PolarBleApiCallback#deviceConnected(PolarDeviceInfo)} callback.
*
* @param identifier Polar device id found printed on the sensor/device (in format "12345678")
* or bt address (in format "00:11:22:33:44:55")
Expand All @@ -257,9 +268,9 @@ public abstract Single<PolarSensorSetting> requestFullStreamSettings(@NonNull fi
public abstract void connectToDevice(@NonNull final String identifier) throws PolarInvalidArgument;

/**
* Request disconnecting from a Polar device. Invokes {@link PolarBleApiCallback#deviceDisconnected(PolarDeviceInfo)} callback.
* Request disconnecting from a BLE device. Invokes {@link PolarBleApiCallback#deviceDisconnected(PolarDeviceInfo)} callback.
*
* @param identifier Polar device id found printed on the sensor/device or bt address
* @param identifier Polar device id found printed on the sensor/device or bt address (in format "00:11:22:33:44:55")
* @throws PolarInvalidArgument if identifier is invalid formatted mac address or polar device id
*/
public abstract void disconnectFromDevice(@NonNull final String identifier) throws PolarInvalidArgument;
Expand Down Expand Up @@ -339,19 +350,24 @@ public abstract Completable startRecording(@NonNull final String identifier,
public abstract Completable removeExercise(@NonNull final String identifier, @NonNull final PolarExerciseEntry entry);

/**
* Start searching for device(s)
* Starts searching for BLE devices when subscribed. Search continues as long as observable is
* subscribed or error. Each found device is emitted only once. By default searches only for Polar devices,
* but can be controlled by {@link #setPolarFilter(boolean)}. If {@link #setPolarFilter(boolean)} is false
* then searches for any BLE heart rate capable devices
*
* @return Flowable stream of {@link PolarDeviceInfo}
* Produces:
* <BR> - onNext for any new Polar device detected
* <BR> - onNext for any new Polar (or BLE) device detected
* <BR> - onError if scan start fails
* <BR> - onComplete non produced unless stream is further configured
*/
@NonNull
public abstract Flowable<PolarDeviceInfo> searchForDevice();

/**
* Start listening to heart rate broadcasts from one or more Polar devices
* Start listening the heart rate from Polar devices when subscribed. This observable listens BLE
* broadcast and parses heart rate from BLE broadcast. The BLE device is not connected when
* using this function.
*
* @param deviceIds set of Polar device ids to filter or null for a any Polar device
* @return Flowable stream of {@link PolarHrBroadcastData}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
public class PolarHrBroadcastData {

/**
* @see polar.com.sdk.api.model.PolarDeviceInfo
* Device information
*
* @see PolarDeviceInfo
*/
public final PolarDeviceInfo polarDeviceInfo;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
import static com.polar.androidcommunications.api.ble.model.gatt.client.pmd.PmdControlPointResponse.PmdControlPointResponseCode.ERROR_ALREADY_IN_STATE;

import android.annotation.SuppressLint;
import android.bluetooth.le.ScanFilter;
import android.content.Context;
import android.os.Build;
import android.os.ParcelUuid;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
Expand Down Expand Up @@ -102,7 +99,7 @@
* The default implementation of the Polar API
*/
public class BDBleApiImpl extends PolarBleApi implements BleDeviceListener.BlePowerStateChangedCallback {

private static final String TAG = "BDBleApiImpl";
private static volatile BDBleApiImpl instance;
private final Map<String, Disposable> connectSubscriptions = new HashMap<>();
private final Map<String, Disposable> deviceDataMonitorDisposable = new HashMap<>();
Expand Down Expand Up @@ -178,17 +175,6 @@ private static void clearInstance() {
instance = null;
}

private void enableAndroidScanFilter() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
List<ScanFilter> scanFilter = new ArrayList<>();
scanFilter.add(new ScanFilter.Builder().setServiceUuid(
ParcelUuid.fromString(BleHrClient.HR_SERVICE.toString())).build());
scanFilter.add(new ScanFilter.Builder().setServiceUuid(
ParcelUuid.fromString(BlePsFtpUtils.RFC77_PFTP_SERVICE.toString())).build());
listener.setScanFilters(scanFilter);
}
}

@Override
public void setMtu(int mtu) {
listener.setMtu(mtu);
Expand Down Expand Up @@ -366,12 +352,12 @@ private Single<PolarSensorSetting> queryFullSettings(final String identifier, fi

@Override
public void backgroundEntered() {
enableAndroidScanFilter();
BleLogger.w(TAG, "call of deprecated backgroundEntered() method");
}

@Override
public void foregroundEntered() {
listener.setScanFilters(null);
listener.scanRestart();
}

@NonNull
Expand Down

0 comments on commit 219f767

Please sign in to comment.