Skip to Content
🚀 Getting Startedinstalling-widget

Last Updated: 6/9/2026


Installing the Widget

Add the ZCal Buddy widget to your Android home screen to view your Zoom calendar events at a glance. The widget provides two view modes—agenda list and single-day timeline—and auto-refreshes every 15 minutes to keep your schedule current.

Prerequisites

  • ZCal Buddy app installed
  • Zoom account connected (see OAuth Setup & Connecting Zoom)
  • At least one calendar synced to the app
  • Available space on your home screen

Adding the Widget to Your Home Screen

Step 1: Access Widget Picker

Long-press on an empty area of your Android home screen. Your device displays the home screen customization menu with options like Wallpapers, Widgets, and Settings.

Tap Widgets to open the widget picker. This shows all available widgets from installed apps.

Step 2: Find ZCal Buddy Widget

Scroll through the widget list to find ZCal Buddy or Zoom Calendar. The widget is registered in the app’s AndroidManifest.xml as ZoomCalendarWidgetReceiver:

<receiver android:name=".widget.ZoomCalendarWidgetReceiver" android:exported="false"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/zoom_calendar_widget_info" /> </receiver>

The widget appears with a preview showing the calendar layout.

Step 3: Choose Widget Size

Long-press the ZCal Buddy widget preview and drag it to your home screen. Most Android launchers allow you to resize the widget by dragging the corner handles.

Recommended sizes:

  • 4x2 cells: Compact view showing 2-3 events
  • 4x3 cells: Standard view showing 4-6 events
  • 4x4 cells: Extended view showing 6-8 events
  • Full screen: Timeline view showing hourly schedule

Larger sizes work better for timeline mode, while smaller sizes suit agenda list mode.

Step 4: Place the Widget

Release your finger to place the widget on the home screen. The widget immediately loads and displays your calendar events using the default settings.

The widget’s provideGlance function fetches settings and events:

override suspend fun provideGlance(context: Context, id: GlanceId) { val settings = WidgetSettingsRepository.getSettings(context) val allEvents = CalendarRepository.getEvents(context) val filteredEvents = CalendarRepository.filterEventsForWidget( events = allEvents, settings = settings ) provideContent { WidgetContent(context, settings, filteredEvents) } }

Step 5: Verify Widget Display

Check that the widget shows your calendar events. You should see:

  • Today’s date in the header (formatted as “EEE, MMM d”, e.g., “Mon, Jan 15”)
  • Three action buttons: refresh (↻), settings (⚙), and create (+)
  • Your upcoming events with titles, times, and colors
  • “Join” buttons on events with Zoom meeting links

If the widget shows “Connect Zoom to sync your calendar,” you need to complete the OAuth setup first.

Understanding Widget View Modes

The widget automatically chooses between two view modes based on your settings:

Agenda List Mode

When it activates: Default mode, or when daysToDisplay > 1, or when daysToDisplay == 1 && agendaViewForSingleDay == true.

What it shows: Events grouped by day with day headers. The AgendaList composable builds rows using buildAgendaRows:

