Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved Settings and Region configuration APIs #1061

Open
davidgyoung opened this issue Nov 4, 2021 · 2 comments
Open

Improved Settings and Region configuration APIs #1061

davidgyoung opened this issue Nov 4, 2021 · 2 comments

Comments

@davidgyoung
Copy link
Member

davidgyoung commented Nov 4, 2021

The Problem

Configuring the library has evolved over time with a mixed bag of styles of settings including:

  • settings in manifest declarations
  • settings on the BeaconManager (both static and instance)
  • settings on Beacon (static)
  • BeaconParsers

In addition, changing settings at runtime (after scanning has started) can sometimes cause problems and behavior is either poorly documented, non-deterministic, or at worst cause crashes. Even in the best of cases, changes to not necessarily take effect right away, and it is unclear to users what does take effect right away and what does not.

Constraints

This proposal for improvement in the library API is designed to stay within the following constraints:

  1. Make it easier for library users to configure library settings
  2. Retain existing settings API (temporarily for 2.x library versions with API marked as deprecated) for backward compatibility.
  3. Only support the new settings API in 3.0+ library releases

Settings API Proposal

The Settings Class below is used to set up library scanning settings. These are typically set before starting ranging/monitoring. If you want to change them after ranging and monitoring are already started, the settings change will stop and restart ranging and monitoring.

The class design below is designed to use a Kotlin data class with a Builder class designed for use by Java apps

Kotlin:

        val settings = Settings(
            debug = true,
            distanceModelUpdateUrl = "https://s3.amazonaws.com/android-beacon-library/android-distance.json",
            scanStrategy = Settings.ForegroundServiceScanStrategy(
                Notification.Builder(
                    context,
                    "BeaconReferenceApp"
                ).build(), 1
            ),
            longScanForcingEnabled = true,
            scanPeriods = Settings.ScanPeriods(
                foregroundScanPeriodMillis = 1100,
                foregroundBetweenScanPeriodMillis = 0,
                backgroundScanPeriodMillis = 1100,
                backgroundBetweenScanPeriodMillis = 0))
        beaconManager.adjustSettings(settings)

Java:

        Settings settings = new Settings.Builder()
                .setDebug(true)
                .setDistanceModelUpdateUrl("https://s3.amazonaws.com/android-beacon-library/android-distance.json")
                .setScanPeriods(new Settings.ScanPeriods(1100, 0, 10000, 0))
                .setScanStrategy(new Settings.ForegroundServiceScanStrategy(
                        new Notification.Builder(context, "BeaconReferenceApp").build(),1)
                )
                .setLongScanForcingEnabled(true)
                .build();
        beaconManager.adjustSettings(settings); 

There are three methods added to BeaconManager for applying a Settings object:

  1. adjustSettings(settings) // Applies Applies settings fields explicitly configured on the passed settings object and any fields not configured are left to what they were before this call. This effectively applies a delta
  2. replaceSettings(settings) // Applies settings fields explicitly configured on the passed settings object and any fields not configured are set to library defaults
  3. revertSettings() // Reverts all previously applied settings in favor of library defaults

Configure scheduled job strategy (default on Android 8+)

        val settings = Settings(
            scanStrategy = Settings.JobServiceScanStrategy(
                immediateJobId = 1234,
                periodicJobId = 1235,
                jobPersistenceEnabled = true
            ),
            longScanForcingEnabled = true,
            scanPeriods = Settings.ScanPeriods(
                foregroundScanPeriodMillis = 1100,
                foregroundBetweenScanPeriodMillis = 0,
                backgroundScanPeriodMillis = 30000,
                backgroundBetweenScanPeriodMillis = 300000
            )
        )
        beaconManager.adjustSettings(settings)

Configure background service strategy (default on Android 4.3-7.x)

        val settings = Settings(
            scanStrategy = Settings.BackgroundServiceScanStrategy()
        )
        beaconManager.adjustSettings(settings)

Configure foreground service strategy

        val settings = Settings(
            scanStrategy = Settings.ForegroundServiceScanStrategy(
                Notification.Builder(
                    context,
                    "BeaconReferenceApp"
                ).build(), 1
            ),
            longScanForcingEnabled = true,
            scanPeriods = Settings.ScanPeriods(
                foregroundScanPeriodMillis = 1100,
                foregroundBetweenScanPeriodMillis = 0,
                backgroundScanPeriodMillis = 1100,
                backgroundBetweenScanPeriodMillis = 0))
        beaconManager.adjustSettings(settings)

Configure intent scan strategy

        val settings = Settings(
            scanStrategy = Settings.IntentScanStrategy(),
            longScanForcingEnabled = true,
            scanPeriods = Settings.ScanPeriods(
                foregroundScanPeriodMillis = 1100,
                foregroundBetweenScanPeriodMillis = 0,
                backgroundScanPeriodMillis = 1100,
                backgroundBetweenScanPeriodMillis = 0)
        )
        beaconManager.adjustSettings(settings)

Deprecated settings that will not be supported by new API

beaconManager.setScannerInSameProcess()
beaconManager.setDataRequestNotifier()
beaconManager.getBeaconParsers()
beaconManager.isAndroidLScanningDisabled()

New BeaconParsers and Region API

Instead of manually configuring BeaconParsers on the BeaconManager using the beaconManager.getBeaconParsers() collection, a new Region class called BeaconRegion will explicitly set the BeaconParser used for each region. Starting ranging or monitoring will auto-register the parser with the library if it has not already been registered.

The point of this change is to make it pretty much impossible to forget to register a parser before starting ranging/monitoring. This also makes it explicit which beacon type you are looking for with the region, and only beacons of that type will match the region.

While proprietary closed-source beacon types cannot be configured in the AltBeacon project due to intellectual property restrictions, external libraries can define them. Referencing these external libraries with the parser definitions makes it much easier to configure apps to work with proprietary beacons:

build.gradle:

dependencies {
    implementation 'com.davidgyoungtech:beacon-parsers:1.0'  // Defines IBeacon and other proprietary formats
    implementation 'org.altbeacon:android-beacon-library:3.0'  // This library without proprietary beacon support

Start ranging:

    val iBeaconRegion = BeaconRegion("all-ibeacons", IBeaconParser(), null, null, null)
    beaconManager.startRangingBeacons(iBeaconRegion)

Note in the above that there is a new second parameter in the region constructor for the BeaconParser. This is parser is activated in the library the first time ranging or monitoring is started as shown in the second line.

@davidgyoung davidgyoung changed the title Improved Settings API Improved Settings API - 3.0 Jan 14, 2024
@davidgyoung davidgyoung changed the title Improved Settings API - 3.0 Improved Settings and Region configuration APIs Jan 14, 2024
@davidgyoung
Copy link
Member Author

The redesign needs to replace and deprecate the BeaconManager configuration method public static void setRssiFilterImplClass(@NonNull Class c) due to issues in #1164. The RssiFilter interface will hopefully remain unchanged.

@davidgyoung
Copy link
Member Author

Work in progress PR is here: #1177

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant