Skip to main content

Flutter SDK Usage & Integration

Learn how to initialize the DoorstepAI SDK and integrate delivery tracking into your Flutter application.

SDK Initialization

Basic Setup with DoorstepAiView Widget

The easiest way to initialize the SDK is using the DoorstepAiView widget, which handles initialization and permission requests automatically:

main.dart
import 'package:flutter/material.dart';
import 'package:doorstepai_dropoff_sdk/doorstepai_dropoff_sdk.dart';
import 'package:doorstepai_dropoff_sdk/doorstep_ai_view.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: DoorstepAiView(
apiKey: 'your-api-key',
notificationTitle: 'Tracking...',
notificationText: 'Tracking your delivery',
),
),
);
}
}
API Key Security

Store your API key securely using environment variables, secure storage, or a configuration service. Never hardcode API keys in production builds.

Manual Initialization

For more control over the initialization process, you can initialize the SDK manually:

delivery_manager.dart
import 'package:flutter/foundation.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:doorstepai_dropoff_sdk/doorstepai_dropoff_sdk.dart';

class DeliveryManager {
static Future<void> initializeSDK() async {
// Initialize SDK first
await DoorstepAI.init(
notificationTitle: 'Tracking...',
notificationText: 'Tracking your delivery',
);

// Set API key after initialization
await DoorstepAI.setApiKey('your-api-key');

// Request permissions on Android
if (defaultTargetPlatform == TargetPlatform.android) {
await _requestAndroidPermissions();
}
}

static Future<void> _requestAndroidPermissions() async {
final permissions = {
Permission.location: 'Location',
Permission.activityRecognition: 'Activity Recognition',
};

// Request permissions sequentially
Map<Permission, PermissionStatus> results = {};
for (var entry in permissions.entries) {
final permission = entry.key;
final name = entry.value;
final status = await permission.request();
results[permission] = status;
}

if (results.values.every((status) => status.isGranted)) {
print('✅ Required Android permissions granted');
} else {
print('❌ One or more required Android permissions denied');
}
}
}

Initialization Parameters

ParameterTypeDescriptionRequired
apiKeyStringYour DoorstepAI API keyRequired
notificationTitleString?Title for tracking notificationsRequired
notificationTextString?Description for tracking notificationsRequired
Notification Customization

The notification title and text are used for the foreground service notification that appears when the SDK is actively tracking deliveries. These parameters are required for proper SDK initialization.

Core Functionality

Delivery IDs

Delivery IDs are designed to be unique identifiers for each delivery session. Use meaningful, unique identifiers that help you track and manage your deliveries effectively.

Starting Delivery Tracking

The SDK provides multiple methods to start delivery tracking based on different address formats:

1. Start by Place ID

import 'package:doorstepai_dropoff_sdk/doorstepai_dropoff_sdk.dart';

Future<void> startDeliveryByPlaceID() async {
try {
await DoorstepAI.startDeliveryByPlaceID(
placeID: 'some_place_id',
deliveryId: 'delivery_12345',
);
print('✅ Delivery started successfully');
} catch (error) {
print('❌ Failed to start delivery: $error');
}
}

2. Start by Plus Code

Future<void> startDeliveryByPlusCode() async {
try {
await DoorstepAI.startDeliveryByPlusCode(
plusCode: 'some_plus_code',
deliveryId: 'delivery_12345',
);
print('✅ Delivery started with Plus Code');
} catch (error) {
print('❌ Plus Code delivery failed: $error');
}
}

3. Start by Address Components

Future<void> startDeliveryByAddress() async {
try {
final address = AddressType(
streetNumber: '123',
route: 'Main Street',
subPremise: 'Apt 4B',
locality: 'San Francisco',
administrativeAreaLevel1: 'CA',
postalCode: '94102',
);

await DoorstepAI.startDeliveryByAddress(
address: address,
deliveryId: 'delivery_12345',
);
print('✅ Address delivery started');
} catch (error) {
print('❌ Address delivery failed: $error');
}
}

Delivery Events

Track important delivery milestones using event reporting:

Send Custom Events

Future<void> sendDeliveryEvent(String deliveryId) async {
try {
await DoorstepAI.newEvent(
eventName: 'driver_arrived',
deliveryId: deliveryId,
);
print('✅ Event sent: driver_arrived');
} catch (error) {
print('❌ Failed to send event: $error');
}
}

