React Native SDK Examples & Troubleshooting
Quickstart
The address-string method keeps timeout and coordinates as positional arguments; delivery options are the fifth argument.
import { DoorstepAI } from '@doorstepai/dropoff-sdk';
await DoorstepAI.init('Tracking...', 'Tracking your delivery');
DoorstepAI.setApiKey('your_api_key');
const foreground = await DoorstepAI.requestPermissions([
'locationWhenInUse',
'motionFitness',
'bluetoothScan',
]);
if (foreground.statuses.locationWhenInUse?.state === 'granted') {
await DoorstepAI.requestPermissions(['locationAlways']);
}
await DoorstepAI.startDeliveryByAddressString(
'123 Main St, Apt 4B, San Francisco, CA 94102',
'delivery_12345',
1800,
{ lat: 37.7749, lng: -122.4194 },
{
customerId: 'customer_42',
driverId: 'driver_7',
},
);
await DoorstepAI.newEvent('taking_pod', 'delivery_12345');
await DoorstepAI.markDropoff('delivery_12345', 'pod');
await DoorstepAI.stopDelivery('delivery_12345');
Route-managed lifecycle
const listener = DoorstepAI.addGeofenceSessionListener((event) => {
console.log(event.deliveryId, event.type, event.reason);
});
await DoorstepAI.startRouteGeofencing(
[
{
deliveryId: 'delivery_12345',
address: '123 Main St, San Francisco, CA',
latitude: 37.7749,
longitude: -122.4194,
customerId: 'customer_42',
driverId: 'driver_7',
},
{
deliveryId: 'delivery_67890',
address: '500 Market St, San Francisco, CA',
latitude: 37.7899,
longitude: -122.4009,
radiusMeters: 200,
},
],
{
defaultRadiusMeters: 250,
timeoutSeconds: 1800,
manualForeground: false, // Android only
},
);
// Call when the driver completes the stop. A later EXIT can then stop it.
await DoorstepAI.markDropoff('delivery_12345', 'pod');
// On dispatch changes, pass the complete replacement list.
await DoorstepAI.updateRouteStops(updatedStops);
// At logout or shift end:
await DoorstepAI.stopRouteGeofencing();
listener?.remove();
Call resumeRouteGeofencingIfNeeded() after initialization and API-key setup on every launch. Background route events require Always/background location permission.
Permission-state handling
Use the wrapper's canonical buckets and detailed native states instead of branching on PermissionsAndroid strings:
const { statuses, unsupported } = await DoorstepAI.checkPermissions();
switch (statuses.locationAlways?.state) {
case 'granted':
break;
case 'whenInUseOnly':
// Explain the background need, then run the second permission phase.
await DoorstepAI.requestPermissions(['locationAlways']);
break;
case 'permanentlyDenied':
case 'restricted':
// Direct the user to the operating-system Settings screen.
break;
case 'notDeclared':
// Fix AndroidManifest.xml or Info.plist in the host build.
break;
}
console.log('Buckets unavailable on this platform:', unsupported);
The request result reports requested, alreadyDetermined, unavailable, and deferred, plus the settled statuses. On Android, locationAlways is always a separate request after foreground location. On iOS, request from a user-initiated flow rather than app launch.
See React Native Permissions for every accepted bucket name, detailed result field, Android-only helper, and the full staged flow.
Troubleshooting
SDK initialization fails
- Confirm
initcompletes beforesetApiKeyand before the first start. - Confirm the API key is present and belongs to the expected environment.
- Wrap each asynchronous call in
try/catchand log the rejected error.
A permission is unavailable or undeclared
unavailablemeans the OS, version, or hardware does not expose that bucket. Android-only Wi-Fi and notification buckets are expected to be unavailable on iOS.notDeclaredmeans the host build is missing an Android manifest entry or iOS usage-description key. Fix the build; prompting again cannot solve it.
Background tracking or route events stop
Check statuses.locationAlways.state. whenInUseOnly is foreground authorization, not a background grant. Also verify Android's foreground service is running, or pass manualForeground: true only when the host already owns one.
Start arguments fail TypeScript checks
Do not put coordinates into StartDeliveryOptions. For startDeliveryByAddressString, the order is (address, deliveryId, timeoutSeconds?, coordinates?, options?); place/address variants have their corresponding published positional signatures.
Release checklist
- Native manifests contain every permission your whitelist requests
- Foreground and background permission phases are tested on both platforms
- Manual start, event, mark, and stop calls succeed
- Route state resumes after process relaunch
- Listener subscriptions are removed during component teardown