Skip to main content
Aero provides Android home screen widgets that display live flight information and update automatically in the background.
iOS widgets are not yet supported. This documentation covers Android widgets only.

Current flight widget

The current flight widget displays real-time information about your active flight directly on your home screen.

Widget features

Auto-updates

Refreshes every 15 minutes while flight is active

Live status

Shows delays, early departures, and on-time status

Flight details

Displays times, airports, gates, and terminals

Smart expiry

Automatically clears 1 hour after landing

Adding a widget

Add the current flight widget to your home screen:
1

Long-press home screen

Long-press an empty area on your Android home screen to enter widget mode.
2

Open widget picker

Tap “Widgets” to open the widget selection screen.
3

Find Aero

Scroll through the widget list to find “Aero”. You’ll see the “Current Flight” widget option.
4

Add to home screen

Long-press the “Current Flight” widget and drag it to your desired location on the home screen.
5

Track a flight

Open the Aero app and search for any flight. When you view a flight, it automatically syncs to the widget.
The widget will display a placeholder message until you track a flight in the app.

Widget information

Displayed data

When a flight is active, the widget shows:
  • Airline logo: SVG or PNG logo from the airline database
  • Flight number: Both IATA (e.g., 6E1045) and ICAO formats
  • Destination: Arrival airport name
  • Airport codes: Departure and arrival IATA codes (e.g., DEL → BOM)
  • Departure time: Local time at departure airport
  • Arrival time: Local time at arrival airport
  • Status indicators:
    • Delay badges (red) when >5 minutes late
    • Early badges (green) when >5 minutes early
    • Separate indicators for departure and arrival

Widget layout

The widget is defined in android/app/src/main/res/xml/current_active_flight.xml and implemented by CurrentActiveFlightReceiver in Kotlin. Widget dimensions:
  • Minimum width: 3 cells (180dp)
  • Minimum height: 2 cells (110dp)
  • Resize mode: Horizontal and vertical
  • Update period: 15 minutes

Automatic updates

Background sync

The widget uses WorkManager to update automatically:
// From lib/main.dart
await Workmanager().registerPeriodicTask(
  'widget-update',
  'widgetUpdateTask',
  frequency: const Duration(minutes: 15),
  constraints: Constraints(
    networkType: NetworkType.connected,
  ),
);
The WidgetUpdateService (lib/services/widget_update_service.dart) handles:
  1. Checking for active flights: Reads flight metadata from widget storage
  2. Fetching updates: Calls the Aero API with forceUpdate=true
  3. Updating widget data: Saves new information using home_widget
  4. Triggering refresh: Notifies Android to redraw the widget

Update conditions

Widgets only update when:
  • ✅ Device has internet connection (WiFi or cellular)
  • ✅ Flight is stored in widget data
  • ✅ Flight arrival time hasn’t passed by >1 hour
  • ✅ WorkManager is allowed to run background tasks

Smart expiry

The widget automatically clears when:
  • Flight has landed >1 hour ago
  • Flight data becomes invalid
  • User manually clears the flight
This prevents stale information from appearing on your home screen.

Widget implementation

Data flow

Here’s how flight data flows to the widget:
1

User views flight

When you view a flight in the app, WidgetUpdateService.updateWidgetWithFlight() is called.
2

Data saved to widget storage

Flight information is saved using the home_widget package:
await HomeWidget.saveWidgetData('airline_logo', airlineLogo);
await HomeWidget.saveWidgetData('flight_number_iata', flightNumberIata);
await HomeWidget.saveWidgetData('destination', destinationName);
// ... more fields
3

Widget receives update

Android is notified to update the widget:
await HomeWidget.updateWidget(
  androidName: 'CurrentActiveFlightReceiver',
  qualifiedAndroidName:
    "fyi.procrastinator.aero.widgets.current_active_flight.CurrentActiveFlightReceiver"
);
4

Background task scheduled

WorkManager schedules periodic updates every 15 minutes.
5

Automatic refresh

Every 15 minutes, WidgetUpdateService.updateWidget() fetches fresh data from the API and updates the widget.

Stored widget data