Stop Delivery Tracking

Future<void> stopDelivery(String deliveryId) async {
try {
await DoorstepAI.stopDelivery(deliveryId: deliveryId);
print('✅ Delivery stopped successfully');
} catch (error) {
print('❌ Failed to stop delivery: $error');
}
}

SDK Methods Reference

Authentication

MethodParametersDescription
setApiKeyString keySet your DoorstepAI API key
await DoorstepAI.setApiKey('your-api-key');

Delivery Management

MethodParametersDescription
startDeliveryByPlaceIDString placeID, String deliveryIdStart delivery tracking using Google Place ID
startDeliveryByPlusCodeString plusCode, String deliveryIdStart delivery tracking using Plus Code
startDeliveryByAddressAddressType address, String deliveryIdStart delivery tracking using address components
newEventString eventName, String deliveryIdSend custom event for active delivery
stopDeliveryString deliveryIdStop delivery tracking

Address Type

class AddressType {
final String streetNumber;
final String route;
final String? subPremise;
final String locality;
final String administrativeAreaLevel1;
final String postalCode;

AddressType({
required this.streetNumber,
required this.route,
this.subPremise,
required this.locality,
required this.administrativeAreaLevel1,
required this.postalCode,
});
}

DoorstepAiView Widget

The DoorstepAiView widget provides a Flutter wrapper for the native iOS SwiftUI view and handles initialization automatically.

Basic Usage

DoorstepAiView(
apiKey: 'your-api-key',
notificationTitle: 'Tracking...',
notificationText: 'Tracking your delivery',
)

Advanced Usage

class DeliveryScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Delivery Tracking')),
body: Column(
children: [
// Your delivery UI
Expanded(
child: DoorstepAiView(
apiKey: 'your-api-key',
notificationTitle: 'Tracking',
notificationText: 'Tracking your delivery',
),
),
],
),
);
}
}

Best Practices

1. Error Handling

Always implement proper error handling for SDK methods:

Future<void> startDeliveryWithErrorHandling() async {
try {
await DoorstepAI.startDeliveryByPlaceID(
placeID: 'your-place-id',
deliveryId: 'unique-delivery-id',
);
// Handle success
} catch (error) {
// Handle error
print('Error: $error');
}
}

2. Lifecycle Management

Handle app lifecycle changes appropriately:

import 'package:flutter/material.dart';

class DeliveryManager extends StatefulWidget {
@override
_DeliveryManagerState createState() => _DeliveryManagerState();
}

class _DeliveryManagerState extends State<DeliveryManager> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}

@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.paused:
print('📱 App paused - SDK continues tracking in background');
break;
case AppLifecycleState.resumed:
print('📱 App resumed');
break;
default:
break;
}
}
}

3. Permission Handling

The DoorstepAiView component automatically handles permission requests, but you can also handle them manually:

import 'package:permission_handler/permission_handler.dart';
import 'package:flutter/foundation.dart';

Future<void> requestPermissions() async {
if (defaultTargetPlatform == TargetPlatform.android) {
final permissions = {
Permission.location: 'Location',
Permission.activityRecognition: 'Activity Recognition',
};

// Request permissions sequentially
Map<Permission, PermissionStatus> results = {};
for (var entry in permissions.entries) {
final permission = entry.key;
final name = entry.value;
final status = await permission.request();
results[permission] = status;
}

if (results.values.every((status) => status.isGranted)) {
print('✅ Required Android permissions granted');
} else {
print('❌ One or more required Android permissions denied');
}
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
print('📱 iOS: Ensure location and motion usage descriptions are in Info.plist');
}
}

Platform-Specific Notes

iOS

  • The DoorstepAiView widget renders the native SwiftUI view
  • Permissions are handled automatically by the system
  • Background location processing is supported

Android

  • The DoorstepAiView widget shows a placeholder (height: 0)
  • Manual permission requests are required
  • Background location requires ACCESS_BACKGROUND_LOCATION permission (API 29+)

Next Steps

  1. 💡 View Examples - See complete implementation examples
  2. 🛠️ Troubleshooting Guide - Solve common integration and runtime issues