Skip to content

Offline Mode Implementation ​

Phase 1 Offline Strategy ​

For your 1-2 month MVP: cached maps + risk zones + helplines. Full offline voice AI comes in a later phase (requires ~2GB on-device model).


What Works Offline ​

FeatureOffline SupportHow
Map display✅ YesCached OSM tiles (flutter_map_cache)
Risk zones✅ YesCached in SQLite, updated on connect
Helpline directory✅ YesBundled in app assets
Police/hospital list✅ YesCached in SQLite
Past reports✅ YesSQLite
Panic button (SMS)✅ YesWorks without internet
Voice AI agent❌ NoRequires OpenRouter API
News feed❌ NoRequires internet
Live places search❌ NoRequires Google Places API

Connectivity-Aware UI ​

dart
// lib/core/utils/connectivity_checker.dart

@riverpod
Stream<bool> isOnline(IsOnlineRef ref) async* {
  final connectivity = Connectivity();

  yield* connectivity.onConnectivityChanged.map((result) =>
    result != ConnectivityResult.none
  );
}

// In any widget:
class ConnectivityBanner extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final online = ref.watch(isOnlineProvider).valueOrNull ?? true;

    if (online) return const SizedBox.shrink();

    return Container(
      width: double.infinity,
      color: Colors.orange,
      padding: const EdgeInsets.symmetric(vertical: 6),
      child: const Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.wifi_off, color: Colors.white, size: 16),
          SizedBox(width: 8),
          Text(
            'অফলাইন মোড - সীমিত ফিচার উপলব্ধ',
            style: TextStyle(color: Colors.white, fontSize: 12),
          ),
        ],
      ),
    );
  }
}

Offline Map Tiles ​

dart
// lib/features/maps/services/tile_cache_service.dart

// flutter_map_cache handles this automatically.
// Pre-cache Dhaka area tiles on first launch:

Future<void> preCacheDhakaTiles() async {
  // Cache zoom levels 10-16 for Dhaka area
  // Approx bounding box: Dhaka metro area
  const bounds = LatLngBounds(
    LatLng(23.6850, 90.3350),  // SW
    LatLng(23.9050, 90.5050),  // NE
  );

  // Use flutter_map_cache to download tiles
  // Estimated size: ~50MB for zoom 10-16 Dhaka
  await TileCacheService.downloadArea(
    bounds: bounds,
    minZoom: 10,
    maxZoom: 16,
  );
}

Offline Queue - Submit When Back Online ​

dart
// When offline, store reports locally and sync when connected

class OfflineQueueService {
  final AppDatabase _db;
  final AgentService _agentService;

  Future<void> queueReport(CivicReport report) async {
    await _db.pendingReports.insertOne(
      PendingReport(
        id: const Uuid().v4(),
        reportJson: jsonEncode(report.toJson()),
        createdAt: DateTime.now(),
        synced: false,
      ),
    );
  }

  // Called when connectivity restored
  Future<void> syncPendingReports() async {
    final pending = await _db.pendingReports
      .filter((r) => r.synced.equals(false))
      .get();

    for (final item in pending) {
      try {
        final report = CivicReport.fromJson(
          jsonDecode(item.reportJson)
        );
        await _agentService.submitReport(report);
        await _db.pendingReports.filter(
          (r) => r.id.equals(item.id)
        ).delete();
      } catch (_) {
        // Will retry next time
      }
    }
  }
}
```\n\n
## Bit-by-Bit Implementation: Offline Capabilities

For users without internet, we must ensure basic functionality works.

### Step-by-Step Logic
1. **Map Tiles**: Use `flutter_map_cache`. When the user is on WiFi, the app downloads OpenStreetMap tiles for Dhaka (zoom levels 10-15). These are stored as `.png` files in the app's local directory.
2. **Local Database**: Use `sqlite3` (via the Drift package in Flutter). Store the polygons (coordinates) of known "Red Zones".
3. **Location Polling**: When offline, the app still gets GPS pings. It queries the local SQLite DB: `SELECT * FROM risk_zones WHERE ST_Contains(geom, user_location)`. If true, trigger a local notification.

## Alternative Approaches to Consider
1. **Google Maps SDK instead of flutter_map?**
   - *Pros*: Google Maps has higher quality POI data.
   - *Cons*: Google Maps SDK does not allow you to cache map tiles for true offline use without internet, and it costs money. `flutter_map` (OpenStreetMap) is 100% free and allows aggressive offline caching.

Documentation maintained by Dreams of X Team .