{"id":25995011,"url":"https://github.com/mantreshkhurana/app_updater","last_synced_at":"2026-02-12T14:20:32.085Z","repository":{"id":65685218,"uuid":"597334932","full_name":"mantreshkhurana/app_updater","owner":"mantreshkhurana","description":"App Updater for Flutter Apps, supporting Android, iOS, Window, macOS \u0026 Linux. Update them via official App Store or from custom url path.","archived":false,"fork":false,"pushed_at":"2023-05-28T13:31:36.000Z","size":472,"stargazers_count":16,"open_issues_count":2,"forks_count":1,"subscribers_count":3,"default_branch":"stable","last_synced_at":"2024-05-02T04:39:11.655Z","etag":null,"topics":["app-updater","app-version-checker","dart","flutter","flutter-app-updater"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/app_updater","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mantreshkhurana.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2023-02-04T08:05:55.000Z","updated_at":"2023-10-19T16:00:59.000Z","dependencies_parsed_at":"2023-02-18T15:01:25.379Z","dependency_job_id":null,"html_url":"https://github.com/mantreshkhurana/app_updater","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mantreshkhurana%2Fapp_updater","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mantreshkhurana%2Fapp_updater/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mantreshkhurana%2Fapp_updater/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mantreshkhurana%2Fapp_updater/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mantreshkhurana","download_url":"https://codeload.github.com/mantreshkhurana/app_updater/tar.gz/refs/heads/stable","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242048561,"owners_count":20063404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["app-updater","app-version-checker","dart","flutter","flutter-app-updater"],"created_at":"2025-03-05T15:18:11.373Z","updated_at":"2026-02-12T14:20:32.072Z","avatar_url":"https://github.com/mantreshkhurana.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# App Updater\n\n[![GitHub stars](https://img.shields.io/github/stars/mantreshkhurana/app_updater.svg?style=social)](https://github.com/mantreshkhurana/app_updater)\n[![pub package](https://img.shields.io/pub/v/app_updater.svg)](https://pub.dartlang.org/packages/app_updater)\n\nA comprehensive Flutter package to check for app updates and display platform-native dialogs. Supports iOS, Android, macOS, Windows, and Linux with adaptive UI for each platform.\n\n| Platform | Dialog Style |\n|----------|--------------|\n| iOS | ![iOS Dialog](./screenshots/ios-screenshot.png) |\n| Android | ![Android Dialog](./screenshots/android-screenshot.png) |\n| macOS | ![macOS Dialog](./screenshots/macos-screenshot.png) |\n| Windows | ![Windows Dialog](./screenshots/windows-screenshot.png) |\n| Linux | ![Linux Dialog](./screenshots/linux-screenshot.png) |\n\n## Features\n\n### Core Features\n\n- **Platform-Specific Dialogs**: Native UI for each platform (Material, Cupertino, Fluent, Adwaita)\n- **Persistent Dialogs**: Force users to update with non-dismissible dialogs\n- **Skip Version**: Let users skip specific versions\n- **Do Not Ask Again**: Remember user's preference to not show update dialogs\n- **Custom Endpoints**: Support for custom XML/JSON version endpoints\n\n### New in v2.1.0\n\n- **Private GitHub Repository Support**: Use `githubToken` or `githubHeaders` for private repos\n\n### New in v2.0.0\n\n- **Release Notes Display**: Show what's new in each update\n- **Update Frequency Control**: Only check for updates every X days\n- **Silent/Background Checking**: Check updates periodically without blocking UI\n- **Force Update by Minimum Version**: Define minimum required version to force updates\n- **Analytics/Callbacks**: Track update impressions, dismissals, and completions\n- **TestFlight Support**: Support beta updates via TestFlight on iOS\n- **GitHub Releases Support**: Check for updates from GitHub releases\n- **Firebase Remote Config**: Integrate with Firebase for remote version control\n- **Localization/i18n**: Built-in translations for dialog text\n- **Update Urgency Levels**: Critical, high, medium, low update types\n- **Changelog Fetching**: Auto-fetch and display changelogs from stores\n\n### Supported Platforms\n\n| Platform | Store | Dialog Style |\n|----------|-------|--------------|\n| iOS | App Store | Cupertino |\n| Android | Play Store | Material Design 3 |\n| macOS | Mac App Store | Cupertino |\n| Windows | Microsoft Store | Fluent Design |\n| Linux | Snap Store / Flathub | Adwaita (GNOME) |\n\n## Installation\n\nAdd `app_updater` to your `pubspec.yaml`:\n\n```yaml\ndependencies:\n  app_updater: ^2.1.0\n```\n\n## Quick Start\n\n```dart\nimport 'package:app_updater/app_updater.dart';\n\n// Create an AppUpdater instance\nfinal appUpdater = AppUpdater.configure(\n  iosAppId: '123456789',\n  macAppId: '987654321',\n  microsoftProductId: '9NBLGGH4NNS1',\n  snapName: 'my-app',\n  flathubAppId: 'com.example.myapp',\n);\n\n// Check for updates and show dialog\nfinal updateInfo = await appUpdater.checkAndShowUpdateDialog(context);\n\nif (updateInfo.updateAvailable) {\n  print('New version available: ${updateInfo.latestVersion}');\n  print('Release notes: ${updateInfo.releaseNotes}');\n}\n```\n\n## Usage\n\n### Basic Usage\n\n```dart\n// Create AppUpdater with configuration\nfinal appUpdater = AppUpdater.configure(\n  iosAppId: '123456789',\n  // androidPackageName is auto-detected!\n);\n\n// Check and show dialog if update available\nawait appUpdater.checkAndShowUpdateDialog(context);\n```\n\n### All Platforms\n\n```dart\nfinal appUpdater = AppUpdater.configure(\n  // Mobile\n  iosAppId: '123456789',\n  androidPackageName: 'com.example.app', // Optional - auto-detected\n  // Desktop\n  macAppId: '987654321',\n  microsoftProductId: '9NBLGGH4NNS1',\n  snapName: 'my-app',\n  flathubAppId: 'com.example.myapp',\n  linuxStoreType: LinuxStoreType.snap, // or LinuxStoreType.flathub\n);\n```\n\n### Dialog Styles\n\nThe package provides 5 dialog styles that match each platform's design language:\n\n```dart\nawait appUpdater.showUpdateDialog(\n  context,\n  dialogStyle: UpdateDialogStyle.adaptive, // Auto-selects based on platform\n);\n\n// Or force a specific style:\n// UpdateDialogStyle.material   - Material Design 3 (Android)\n// UpdateDialogStyle.cupertino  - iOS/macOS native\n// UpdateDialogStyle.fluent     - Windows Fluent Design\n// UpdateDialogStyle.adwaita    - Linux GNOME/Adwaita\n```\n\n### Persistent (Forced) Updates\n\nFor critical updates that users must install:\n\n```dart\nawait appUpdater.checkAndShowUpdateDialog(\n  context,\n  isPersistent: true,  // Cannot be dismissed\n  isDismissible: false,\n  title: 'Critical Update Required',\n  message: 'Please update to continue using the app.',\n);\n```\n\n### Skip Version \u0026 Do Not Ask Again\n\nLet users control update notifications:\n\n```dart\nawait appUpdater.checkAndShowUpdateDialog(\n  context,\n  showSkipVersion: true,    // Shows \"Skip this version\" option\n  showDoNotAskAgain: true,  // Shows \"Don't remind me again\" option\n);\n```\n\n### Managing Preferences\n\n```dart\n// Check if user skipped a version\nfinal isSkipped = await UpdatePreferences.isVersionSkipped('2.0.0');\n\n// Check if user chose \"do not ask again\"\nfinal doNotAsk = await UpdatePreferences.isDoNotAskAgain();\n\n// Reset all preferences\nawait UpdatePreferences.clearAll();\n\n// Reset only skipped version\nawait UpdatePreferences.clearSkippedVersion();\n\n// Get analytics data\nfinal impressions = await UpdatePreferences.getUpdateImpressions();\nfinal dismissals = await UpdatePreferences.getUpdateDismissals();\n```\n\n---\n\n## New Features\n\n### Release Notes Display\n\nShow what's new in the update dialog:\n\n```dart\nawait appUpdater.checkAndShowUpdateDialog(\n  context,\n  showReleaseNotes: true, // Enabled by default\n);\n\n// Release notes are automatically fetched from:\n// - App Store (iOS/macOS)\n// - Flathub (Linux)\n// - GitHub Releases\n// - Custom JSON/XML endpoints\n```\n\n### Update Frequency Control\n\nPrevent checking for updates too frequently:\n\n```dart\nfinal appUpdater = AppUpdater.configure(\n  iosAppId: '123456789',\n  checkFrequency: Duration(days: 1), // Only check once per day\n);\n\n// Manual check respecting frequency\nfinal updateInfo = await appUpdater.checkForUpdate();\n\n// Force check ignoring frequency\nfinal updateInfo = await appUpdater.checkForUpdate(respectFrequency: false);\n```\n\n### Background/Silent Checking\n\nCheck for updates in the background without blocking the UI:\n\n```dart\n// Start periodic background checking\nappUpdater.startBackgroundChecking(Duration(hours: 6));\n\n// Listen for updates\nappUpdater.updateStream.listen((updateInfo) {\n  if (updateInfo.updateAvailable) {\n    // Show notification or update badge\n    showNotification('Update available: ${updateInfo.latestVersion}');\n  }\n});\n\n// Stop background checking when done\nappUpdater.stopBackgroundChecking();\n\n// Don't forget to dispose\n@override\nvoid dispose() {\n  appUpdater.dispose();\n  super.dispose();\n}\n```\n\n### Force Update by Minimum Version\n\nForce updates when users are below a minimum version:\n\n```dart\nfinal appUpdater = AppUpdater.configure(\n  iosAppId: '123456789',\n  minimumVersion: '2.0.0', // Users below this MUST update\n);\n\n// Or via custom JSON endpoint:\n// { \"version\": \"2.5.0\", \"minimumVersion\": \"2.0.0\" }\n\n// Check if force update is required\nfinal updateInfo = await appUpdater.checkForUpdate();\nif (updateInfo.requiresForceUpdate) {\n  // Show non-dismissible dialog\n  await appUpdater.showUpdateDialog(context, isPersistent: true);\n}\n```\n\n### Update Urgency Levels\n\nCommunicate update importance to users:\n\n```dart\n// Urgency levels: low, medium, high, critical\n// Set via custom endpoints or Firebase Remote Config\n\n// Custom JSON endpoint example:\n// { \"version\": \"2.5.0\", \"urgency\": \"critical\" }\n\n// The dialog icon and color change based on urgency\nfinal updateInfo = await appUpdater.checkForUpdate();\nprint('Urgency: ${updateInfo.urgency}'); // UpdateUrgency.critical\n```\n\n### Analytics \u0026 Callbacks\n\nTrack user interactions with update dialogs:\n\n```dart\nfinal appUpdater = AppUpdater.configure(\n  iosAppId: '123456789',\n  onAnalyticsEvent: (event) {\n    // Send to your analytics service\n    analytics.logEvent(\n      name: event.eventName,\n      parameters: event.toMap(),\n    );\n  },\n);\n\n// Available events:\n// - update_dialog_shown\n// - update_accepted\n// - update_declined\n// - update_version_skipped\n// - update_do_not_ask_again\n// - update_check_started\n// - update_check_completed\n// - update_check_failed\n// - update_store_opened\n```\n\n### GitHub Releases Support\n\nCheck for updates from GitHub releases:\n\n```dart\nfinal appUpdater = AppUpdater.configure(\n  githubOwner: 'mycompany',\n  githubRepo: 'myapp',\n  githubIncludePrereleases: false, // Set to true for beta builds\n);\n\n// Automatically fetches:\n// - Latest version from tag name\n// - Release notes from body\n// - Download URL from assets\n```\n\n### Private GitHub Repositories\n\nFor private repos, just pass your GitHub Personal Access Token:\n\n```dart\nfinal appUpdater = AppUpdater.configure(\n  githubOwner: 'mycompany',\n  githubRepo: 'private-app',\n  githubToken: 'ghp_xxxxxxxxxxxxx', // That's it!\n);\n```\n\nFor GitHub Enterprise or advanced auth scenarios, use custom headers:\n\n```dart\nfinal appUpdater = AppUpdater.configure(\n  githubOwner: 'mycompany',\n  githubRepo: 'private-app',\n  githubHeaders: {\n    'Authorization': 'token ghp_xxxxxxxxxxxxx',\n    'Accept': 'application/vnd.github+json',\n    'X-GitHub-Api-Version': '2022-11-28',\n  },\n);\n```\n\n\u003e **Note:** If both `githubToken` and `githubHeaders` are provided, values in `githubHeaders` take precedence for overlapping keys (e.g., `Authorization`).\n\n### TestFlight Support (iOS)\n\nSupport beta updates via TestFlight:\n\n```dart\nfinal appUpdater = AppUpdater.configure(\n  iosAppId: '123456789',\n  testFlightEnabled: true,\n  testFlightUrl: 'https://testflight.apple.com/join/ABC123', // Optional custom URL\n);\n\n// Open TestFlight for beta testing\nawait appUpdater.openTestFlight();\n```\n\n### Firebase Remote Config Integration\n\nUse Firebase Remote Config for dynamic version control:\n\n```dart\nfinal appUpdater = AppUpdater.configure(\n  firebaseRemoteConfigEnabled: true,\n  firebaseSettings: FirebaseRemoteConfigSettings(\n    minimumVersionKey: 'minimum_app_version',\n    latestVersionKey: 'latest_app_version',\n    updateUrlKey: 'app_update_url',\n    releaseNotesKey: 'release_notes',\n    urgencyKey: 'update_urgency',\n    mandatoryKey: 'mandatory_update',\n  ),\n  firebaseConfigFetcher: () async {\n    // Fetch from your Firebase Remote Config instance\n    await FirebaseRemoteConfig.instance.fetchAndActivate();\n    return {\n      'minimum_app_version': FirebaseRemoteConfig.instance.getString('minimum_app_version'),\n      'latest_app_version': FirebaseRemoteConfig.instance.getString('latest_app_version'),\n      'app_update_url': FirebaseRemoteConfig.instance.getString('app_update_url'),\n      'release_notes': FirebaseRemoteConfig.instance.getString('release_notes'),\n      'update_urgency': FirebaseRemoteConfig.instance.getString('update_urgency'),\n      'mandatory_update': FirebaseRemoteConfig.instance.getBool('mandatory_update'),\n    };\n  },\n);\n```\n\n### Localization / i18n\n\nProvide translations for all dialog text:\n\n```dart\n// Create localized strings\nfinal frenchStrings = UpdateStrings(\n  updateAvailableTitle: 'Mise à jour disponible',\n  updateAvailableMessage: 'Une nouvelle version ({latestVersion}) est disponible. Vous avez actuellement la version {currentVersion}.',\n  updateButton: 'Mettre à jour',\n  laterButton: 'Plus tard',\n  skipVersionButton: 'Ignorer cette version',\n  doNotAskAgainButton: 'Ne plus me rappeler',\n  criticalUpdateTitle: 'Mise à jour critique requise',\n  criticalUpdateMessage: 'Cette mise à jour contient des correctifs importants.',\n  releaseNotesTitle: 'Nouveautés',\n  loadingText: 'Vérification des mises à jour...',\n  errorText: 'Impossible de vérifier les mises à jour',\n  upToDateText: 'Votre application est à jour !',\n);\n\nfinal appUpdater = AppUpdater.configure(\n  iosAppId: '123456789',\n  strings: frenchStrings,\n);\n```\n\n---\n\n## Custom Update Servers\n\n### Custom JSON Endpoint\n\nHost your own version endpoint:\n\n```json\n{\n  \"version\": \"2.0.0\",\n  \"url\": \"https://example.com/download\",\n  \"releaseNotes\": \"- New feature X\\n- Bug fix Y\",\n  \"minimumVersion\": \"1.5.0\",\n  \"urgency\": \"high\",\n  \"mandatory\": false\n}\n```\n\n```dart\nfinal appUpdater = AppUpdater.configure(\n  customJsonUrl: 'https://example.com/version.json',\n);\n```\n\n### Custom XML Endpoint\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003capp\u003e\n  \u003cversion\u003e2.0.0\u003c/version\u003e\n  \u003curl\u003ehttps://example.com/download\u003c/url\u003e\n  \u003creleaseNotes\u003eNew features and improvements\u003c/releaseNotes\u003e\n  \u003cminimumVersion\u003e1.5.0\u003c/minimumVersion\u003e\n  \u003curgency\u003ehigh\u003c/urgency\u003e\n  \u003cmandatory\u003efalse\u003c/mandatory\u003e\n\u003c/app\u003e\n```\n\n```dart\nfinal appUpdater = AppUpdater.configure(\n  customXmlUrl: 'https://example.com/version.xml',\n);\n```\n\n---\n\n## Additional Methods\n\n### Check Without Dialog\n\n```dart\nfinal updateInfo = await appUpdater.checkForUpdate();\n\nprint('Current: ${updateInfo.currentVersion}');\nprint('Latest: ${updateInfo.latestVersion}');\nprint('Update available: ${updateInfo.updateAvailable}');\nprint('Store URL: ${updateInfo.updateUrl}');\nprint('Release notes: ${updateInfo.releaseNotes}');\nprint('Urgency: ${updateInfo.urgency}');\nprint('Is mandatory: ${updateInfo.isMandatory}');\nprint('Requires force update: ${updateInfo.requiresForceUpdate}');\nprint('Update size: ${updateInfo.formattedUpdateSize}');\n```\n\n### Open Store\n\n```dart\n// Open the appropriate store for the current platform\nawait appUpdater.openStore();\n\n// Or use the convenience function\nawait openAppStore(\n  iosAppId: '123456789',\n  microsoftProductId: '9NBLGGH4NNS1',\n);\n```\n\n### Callbacks\n\n```dart\nawait appUpdater.checkAndShowUpdateDialog(\n  context,\n  onNoUpdate: () {\n    ScaffoldMessenger.of(context).showSnackBar(\n      const SnackBar(content: Text('App is up to date!')),\n    );\n  },\n  onUpdate: () {\n    print('User chose to update');\n  },\n  onCancel: () {\n    print('User cancelled');\n  },\n);\n```\n\n### Custom Dialog\n\n```dart\nawait appUpdater.showUpdateDialog(\n  context,\n  customDialog: AlertDialog(\n    title: const Text('Custom Update Dialog'),\n    content: const Text('A new version is available!'),\n    actions: [\n      TextButton(\n        onPressed: () =\u003e Navigator.pop(context),\n        child: const Text('Later'),\n      ),\n      FilledButton(\n        onPressed: () {\n          Navigator.pop(context);\n          appUpdater.openStore();\n        },\n        child: const Text('Update'),\n      ),\n    ],\n  ),\n);\n```\n\n---\n\n## API Reference\n\n### AppUpdater\n\n| Method | Description |\n|--------|-------------|\n| `AppUpdater.configure(...)` | Create instance with individual parameters |\n| `AppUpdater(config)` | Create instance with `AppUpdaterConfig` |\n| `checkForUpdate()` | Check for updates, returns `UpdateInfo` |\n| `showUpdateDialog(context, ...)` | Show update dialog |\n| `checkAndShowUpdateDialog(context, ...)` | Check and show dialog if update available |\n| `openStore()` | Open the appropriate app store |\n| `openTestFlight()` | Open TestFlight (iOS only) |\n| `getStoreUrl()` | Get store URL for current platform |\n| `getTestFlightUrl()` | Get TestFlight URL (iOS only) |\n| `startBackgroundChecking(interval)` | Start periodic background checks |\n| `stopBackgroundChecking()` | Stop background checks |\n| `performBackgroundCheck()` | Perform single background check |\n| `dispose()` | Clean up resources |\n\n### AppUpdaterConfig\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `iosAppId` | `String?` | iOS App Store app ID |\n| `macAppId` | `String?` | macOS App Store app ID |\n| `androidPackageName` | `String?` | Android package name (auto-detected) |\n| `microsoftProductId` | `String?` | Microsoft Store product ID |\n| `snapName` | `String?` | Snap Store package name |\n| `flathubAppId` | `String?` | Flathub app ID |\n| `customXmlUrl` | `String?` | Custom XML endpoint URL |\n| `customJsonUrl` | `String?` | Custom JSON endpoint URL |\n| `linuxStoreType` | `LinuxStoreType` | snap or flathub |\n| `githubOwner` | `String?` | GitHub repository owner |\n| `githubRepo` | `String?` | GitHub repository name |\n| `githubIncludePrereleases` | `bool` | Include prereleases (default: false) |\n| `githubToken` | `String?` | GitHub PAT for private repos |\n| `githubHeaders` | `Map\u003cString, String\u003e?` | Custom HTTP headers for GitHub API |\n| `testFlightEnabled` | `bool` | Enable TestFlight (default: false) |\n| `testFlightUrl` | `String?` | Custom TestFlight URL |\n| `firebaseRemoteConfigEnabled` | `bool` | Enable Firebase (default: false) |\n| `firebaseSettings` | `FirebaseRemoteConfigSettings?` | Firebase config keys |\n| `firebaseConfigFetcher` | `Function?` | Callback to fetch Firebase values |\n| `checkFrequency` | `Duration?` | Minimum time between checks |\n| `minimumVersion` | `String?` | Minimum required version |\n| `onAnalyticsEvent` | `Function?` | Analytics callback |\n| `strings` | `UpdateStrings` | Localized strings |\n\n### UpdateDialogStyle\n\n| Style | Platform | Description |\n|-------|----------|-------------|\n| `adaptive` | All | Auto-selects based on platform |\n| `material` | Android | Material Design 3 |\n| `cupertino` | iOS/macOS | Native Apple design |\n| `fluent` | Windows | Microsoft Fluent Design |\n| `adwaita` | Linux | GNOME/Adwaita style |\n\n### UpdateUrgency\n\n| Level | Description |\n|-------|-------------|\n| `low` | Minor improvements, can be skipped |\n| `medium` | Regular updates with new features |\n| `high` | Important updates, strongly recommended |\n| `critical` | Security fixes or breaking changes |\n\n### UpdateInfo\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `currentVersion` | `String` | Current app version |\n| `latestVersion` | `String?` | Latest available version |\n| `updateUrl` | `String?` | Store/download URL |\n| `updateAvailable` | `bool` | Whether update is available |\n| `releaseNotes` | `String?` | Release notes/changelog |\n| `urgency` | `UpdateUrgency` | Update urgency level |\n| `minimumVersion` | `String?` | Minimum required version |\n| `isMandatory` | `bool` | Whether update is mandatory |\n| `releaseDate` | `DateTime?` | Release date |\n| `updateSizeBytes` | `int?` | Update size in bytes |\n| `requiresForceUpdate` | `bool` | Whether force update is required |\n| `formattedUpdateSize` | `String?` | Human-readable size (e.g., \"15.2 MB\") |\n\n### UpdatePreferences\n\n| Method | Description |\n|--------|-------------|\n| `isVersionSkipped(version)` | Check if version is skipped |\n| `skipVersion(version)` | Skip a specific version |\n| `isDoNotAskAgain()` | Check \"do not ask again\" preference |\n| `setDoNotAskAgain(value)` | Set \"do not ask again\" preference |\n| `getLastCheckTime()` | Get last update check time |\n| `setLastCheckTime(time)` | Set last update check time |\n| `shouldCheckForUpdate(frequency)` | Check if enough time has passed |\n| `getUpdateImpressions()` | Get dialog impression count |\n| `getUpdateDismissals()` | Get dismissal count |\n| `clearAll()` | Clear all preferences |\n| `clearSkippedVersion()` | Clear skipped version only |\n\n### UpdateAnalyticsEvent\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `eventName` | `String` | Event name |\n| `currentVersion` | `String` | Current app version |\n| `latestVersion` | `String?` | Latest available version |\n| `urgency` | `UpdateUrgency?` | Update urgency |\n| `platform` | `String` | Platform name |\n| `timestamp` | `DateTime` | Event timestamp |\n| `toMap()` | `Map` | Convert to map for analytics |\n\n### UpdateStrings\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `updateAvailableTitle` | `String` | Dialog title |\n| `updateAvailableMessage` | `String` | Dialog message (supports placeholders) |\n| `updateButton` | `String` | Update button text |\n| `laterButton` | `String` | Later button text |\n| `skipVersionButton` | `String` | Skip version button text |\n| `doNotAskAgainButton` | `String` | Do not ask again button text |\n| `criticalUpdateTitle` | `String` | Critical update title |\n| `criticalUpdateMessage` | `String` | Critical update message |\n| `releaseNotesTitle` | `String` | Release notes section title |\n| `loadingText` | `String` | Loading text |\n| `errorText` | `String` | Error text |\n| `upToDateText` | `String` | Up to date text |\n\n---\n\n## Notes\n\n- Update dialogs won't work on iOS Simulator (no App Store)\n- Android package name is auto-detected if not provided\n- Custom endpoints take priority over store checks\n- Firebase Remote Config takes highest priority when enabled\n- GitHub releases are checked before platform stores\n- Private GitHub repos require `githubToken` or `githubHeaders` for authentication\n- Release notes are automatically fetched from supported sources\n- Background checking requires calling `dispose()` when done\n\n## Credits\n\n- [url_launcher](https://pub.dev/packages/url_launcher)\n- [package_info_plus](https://pub.dev/packages/package_info_plus)\n- [shared_preferences](https://pub.dev/packages/shared_preferences)\n\n## Author\n\n- [Mantresh Khurana](https://github.com/mantreshkhurana)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmantreshkhurana%2Fapp_updater","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmantreshkhurana%2Fapp_updater","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmantreshkhurana%2Fapp_updater/lists"}