droido 1.1.1 copy "droido: ^1.1.1" to clipboard
droido: ^1.1.1 copied to clipboard

Debug-only network inspector for Flutter. Supports Dio, HTTP, Retrofit. Modern UI, zero release impact.

๐Ÿค– Droido #

A lightweight, debug-only network inspector for Flutter apps. Supports Dio, HTTP package, and Retrofit. Features a clean, modern UI with persistent notification. Built with clean architecture principles and zero impact on release builds.

pub package License: MIT

โœจ Features #

  • ๐Ÿ“ก Multi-Client Support - Works with Dio, HTTP package, and Retrofit
  • ๐Ÿ”” Persistent Notification - Always-visible debug notification (debug mode only)
  • ๐ŸŽจ Modern UI - Clean white-theme interface with Material Design
  • ๐Ÿ” Search & Filter - Quickly find specific requests
  • ๐Ÿ“ค Export Options - Export as JSON, HAR, or CSV formats
  • ๐Ÿ”„ cURL Generation - Generate cURL commands for any request
  • ๐Ÿ“ฒ Share cURL - Share commands to any device via native share sheet
  • ๐ŸŒฒ Tree-Shakable - Zero footprint in release builds
  • ๐Ÿ“Š Detailed Metrics - Request time, response size, duration with color-coded indicators
  • ๐Ÿ—๏ธ Clean Architecture - SOLID principles, testable, maintainable

โœจ Demo #

Watch the latest walkthrough directly below:

๐Ÿ“ฆ Installation #

Add to your pubspec.yaml:

dependencies:
  droido: ^1.0.4
  dio: ^5.4.0     # If using Dio
  http: ^1.2.0    # If using HTTP package

Then run:

flutter pub get

Android Setup (Required) #

Add required permissions to android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Required for Android 13+ notifications -->
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    
    <application>
        <!-- Your existing configuration -->
    </application>
</manifest>

Note: On Android 13+, notification permission will be automatically requested when Droido initializes. Users will see a system permission dialog on first launch.

iOS Setup #

No additional setup required for iOS.

๐Ÿš€ Quick Start #

Using Dio #

import 'package:droido/droido.dart';
import 'package:dio/dio.dart';

final navigatorKey = GlobalKey<NavigatorState>();

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final dio = Dio();
  
  // Just pass navigatorKey - Droido handles notification tap automatically!
  await Droido.init(
    dio: dio,
    navigatorKey: navigatorKey,
  );

  runApp(MaterialApp(navigatorKey: navigatorKey, home: MyApp()));
}

Using HTTP Package #

import 'package:droido/droido.dart';
import 'package:http/http.dart' as http;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final rawClient = http.Client();
  
  await Droido.init(
    httpClient: rawClient,
    navigatorKey: navigatorKey,
  );
  
  // Get the wrapped client for requests
  final client = Droido.httpClient!;
  
  // Make requests - automatically logged!
  final response = await client.get(Uri.parse('https://api.example.com/data'));

  runApp(const MyApp());
}

Using Retrofit #

import 'package:droido/droido.dart';
import 'package:dio/dio.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final dio = Dio();
  
  await Droido.init(
    dio: dio,
    navigatorKey: navigatorKey,
  );
  
  // Create Retrofit client - requests are automatically intercepted!
  final apiClient = MyRetrofitClient(dio);

  runApp(const MyApp());
}

Using Multiple Clients #

// Initialize with both Dio and HTTP + auto navigation
await Droido.init(
  dio: dio,
  httpClient: httpClient,
  navigatorKey: navigatorKey,
  config: const DroidoConfig(
    maxLogs: 500,
    enableNotification: true,
  ),
);

// Both clients log to the same DroidoPanel!

Already Using flutter_local_notifications? #

If your app already uses flutter_local_notifications, just add one line to your existing handler:

_notificationsPlugin.initialize(
  initializationSettings,
  onDidReceiveNotificationResponse: (details) {
    if (Droido.handlePayload(details.payload)) return;  // โ† Add this line
    
    // Your existing notification handling code below...
    handleMyNotification(details);
  },
);

Then pass your plugin to avoid double-initialization:

await Droido.init(
  dio: dio,
  config: DroidoConfig(
    externalNotificationPlugin: _notificationsPlugin,
  ),
);

