Data Persistence API
Tracelet guarantees data delivery by using an offline-first architecture. Every location coordinate, activity change, and geofence event is written instantly to an encrypted local SQLite database.
While Tracelet’s Sync engine automatically reads and deletes data from this database, you have full manual control over the persistent store.
1. Querying Locations
You can extract the raw, un-synced locations currently sitting in the SQLite database.
// Get ALL locations currently stored in the database
final locations = await tl.Tracelet.getLocations();
for (final loc in locations) {
print('Location: \${loc.coords.latitude}, \${loc.coords.longitude}');
}Advanced SQL Queries
You don’t have to fetch everything. Tracelet exposes a SQLQuery object that allows you to filter the database exactly like standard SQL.
// Get only the locations recorded on a specific date
final query = tl.SQLQuery(
where: "timestamp >= ? AND timestamp <= ?",
whereArgs: ["2024-01-01T00:00:00Z", "2024-01-01T23:59:59Z"],
limit: 100,
order: "timestamp DESC"
);
final specificLocations = await tl.Tracelet.getLocations(query);2. Counting Records
If you just need to know how many locations are backlogged (e.g., to show an “Offline Sync Queue” badge in your UI), use getCount(). It is highly optimized and doesn’t load the records into memory.
// Count total un-synced locations
final count = await tl.Tracelet.getCount();
print('Pending locations to sync: \$count');
// You can also use SQL queries here
final highAccuracyCount = await tl.Tracelet.getCount(
tl.SQLQuery(where: "accuracy <= 20")
);3. Inspecting the Offline Queue
Because Tracelet prunes each record the moment it is confirmed synced, every location still in the database is — by definition — pending upload. The pending-queue helpers make this explicit, which is ideal for showing a “waiting to sync” badge, building an audit view, or diagnosing connectivity.
// The locations still waiting to be delivered to your backend.
final pending = await tl.Tracelet.getPendingLocations();
// Just the queue depth (optimized — no records are loaded into memory).
final pendingCount = await tl.Tracelet.getPendingLocationCount();
print('Offline queue: \$pendingCount location(s) waiting to sync');Both accept an optional SQLQuery for time-range filtering, exactly like getLocations() / getCount().
4. Destroying Data
If the user logs out, or explicitly deletes their account, you must destroy their location history to comply with GDPR/HIPAA.
Destroy All
This wipes the location database completely clean.
await tl.Tracelet.destroyLocations();Destroy Specific Location
You can destroy a single, specific location if you know its UUID.
Where do you get the UUID?
Every location generated by Tracelet is automatically assigned a unique uuid. You can get this ID by calling getLocations() and reading the uuid property on the Location object.
final locations = await tl.Tracelet.getLocations();
if (locations.isNotEmpty) {
final firstLocationId = locations.first.uuid;
// Destroy just this specific location from the database
await tl.Tracelet.destroyLocation(firstLocationId);
}Destroy Synced
Typically Tracelet automatically deletes locations after it receives an HTTP 200 OK from your server. However, if you are doing manual syncing, you can trigger this cleanup manually.
await tl.Tracelet.destroySyncedLocations();