Testing and diagnostics
Approve a test phone, send it a test push and a test geofence, read where Bubbl stands on the device, and find its logs.
A first test run#
- Start the app with your Sandbox key and address, and approve the phone under Configuration › Test Devices. See Sandbox and Production.
- Check
Bubbl.diagnostics():activeandregisteredtrue. - Send a test push from the Active users card on the dashboard's home page, or from Configuration › Test Devices. See Send a test push.
- For a guided run, open Set up the SDK from Configuration › Developers. Its Test checklist ticks six checks as your phone reports them, and can place a temporary 100 m test geofence at your approved test phone for 30 minutes: walk into it, or open the app inside it, and its notification should show. See SDK setup.
Diagnostics#
Bubbl.diagnostics() says where Bubbl stands on the device, for your support or debug screen. It's suspend (or takes a callback) on Android, async (or takes a completion handler) on iOS, and returns a Future or Promise in Flutter and React Native.
Bubbl.diagnostics { d ->
Log.i("App", "active=${d.active} registered=${d.registered} push=${d.hasPushToken} " +
"geofences=${d.geofences} background=${d.backgroundLocation} lastError=${d.lastError}")
}let d = await Bubbl.diagnostics()
print(d.active, d.registered, d.hasPushToken, d.geofences, d.backgroundLocation, d.osWatchesGeofences, d.lastError ?? "none")final d = await Bubbl.diagnostics();
debugPrint('installId=${d.installId} active=${d.active} registered=${d.registered} push=${d.hasPushToken} '
'geofences=${d.geofences} background=${d.backgroundLocation} lastError=${d.lastError}');const d = await Bubbl.diagnostics();
console.log(d.installId, d.active, d.registered, d.hasPushToken, d.geofences, d.backgroundLocation, d.lastError);| Field | What you want to see |
|---|---|
started, active | True. If active is false, check consentRequired and consent, pausedUntil, sdkSupported and supported. |
supported | True: the device meets the runtime minimum (Android 8.1, iOS 17). |
sdkSupported | True. False means your workspace requires a newer SDK. |
registered | True after the first successful call to Bubbl, straight away with a device credential. |
installId | This install's ID: search for it under Active users in the dashboard. |
environment, testDevice | "sandbox" or "production"; in a Sandbox, the test device's status and, while pending, its code. |
permissions | What the user allowed. |
hasPushToken | True once the phone has a push token. |
geofences | How many are watched. |
backgroundLocation | True with "Always" or "Allow all the time"; otherwise geofences work only while the app is open. |
locationEnabled | False after setLocationEnabled(false). |
queuedEvents | Events waiting to be sent. |
lastError | The last error Bubbl logged. |
pausedUntil | Set when the server has paused Bubbl, in Unix seconds. |
credentialRejected | False. True means the server refused the device credential Bubbl was started with. |
transitionsDroppedWhileLocked | Geofence events lost before the first unlock after a reboot (iOS; always 0 on Android). |
sdkVersion | The SDK version running. |
Each platform adds its own fields. In Flutter and React Native they're null on the other platform:
- Android:
backgroundRestricted(the user restricted the app's background activity, so Bubbl can't run with the app closed) andbatteryOptimized(battery optimisation applies, the default, so background work may be delayed in Doze). - iOS:
osWatchesGeofences(iOS watches the geofences itself: "Always", precise location, and a device that can),backgroundRefreshAvailable(Background App Refresh is on for the app) andlowPowerMode(Low Power Mode holds background work back).
See Diagnostics for the full types.
Logs#
Bubbl logs natively. Set how much with logLevel in BubblOptions: none, error, warning (the default), info or debug.
BubblOptions(baseUrl = "https://api.sandbox.bubbl.tech", logLevel = BubblOptions.LogLevel.DEBUG)BubblOptions(baseUrl: "https://api.sandbox.bubbl.tech", logLevel: .debug)const BubblOptions(baseUrl: 'https://api.sandbox.bubbl.tech', logLevel: BubblLogLevel.debug){ baseUrl: 'https://api.sandbox.bubbl.tech', logLevel: 'debug' }- Android: Logcat, tag
BubblSDK. - iOS: the unified log, subsystem
tech.bubbl.sdk: the Xcode console, or Console.app filtered on the subsystem. - Flutter and React Native: the same native logs, in Logcat or the iOS unified log, not the Dart or JavaScript console.
Useful lines to look for: Bubbl … started with the SDK version (at info level), Bubbl sandbox: approve this device with code …, and Bubbl.… before Bubbl.start: ignored when a call comes too early.
Local development over http#
The API address must be https://. For a local server, http:// is allowed only for localhost, 127.0.0.1, 10.0.2.2 (the Android emulator's host) and *.test hosts. Your app must also allow cleartext traffic to that host:
- Android: a network security config that permits cleartext to that host.
- iOS: App Transport Security blocks it unless
Info.plistsetsNSAppTransportSecurity›NSAllowsLocalNetworkingtoYES. Bubbl logs a warning if it's missing. Add it to development builds only. - Expo: Bubbl's config plugin options
android.cleartextHosts(a network security config allowing only those hosts) andios.allowLocalNetworking. If your app already setsandroid:networkSecurityConfig, the plugin refusescleartextHostswith an error: add the hosts to your own config instead. Keep both out of release builds, for example fromapp.config.jswith an environment variable.
Tests and places without Bubbl#
Where there's no native module (Jest, Expo Go, your app's web build, or a build from before you installed the package), Bubbl's calls do nothing and log one error saying why. Bubbl.diagnostics() still resolves, with started and active false and the reason in lastError. Rebuild the app after installing.
In Jest, use the package's mock, whose functions are jest.fns:
jest.mock('@bubblsdk/react-native-sdk', () => require('@bubblsdk/react-native-sdk/jest'));Related#
- Troubleshooting
- Active users and Test devices in the dashboard docs.