Droido.setNotificationCallback(() {
  navigatorKey.currentState?.push(
    MaterialPageRoute(builder: (_) => const DroidoPanel()),
  );
});

That's it! Both your notifications and Droido's notification will work correctly.

With Configuration #

await Droido.init(
  dio: dio,
  httpClient: httpClient,
  config: const DroidoConfig(
    maxLogs: 500,                      // Maximum logs to keep
    enableNotification: true,          // Show notification
    notificationTitle: 'Debug Active', // Notification title
    notificationOngoing: false,        // Set to false to allow dismissing (default: true)
    includeRequestHeaders: true,       // Log request headers
    includeResponseHeaders: true,      // Log response headers
    includeRequestBody: true,          // Log request body
    includeResponseBody: true,         // Log response body
    maxBodySize: 1048576,             // Max body size (1MB)
    autoClearOnRestart: false,        // Clear logs on restart
  ),
);

That's it! ๐ŸŽ‰ #

Droido automatically captures all network requests. Tap the notification to open the debug panel.

๐Ÿ“– API Reference #

Initialize #

// Dio only
await Droido.init(dio: dio);

// HTTP only
await Droido.init(httpClient: httpClient);

// Both clients
await Droido.init(dio: dio, httpClient: httpClient);

// With configuration
await Droido.init(
  dio: dio,
  config: const DroidoConfig(
    maxLogs: 1000,
    enableNotification: true,
  ),
);

HTTP Client Access #

// Get the wrapped HTTP client (for HTTP package users)
final client = Droido.httpClient;

// Use it for requests
final response = await client?.get(Uri.parse('https://api.example.com'));

Notification Callback #

// Set callback for notification tap
Droido.setNotificationCallback(() {
  // Your navigation logic
  navigatorKey.currentState?.push(
    MaterialPageRoute(builder: (_) => const DroidoPanel()),
  );
});

Access Logs #

// Get logs stream
Stream<List<NetworkLog>> stream = Droido.logsStream;

// Get current logs
List<NetworkLog> logs = Droido.logs;

// Get log count
int count = Droido.logCount;

Search & Filter #

// Search logs by URL, method, or status
List<NetworkLog> results = Droido.searchLogs('api/users');

Export Logs #

// Export as JSON
String json = Droido.exportAsJson();

// Export as HAR format
String har = Droido.exportAsHar();

// Export as CSV
String csv = Droido.exportAsCsv();

Generate cURL #

// Generate cURL command for a request
String curl = Droido.generateCurl(log);

Share cURL #

// Share cURL command via native share sheet
await Droido.shareCurl(log);

The share feature opens the platform's native share dialog, allowing you to send the cURL command to any app (messaging, email, notes, etc.).

Clear Logs #

// Clear all logs
await Droido.clearLogs();

Dispose #

// Dispose resources
await Droido.dispose();

๐Ÿ“ฑ UI Components #

DroidoPanel #

Main debug panel showing all network requests:

MaterialPageRoute(
  builder: (_) => const DroidoPanel(),
);

Features:

  • List of all network requests
  • Search functionality
  • Export options
  • Tap to view detailed request/response

Request Detail View #

Automatically shown when tapping a request card. Shows:

  • Request time, response size, and duration
  • Method and status code
  • Full URL with copy button
  • Request/Response headers and body
  • Formatted JSON display
  • Error messages (if any)

โš™๏ธ Configuration Options #

Option Type Default Description
maxLogs int 500 Maximum number of logs to keep in memory
enableNotification bool true Show persistent notification
notificationTitle String 'Debug Active' Notification title text
notificationOngoing bool true Make notification non-dismissable (persistent until app closed)
notificationChannelId String 'droido_debug_channel' Android notification channel ID
notificationChannelName String 'Droido Debug' Android notification channel name
includeRequestHeaders bool true Include request headers in logs
includeResponseHeaders bool true Include response headers in logs
includeRequestBody bool true Include request body in logs
includeResponseBody bool true Include response body in logs
maxBodySize int? 1048576 Maximum body size to log (bytes)
autoClearOnRestart bool false Clear logs when app restarts

๐ŸŽจ UI Highlights #

