An Expo module for Android's Notification.ProgressStyle (API 36+), enabling rich progress-based notifications with visual segments, icons, and tracking indicators.
├── app/ # Example app
│ └── index.tsx # Demo UI for testing notifications
├── modules/
│ └── progress-centric-notifications/
│ ├── android/ # Native Kotlin implementation
│ ├── src/ # TypeScript module interface
│ └── plugin/ # Expo config plugin for icons
└── assets/notification-icons/ # Notification icon assets
The module exposes these functions from modules/progress-centric-notifications/index.ts:
// Permission handling
requestPermissionsAsync(): Promise<PermissionResponse>
getPermissionsAsync(): Promise<PermissionResponse>
useNotificationPermissions() // React hook
// Channel management
setChannel(channelId: string, options: ChannelOptions): Promise<void>
// Notification lifecycle
present(channelId: string, notificationId: string, config: NotificationConfig): Promise<void>
dismiss(notificationId: string): Promise<void>
dismissAll(): Promise<void>ChannelOptions
{
name: string // Channel name shown in settings
description?: string // Channel description
importance?: 'default' | 'high' | 'low' | 'min'
}NotificationConfig
{
// Content
title: string
message?: string
subText?: string
shortCriticalText?: string // API 36+ only
// Icons (drawable resource names)
smallIcon?: string
largeIcon?: string
// Time
when?: number // Timestamp in ms (e.g., ETA)
showWhen?: boolean
// Behavior
isOngoing?: boolean
onlyAlertOnce?: boolean
autoCancel?: boolean
url?: string // Deep link on tap
// Action buttons
actions?: { title: string, url: string, icon?: string }[]
// Progress bar (API 36+ only)
progressStyle?: ProgressStyleConfig
}ProgressStyleConfig
{
progress?: number // 0-100
isIndeterminate?: boolean
styledByProgress?: boolean
// Icons
trackerIcon?: string // Moving indicator
startIcon?: string // Origin icon
endIcon?: string // Destination icon
// Visual segments
segments?: { length: number, color: string }[]
points?: { position: number, color: string }[]
}The Kotlin module is in android/src/main/java/expo/modules/progresscentricnotifications/:
| File | Purpose |
|---|---|
ProgressCentricNotificationsModule.kt |
Main module with permission handling, channel creation, notification building |
NotificationConfig.kt |
Record class for notification configuration |
ChannelOptions.kt |
Record class for channel settings + importance enum |
ProgressStyleConfig.kt |
Record class for progress bar configuration |
ProgressPoint.kt / ProgressSegment.kt |
Progress bar visual elements |
Key native features:
- Uses
Notification.ProgressStylefor rich progress UI (API 36+) - Tag-based notification identification (
notify(tag, 0, notification)) - Fallback channel creation if specified channel doesn't exist
- Automatic
requestPromotedOngoingfor lock screen visibility - Deep linking via
PendingIntentwith URL or app launch
The plugin in plugin/src/withNotificationIcons.ts handles icon processing:
- Reads PNG icons from configured asset folders
- Scales to all Android DPI buckets (mdpi → xxxhdpi)
- Validates Android resource naming (lowercase + underscore only)
- Copies to
android/app/src/main/res/drawable-*folders
Icon sizes (base dp):
| Type | Base Size | Usage |
|---|---|---|
| small | 24dp | Status bar icon |
| large | 64dp | Notification panel |
| tracker | 40dp | Moving progress indicator |
| start/end | 36dp | Progress bar endpoints |
The demo app in app/index.tsx simulates a food delivery tracking flow:
- Permission requesting via
useNotificationPermissionshook - Channel setup with
setChannel - 5-stage delivery progression with
present - Deep linking with custom URL scheme
- Progress bar with colored segments and icons
1. Order Received (10%) → Kitchen initialization
2. Cooking (30%) → Food preparation
3. Out for Delivery (60%) → Driver en route (shows tracker)
4. Almost There (85%) → Near destination (shows tracker)
5. Delivered (100%) → Complete
- Permission - Status display and request button
- Channel - Shows if notification channel is ready
- Quick Actions - "Run Full Demo" auto-cycles all stages, "Dismiss" clears notification
- Manual Stages - Individual buttons for each delivery state
- Info - Channel ID, notification ID, deep link URL
const CHANNEL_ID = "delivery";
const NOTIFICATION_ID = "order-123";
const APP_SCHEME = "androidprogresscentricnotificationsexpo";# Install dependencies
pnpm install
# Run on Android
pnpm androidThe app requires Android API 36+ for ProgressStyle features. On older APIs, notifications work but without the rich progress bar UI.