Skip to main content

Upgrading to 1.12

AFCore 1.12 adds the locations(), content() and activePerks() modules and has a handful of breaking changes. An app that builds its config with AFCoreConfig.Builder, runs on the Bismuth realm and does not use Movement Health upgrades by changing only the version: reads keep their 1.11 behavior unless you opt in. Work through the checklist below; the full list of changes is in the changelog.

1. Update the dependency​

implementation("com.advantahealth:core-android:1.12.1")
  • Android: exclude AFCore from backups (required). Unless your app sets android:allowBackup="false", reference AFCore's backup rule files or copy their entries into yours -- see Install on Android.
  • Android dependencies moved forward with no code change: Kotlin stdlib 2.4.21, Ktor 3.5.2, Kermit 2.2.0, WorkManager 2.12.0, Fragment 1.9.1 (kotlinx-coroutines stays at 1.11.0). compileSdk 37 and minSdk 26 are unchanged.

2. Breaking changes​

  • AFException.message is member-safe. For system failures it is now a short sentence you can show as is. Log technicalMessage instead of message, and branch on kind (AFErrorKind) instead of parsing the text. Backend refusals can also carry a machine-readable errorCode. See Error Handling.
  • registerMovrProfile() returns the Movr external id (String?) instead of Boolean, and throws on failure. Configure the MOVR SDK with that id; null means no usable profile was registered.
  • Virtual Fitness status. isMemberRegisteredToNeou() / isMemberRegisteredToLifetimeDigital() are deprecated (their result was inverted). Use getNEOUStatus() / getLifetimeDigitalStatus() and handle CONNECTED, NOT_ENROLLED and ACCOUNT_DISABLED.
  • New enum values AFHeartbeatTrigger.SIGNIFICANT_LOCATION_CHANGE and DeviceType.GOOGLE_HEALTH: add a branch (or else) to exhaustive Kotlin when expressions.
  • New interface members on Activities, Authentication, ApplicationSettings, VirtualFitness and MyCarePath: only code that implements these interfaces (typically test fakes) must add them. Prebuilt libraries that construct MenuItem, BottomNavItem or AFActivitiesSummary must be recompiled.
  • androidx.security:security-crypto is no longer included. If your app uses EncryptedSharedPreferences or MasterKey, declare androidx.security:security-crypto:1.1.0 yourself.

3. Set the realm (Horizon apps) and decide on read failures​

Apps whose members are on Horizon must set the realm; without it requests are routed to Bismuth, the 1.11 behavior. See Initialization.

throwOnReadFailure defaults to false, so reads that existed in 1.11 still return an empty result when they fail. Setting it to true (recommended, and the only behavior in 2.0) makes them throw AFException, so an empty result always means "no data". Before you turn it on, wrap every such read in try/catch / do/catch: on Android the compiler does not force you to, and on iOS watch for try? and force-unwraps. Reads added in 1.12 always throw.

val config = AFCoreConfig.builder()
.baseUrl("https://api.example.com")
.realm(AFRealm.HORIZON) // Horizon apps only
.throwOnReadFailure(true) // optional, recommended
.build()

4. Deprecations at a glance​

Everything below still works in 1.12 and produces a warning that names its replacement, so you can migrate screen by screen. A build with allWarningsAsErrors / -Werror must migrate or suppress them.

DeprecatedUse instead
AFCoreConfig public constructorAFCoreConfig.builder() / AFCoreConfig.Builder()
AFCore.sessionState, AFCore.isLoggedIn()AFCore.authentication().sessionState, .isLoggedIn()
facilities().get()locations().getFavorites(), keeping FAVORITE and MUTED (it also returns EXCLUDED)
locations().getFavorites(type) (1.12.1)locations().getFavorites(), then filter by favoriteType
facilities().update(id, verified = true) / delete(id)locations().addFavorite(locationId) / removeFavorite(locationId)
facilities().nominateFacility(...) / getNominatedFacilities()locations().nominateLocation(...) / getMySubmissions(...)
facilities().startMonitoring() / stopMonitoring() / isMonitoringActive()locations().startVisitDetection() / stopVisitDetection() / isVisitDetectionActive()
facilities().geofenceEvents, subscribeToEvents / subscribeToStatuslocations().visitEvents, subscribeToVisitEvents / subscribeToVisitDetectionStatus
map().getNearbyFacilities(...) / getFacilitiesByViewPort(...)locations().getLocationsByRadius(...) / getLocationsByViewPort(...)
heartbeatEnabled(value) (builder), AFCore.setHeartbeatEnabled(...)locationSharingEnabled(value) in the config (reconfigure to change it)
AFCore.heartbeat, AFCore.heartbeatEnabled, AFCore.fireDebugHeartbeat()locations().locationSharing, locations().locationSharingEnabled, locations().shareLocationNow()
Swift subscribeToHeartbeat / subscribeToHeartbeatEnabledlocations().subscribeToLocationSharing / subscribeToLocationSharingEnabled

When you switch to locations():

  • Keep calling facilities().update(id, verified = false) to exclude a location; Locations has no replacement yet (muting a favorite only pauses it).
  • Visit detection monitors fitness favorites only (FavoriteLocation.isFitness); stores never earn gym visits. Automatic visits are credited exactly as before.
  • Background location sharing is new and only available through locationSharingEnabled(true) with "Always" location permission. See Locations.

5. userInterface() changes​

userInterface() keeps its signatures. Route keys are now normalized (SMARTWALKING → MY_DASHBOARD, HOME_WORKOUTS → FIT_HOME, MOVEMENT_HEALTH → MOVR), so you can remove your own mapping for the AIDE names. MenuItem gains section fields and BottomNavItem a webUrl, both with null defaults. For new code, consider content().

6. Other behavior to check​

  • Sign-out. logout() now also stops SmartWalking auto-sync (call enableAutoSync() again after the next sign-in) and removes this install's push registration. If you call messaging().deleteToken(), call it before logout().
  • Session boundaries. A different member signing in, or re-initializing for another base URL or realm, clears the previous member's cached data, queued submissions and monitoring.
  • Sessions survive temporary failures. Only a rejected refresh token ends a session; timeouts and server errors keep the member signed in.
  • New writes are never queued. locations() and activePerks() writes reach the backend or throw.
  • Device storage (iOS). Keychain items move to device-only storage on first launch without signing the member out. No action needed.
  • Rolling back. Prefer a forward fix: a 1.11 build still starts after 1.12, but signs members out once.
  • AFCoreInternalApi warnings mark declarations that were public only for technical reasons. Stop using them.

7. New modules​

Adopt them when you are ready: locations() (favorites, place search, visit detection, location sharing), content() (toolbar, banners, Explore menu), activePerks() (rewards; your client needs the ActivePerks capability). If one of them is not available in your environment, contact your Advanta representative.

Learn more​

See the API Reference and the changelog. Complete integration guides are in AIDE Docs.