Modern Design #

  • Clean white theme with subtle shadows
  • Color-coded status indicators (2xx = green, 4xx = amber, 5xx = red)
  • Method-based coloring (GET = blue, POST = green, DELETE = red)
  • Performance indicators (fast = green, slow = red)

Metric Cards #

Each request displays:

  • โฑ Request time (HH:MM:SS)
  • ๐Ÿ“Š Response size (B/KB/MB)
  • โšก Duration (ms/s) with color coding

Detail View Tabs #

  • Overview: Key metrics and request details
  • Request: Headers and body
  • Response: Headers and body

๐Ÿ—๏ธ Architecture #

Droido follows Clean Architecture principles:

lib/
โ”œโ”€โ”€ droido.dart              # Public API
โ””โ”€โ”€ src/
    โ”œโ”€โ”€ core/               # Domain layer (pure Dart)
    โ”‚   โ”œโ”€โ”€ entities/      # Domain models
    โ”‚   โ”œโ”€โ”€ repositories/  # Abstract contracts
    โ”‚   โ””โ”€โ”€ usecases/      # Business logic
    โ”œโ”€โ”€ data/              # Data layer
    โ”‚   โ”œโ”€โ”€ repositories/  # Concrete implementations
    โ”‚   โ””โ”€โ”€ services/      # HTTP interceptors (Dio & HTTP)
    โ”œโ”€โ”€ presentation/      # Presentation layer
    โ”‚   โ”œโ”€โ”€ pages/        # UI screens
    โ”‚   โ”œโ”€โ”€ widgets/      # Reusable widgets
    โ”‚   โ””โ”€โ”€ theme/        # Design tokens
    โ””โ”€โ”€ di/                # Dependency injection

SOLID Principles #

  • Single Responsibility: Each class has one clear purpose
  • Open/Closed: Extensible through interfaces
  • Liskov Substitution: Interface-based design
  • Interface Segregation: Minimal, focused interfaces
  • Dependency Inversion: Depends on abstractions

๐Ÿ”’ Privacy & Security #

  • Debug Only: All functionality wrapped in kDebugMode checks
  • Tree-Shakable: Completely removed from release builds
  • No Analytics: Zero external data transmission
  • Local Storage: All data stays on device
  • No Permissions: Minimal permissions required (only notifications)

๐Ÿงช Testing #

Droido is designed to be no-op in release builds:

import 'package:droido/droido.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  test('Droido is no-op in release mode', () {
    // kDebugMode is false in tests
    expect(Droido.isInitialized, false);
    expect(Droido.logs, isEmpty);
  });
}

๐Ÿ“Š NetworkLog Model #

class NetworkLog {
  final String id;                           // Unique identifier
  final String url;                          // Request URL
  final String method;                       // HTTP method
  final DateTime timestamp;                  // Request time
  final Map<String, dynamic>? requestHeaders;
  final dynamic requestBody;
  final int? statusCode;                     // Response status
  final Map<String, dynamic>? responseHeaders;
  final dynamic responseBody;
  final int? durationMs;                     // Duration in milliseconds
  final String? errorMessage;                // Error if failed
  final StackTrace? stackTrace;              // Stack trace if error
  
  // Computed properties
  bool get isSuccessful;  // Status 200-299
  bool get isFailed;      // Status 400+
  bool get isPending;     // No response yet
  String get statusDescription;  // Human-readable status
  String get domain;      // Extracted domain
  String get path;        // URL path
}

๐Ÿ’ก Inspired By #

  • Chucker - Android HTTP inspector
  • Netfox - iOS network debugging
  • Alice - Flutter HTTP inspector

๐Ÿค Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

๐Ÿ“ License #

MIT License - see the LICENSE file for details.

๐Ÿ“ง Support #


Made with โค๏ธ for the Flutter community

15
likes
160
points
172
downloads

Publisher

verified publisherbrooky.in

Weekly Downloads

Debug-only network inspector for Flutter. Supports Dio, HTTP, Retrofit. Modern UI, zero release impact.

Repository (GitHub)
View/report issues

Topics

#debug #network #inspector #dio #logging

Documentation

API reference

License

MIT (license)

Dependencies

dio, flutter, flutter_local_notifications, freezed_annotation, http, intl, json_annotation, rxdart, share_plus

More

Packages that depend on droido