Usage
Once the native side is wired up (see Get Started),
call the SDK from TypeScript through the src/TrackingSdk.ts wrapper.
Available API
| Wrapper function | Android behaviour |
|---|---|
initAndStartTracking(username, skip, token?, distance?) | Initializes the SDK and starts tracking; resolves to a result object |
stopTracking() | Stops tracking; normally resolves to "Tracking stopped" |
getTrackingState() | Queries native SDK state; the wrapper returns false if unavailable or on error |
getSavedTrackingStatus() | Reads the locally saved { enabled, username }; username may be null |
getDeviceHealth() | Returns device health flags; the wrapper returns null on failure |
src/TrackingSdk.ts also exports startTracking, syncTracking, refreshAccessToken and
destroyTrackingSdk, but the current Kotlin module does not implement them - on Android these
calls throw an unavailable-method error. Use initAndStartTracking to start tracking.
Example screen
After adding src/TrackingSdk.ts and src/trackingPermissions.ts, this minimal App.tsx starts,
stops and checks tracking. Replace 'driver-001' with the authenticated user's identifier. It uses
SDK-managed authentication.
import React, {useRef, useState} from 'react';
import {Alert, Button, Text, View} from 'react-native';
import {
getDeviceHealth,
getTrackingState,
initAndStartTracking,
stopTracking,
} from './src/TrackingSdk';
import {requestTrackingPermissions} from './src/trackingPermissions';
export default function App() {
const [busy, setBusy] = useState(false);
const [status, setStatus] = useState('Not checked');
const actionRunning = useRef(false);
async function run(action: () => Promise<void>) {
if (actionRunning.current) {
return;
}
actionRunning.current = true;
setBusy(true);
try {
await action();
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
Alert.alert('Tracking error', message);
} finally {
actionRunning.current = false;
setBusy(false);
}
}
async function start() {
if (!(await requestTrackingPermissions())) {
setStatus('Permissions required — grant access, then retry');
return;
}
await initAndStartTracking('driver-001', false, null, 50);
setStatus((await getTrackingState()) ? 'Tracking active' : 'Tracking inactive');
}
async function stop() {
await stopTracking();
setStatus('Tracking stopped');
}
async function checkHealth() {
const health = await getDeviceHealth();
Alert.alert(
'Device health',
health ? JSON.stringify(health, null, 2) : 'Health unavailable',
);
}
return (
<View>
<Text>{status}</Text>
<Button title="Start" disabled={busy} onPress={() => void run(start)} />
<Button title="Stop" disabled={busy} onPress={() => void run(stop)} />
<Button
title="Check device health"
disabled={busy}
onPress={() => void run(checkHealth)}
/>
</View>
);
}
For a fuller UI flow, see src/screens/DutyTrackingScreen.tsx in the
sample app.
Saved status vs. live state
The saved status is a local snapshot, not proof that tracking is running or that a location reached the server:
import {getSavedTrackingStatus, getTrackingState} from './src/TrackingSdk';
const saved = await getSavedTrackingStatus();
const username = saved.username ?? '';
const active = await getTrackingState();
// Use saved data to restore UI context; use active to display queried state.
The wrapper's false fallback cannot distinguish an inactive SDK from a query error. If you need
that distinction, inspect the native error or adapt the wrapper to propagate it.
Lifecycle rules
- Call from the foreground. Initialize, start, stop and state operations bind to the current Android activity. Call them while the app is visible, not from a headless task.
- Recheck on relaunch. Check state and permissions before deciding to initialize again. The bridge does not itself restart tracking after process death or reboot - verify any such SDK behaviour on devices rather than inferring it from the saved flag.
- Stop explicitly. For end-of-duty or logout,
await stopTracking()before completing the action. Navigating away from a screen is not a stop request, and native module invalidation does not stop tracking either. - Stopping tracking leaves the saved username in local storage.
Device health
getDeviceHealth() reports the following flags. The bridge only reports them - it does not change
device settings. Treat them as diagnostics, not automatically as fatal startup errors.
| Field | Meaning |
|---|---|
locationPermissionOff | Location permission is unavailable |
preciseLocationOff | Precise location is unavailable |
backgroundLocationPermissionOff | Background location permission is unavailable |
locationServiceOff | Device location services are off |
batteryOptimizationEnabled | Battery optimization is enabled |
motionActivityDisabled | Motion / activity recognition is disabled |
autoStartManagementAvailable | The device has an auto-start management mechanism |
autoStartStatus | UNKNOWN or NOT_APPLICABLE - not confirmation that auto-start is enabled |
See also: Troubleshooting.