The following data is stored for widget updates:
KeyDescriptionExample
flight_idFlightAware IDUAE-54-1709812800
flight_iataIATA flight number6E1045
flight_icaoICAO flight numberIGO1045
flight_dateFlight date (ISO 8601)2024-03-01T00:00:00.000Z
airline_logoLogo URLhttps://...
destinationArrival airport nameChhatrapati Shivaji International Airport
departure_airport_codeDeparture IATADEL
arrival_airport_codeArrival IATABOM
departure_time_localLocal departure time14:30
arrival_time_localLocal arrival time16:45
is_delay_in_departureDeparture delayed?true / false
is_delay_in_arrivalArrival delayed?true / false
is_expedite_in_departureDeparture early?true / false
is_expedite_in_arrivalArrival early?true / false
arrival_time_scheduledFor expiry check2024-03-01T16:45:00.000Z
All data is stored in SharedPreferences via the home_widget package.

Delay and early indicators

Delay detection

Flights are considered delayed when estimated/actual time is >5 minutes later than scheduled:
static bool _isDelayed(String? scheduledTime, String? estimatedTime) {
  if (scheduledTime == null || estimatedTime == null) return false;
  
  final scheduled = DateTime.parse(scheduledTime);
  final estimated = DateTime.parse(estimatedTime);
  final diff = estimated.difference(scheduled);
  return diff.inMinutes > 5;
}

Early detection

Flights are considered expedited when estimated/actual time is >5 minutes earlier than scheduled:
static bool _isExpedited(String? scheduledTime, String? estimatedTime) {
  if (scheduledTime == null || estimatedTime == null) return false;
  
  final scheduled = DateTime.parse(scheduledTime);
  final estimated = DateTime.parse(estimatedTime);
  final diff = scheduled.difference(estimated);
  return diff.inMinutes > 5;
}

Visual indicators

The widget displays status with color-coded badges:
  • 🔴 Red badge: “X min late” when delayed
  • 🟢 Green badge: “X min early” when expedited
  • No badge: On time (within 5-minute threshold)
Separate indicators appear for departure and arrival times.

Time formatting

Times are displayed in the local timezone of each airport:
static String _formatTime(String? timeString, {String? timezone}) {
  if (timeString == null || timeString.isEmpty) return '--:--';
  
  final dateTime = DateTime.parse(timeString);
  
  if (timezone != null && timezone.isNotEmpty) {
    return dateTime.toTimezoneString(timezone, use24Hrs: true);
  }
  
  return DateFormat('HH:mm').format(dateTime);
}
This ensures departure time shows in departure airport’s timezone and arrival time shows in arrival airport’s timezone.

Troubleshooting

Widget not updating

If your widget isn’t updating automatically:
1

Check background data

Go to Android Settings → Apps → Aero → Mobile data & WiFi → Background data. Ensure it’s enabled.
2

Disable battery optimization

Go to Settings → Apps → Aero → Battery → Unrestricted. This allows WorkManager to run.
3

Verify internet connection

The widget requires an active internet connection to fetch updates. Check WiFi or cellular data.
4

Re-add the widget

Remove the widget from your home screen and add it again. Then view a flight in the app.

Widget shows old flight

If the widget displays a previous flight:
  1. Open the Aero app
  2. Search for and view your current flight
  3. The widget will update within 1 minute
  4. Background updates continue every 15 minutes

Widget is blank

A blank widget means no flight is currently tracked:
  1. Open the Aero app
  2. Search for any flight
  3. View the flight details
  4. The widget will populate automatically

Widget won’t clear after landing

The widget should auto-clear 1 hour after landing. If it doesn’t:
  1. View a different flight in the app (replaces widget data)
  2. Or wait for the next background update (up to 15 minutes)
  3. Or remove and re-add the widget

Widget permissions

The widget requires these Android permissions (automatically granted):
<uses-permission android:name="android.permission.INTERNET" />
No additional permissions needed. The widget receiver is declared in AndroidManifest.xml:
<receiver
    android:name=".widgets.current_active_flight.CurrentActiveFlightReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/current_active_flight" />
</receiver>

Future widget types

Planned widgets for future releases:
  • Compact flight widget: Smaller 2×1 widget with minimal info
  • Next flight widget: Shows your next upcoming flight
  • Airport status widget: Live status of a specific airport
  • Multi-flight widget: Track up to 3 flights simultaneously
Stay tuned for updates! See Customization for app icon and theme settings.

Build docs developers (and LLMs) love