for (i in 0 until settings.daysToDisplay.coerceIn(1, 7)) { val dayCalendar = Calendar.getInstance().apply { add(Calendar.DAY_OF_YEAR, i) } val key = keyFormatter.format(dayCalendar.time) val title = titleFormatter.format(dayCalendar.time) val dayEvents = events.filter { it.dateKey == key }.sortedBy { it.startMillis } // ... add day header and event cards }

Best for: Viewing multiple days at once, scanning your week ahead, or smaller widget sizes.

Single Day Timeline Mode

When it activates: When daysToDisplay == 1 && agendaViewForSingleDay == false.

What it shows: Today’s events in a timeline with hour markers from 0-23. The SingleDayTimeline composable displays:

  • Hour labels (12 AM, 1 AM, … 11 PM)
  • Quarter-hour marks (small lines at :15, :30, :45)
  • Events positioned at their start times
  • A red “now” indicator showing the current time

The timeline uses buildSingleDayRows to create hour markers and position events:

for (hour in 0..23) { val hourEvents = timedEvents.filter { event -> Calendar.getInstance().apply { timeInMillis = event.startMillis }.get(Calendar.HOUR_OF_DAY) == hour } // ... add hour markers and events }

Best for: Detailed view of today’s schedule, larger widget sizes, or when you want a visual timeline.

Widget Display Features

Event Cards

Each event displays as a colored card with:

  • Event title: Bold text, or “(No title)” if blank
  • Event time: Formatted time range
  • Color coding: Based on calendar color from event.colorHex
  • Join button: Blue “Join” button for events with Zoom URLs
  • Visual states:
    • Solid fill: Accepted events (selfResponseStatus == "accepted" or "tentative")
    • Hollow outline: Declined events (selfResponseStatus == "declined")
    • Muted colors: Past events (event.endMillis < System.currentTimeMillis())
    • Strikethrough: Declined events show ”━━━━ Title ━━━━“

Header Actions

The widget header provides three buttons:

Refresh (↻): Triggers WidgetRefreshAction callback to manually refresh the widget. This fetches the latest events from local storage and updates the display.

Settings (⚙): Opens MainActivity with screen = "settings" intent extra. This launches the app’s settings screen where you can configure widget display options.

Create (+): Opens MainActivity with screen = "create_event" intent extra. This launches the event creation screen.

Empty State

If you have no events for the displayed period, the widget shows a placeholder card with the text from settings.noMoreEventsPlaceholder (default: “No more events”). This appears in agenda mode when a day has no events and in timeline mode when today has no events.

Automatic Widget Refresh

The widget auto-refreshes every 15 minutes via WorkManager. This is configured in MainActivity.scheduleWidgetRefresh():

private fun scheduleWidgetRefresh() { val workRequest = PeriodicWorkRequestBuilder<WidgetUpdateWorker>( 15, TimeUnit.MINUTES ).build() WorkManager.getInstance(this).enqueueUniquePeriodicWork( "zoom_widget_refresh", ExistingPeriodicWorkPolicy.UPDATE, workRequest ) }

The WidgetUpdateWorker runs in the background to fetch fresh calendar data from Zoom’s API and update all widget instances. This ensures your schedule stays current without manual intervention.

You can also manually refresh anytime by tapping the refresh button (↻) in the widget header.

Interacting with Widget Events

Viewing Event Details

Tap any event card to open the event details screen in the app. The widget passes event data via intent extras:

Intent(context, MainActivity::class.java).apply { putExtra("screen", "event_details") putExtra("event_id", event.eventId) putExtra("event_calendar_id", event.calendarId) putExtra("event_title", event.title) putExtra("event_time", event.time) // ... more event data }

The details screen shows full event information including location, description, attendees, and RSVP options.

Joining Zoom Meetings

Tap the blue Join button on any event with a Zoom URL. The widget creates an intent to open the Zoom app:

Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply { setPackage("us.zoom.videomeetings") }

If the Zoom app is installed, it opens directly to the meeting. If not installed, the system prompts you to install it from the Play Store.

Opening Zoom App

Tap the date in the widget header to open the Zoom app. The widget checks if Zoom is installed using context.packageManager.getLaunchIntentForPackage("us.zoom.videomeetings"). If not found, it opens the Zoom website at https://zoom.us.

Troubleshooting Widget Issues

Widget shows “Connect Zoom to sync your calendar”

The app doesn’t have valid Zoom credentials. Open the app and tap Connect Zoom to complete OAuth authentication.

Widget is blank or not updating

Try these steps:

  1. Tap the refresh button (↻) in the widget header
  2. Open the app to trigger a sync
  3. Remove and re-add the widget
  4. Check that background data is enabled for ZCal Buddy in Android settings

Events not appearing in widget

Check widget settings:

  1. Tap the settings button (⚙) in the widget header
  2. Verify your calendars are selected in the calendar filter
  3. Ensure “Days to display” is set to 1 or higher
  4. Check that “Show empty days” is enabled if you want to see days without events

Widget shows wrong time zone

The widget uses your device’s system time zone. Events are converted from their stored time zone to your local time zone for display. Check your device’s date & time settings if times appear incorrect.

What’s Next

Now that your widget is installed and displaying events, learn how to create new calendar events with Zoom meetings. See Creating Calendar Events for detailed instructions on event creation and meeting configuration.