{"id":32292908,"url":"https://github.com/jayadevpanthaplavil/update-manager","last_synced_at":"2026-02-23T19:05:20.740Z","repository":{"id":317320497,"uuid":"1066290261","full_name":"jayadevpanthaplavil/update-manager","owner":"jayadevpanthaplavil","description":"A Flutter package to manage app updates with Firebase Remote Config and Shorebird, supporting force, optional, and patch updates easily.","archived":false,"fork":false,"pushed_at":"2025-10-22T06:58:54.000Z","size":192,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-23T03:36:42.928Z","etag":null,"topics":["dart","firebase","firebase-remote-config","flutter","hacktoberfest","hacktoberfest-accepted","mobile-app","shorebird","update","update-checker"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/update_manager","language":"Dart","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/jayadevpanthaplavil.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-29T09:35:41.000Z","updated_at":"2025-10-22T06:55:39.000Z","dependencies_parsed_at":"2025-10-15T18:20:24.681Z","dependency_job_id":"4f1e2c3e-aaa8-4a2c-aec4-feac4a8b7667","html_url":"https://github.com/jayadevpanthaplavil/update-manager","commit_stats":null,"previous_names":["jayadevpanthaplavil/update-manager"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/jayadevpanthaplavil/update-manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jayadevpanthaplavil%2Fupdate-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jayadevpanthaplavil%2Fupdate-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jayadevpanthaplavil%2Fupdate-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jayadevpanthaplavil%2Fupdate-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jayadevpanthaplavil","download_url":"https://codeload.github.com/jayadevpanthaplavil/update-manager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jayadevpanthaplavil%2Fupdate-manager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29751813,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-23T07:44:07.782Z","status":"ssl_error","status_checked_at":"2026-02-23T07:44:07.432Z","response_time":90,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["dart","firebase","firebase-remote-config","flutter","hacktoberfest","hacktoberfest-accepted","mobile-app","shorebird","update","update-checker"],"created_at":"2025-10-23T03:26:07.965Z","updated_at":"2026-02-23T19:05:20.731Z","avatar_url":"https://github.com/jayadevpanthaplavil.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# update_manager\n\nA Flutter package for managing app updates with **Firebase Remote Config** and **Shorebird patch updates**.  \nIt helps you implement **force updates**, **optional updates**, and **patch updates** easily.\n\n---\n\n## ✨ Features\n- 🚀 Force update when a critical version is required\n- 📢 Optional update when a newer version is available\n- ⚡ Patch updates via Shorebird\n- 🔧 Configurable via Firebase Remote Config\n- 🎯 Simple integration with callback support\n- 🛠️ Example app included\n\n---\n## 📦 Installation\n\n### 1. Add Dependencies\nAdd this to your `pubspec.yaml`:\n```yaml\ndependencies:\n  update_manager: ^1.2.0\n  # Required dependencies\n  firebase_core: ^4.1.1\n  package_info_plus: ^9.0.0\n```\n\n### 2. Install Packages\nRun:\n```sh\nflutter pub get\n```\n\n### 3. Configure Firebase\nThis package requires Firebase to be configured in your project. Follow the [official Firebase setup guide](https://firebase.google.com/docs/flutter/setup) for your platform:\n\n- [Android setup](https://firebase.google.com/docs/flutter/setup?platform=android)\n- [iOS setup](https://firebase.google.com/docs/flutter/setup?platform=ios)\n\nMake sure to initialize Firebase in your `main.dart`:\n```dart\nimport 'package:firebase_core/firebase_core.dart';\nimport 'firebase_options.dart';\n\nvoid main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n  await Firebase.initializeApp(\n    options: DefaultFirebaseOptions.currentPlatform,\n  );\n  runApp(MyApp());\n}\n```\n\n\n### 4. Setup Shorebird for Code Push Updates\n\n#### Install Shorebird CLI\n\n### Install Shorebird\n[Shorebird Quickstart](https://docs.shorebird.dev/getting-started/)\n\n```sh\n# Verify installation\nshorebird --version\n```\n\nFor more information, visit the [Shorebird documentation](https://docs.shorebird.dev/).\n\n---\n\n## 🚀 Usage\n\n## Main Entry Points in [`Example/`](example)\n\n- **`main.dart`** – Standard setup. Requires manual configuration of update checks and UI.\n- **`main_default_ui.dart`** – Comes with built-in update dialogs and patch UI. Minimal configuration required.\n\n**Tip:** For quick setup with default UI, use `main_default_ui.dart`.\n\n```dart\nimport 'package:firebase_core/firebase_core.dart';\nimport 'package:flutter/material.dart';\nimport 'package:package_info_plus/package_info_plus.dart';\nimport 'package:update_manager/update_manager.dart';\n\nconst UpdateTrack kAppUpdateTrack = UpdateTrack.stable;\n\nFuture\u003cvoid\u003e main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n  await Firebase.initializeApp();\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: 'Update Manager Example',\n      theme: ThemeData(\n        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),\n        useMaterial3: true,\n      ),\n      home: const MyHomePage(title: 'Update Manager Example'),\n    );\n  }\n}\n\nclass MyHomePage extends StatefulWidget {\n  const MyHomePage({super.key, required this.title});\n\n  final String title;\n\n  @override\n  State\u003cMyHomePage\u003e createState() =\u003e _MyHomePageState();\n}\n\nclass _MyHomePageState extends State\u003cMyHomePage\u003e {\n  UpdateManager? _updateManager;\n  final UpdateTrack _currentTrack = kAppUpdateTrack;\n  String _currentVersion = '';\n  int? _currentPatchNumber;\n\n  @override\n  void initState() {\n    super.initState();\n    _initialize();\n  }\n\n  Future\u003cvoid\u003e _initialize() async {\n    final packageInfo = await PackageInfo.fromPlatform();\n    setState(() {\n      _currentVersion = packageInfo.version;\n    });\n\n    if (!mounted) return;\n\n    // Configure UI preferences\n    final uiConfig = UpdateUIConfig(\n      dialogStyle: UpdateUIStyle.material,\n      patchUIStyle: PatchUIStyle.snackbar,\n      androidPlayStoreUrl: 'redirection link',\n      iosAppStoreUrl: 'redirection link',\n      showDefaultUI: true, // Set to false if using custom callbacks only\n      primaryColor: Colors.deepPurple,\n      accentColor: Colors.amber,\n    );\n\n    _updateManager = UpdateManager(\n      enableShorebird: true,\n      packageInfo: packageInfo,\n      uiConfig: uiConfig,\n      context: context,\n    );\n\n    try {\n      await _updateManager?.initialise(shorebirdTrack: _currentTrack);\n      final installedPatch = await _updateManager?.shorebirdService\n          ?.readCurrentPatch();\n      if (mounted) {\n        setState(() {\n          _currentPatchNumber = installedPatch;\n        });\n      }\n    } catch (e) {\n      debugPrint(\"UpdateManager init error: $e\");\n    }\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    final theme = Theme.of(context);\n\n    return Scaffold(\n      appBar: AppBar(\n        backgroundColor: theme.colorScheme.inversePrimary,\n        title: Text(widget.title),\n      ),\n      body: SingleChildScrollView(\n        padding: const EdgeInsets.all(16),\n        child: Column(\n          children: [\n            // Version Info Card\n            Card(\n              color: theme.colorScheme.primaryContainer,\n              child: Padding(\n                padding: const EdgeInsets.all(20),\n                child: Column(\n                  children: [\n                    Text(\n                      'Current Version',\n                      style: theme.textTheme.titleMedium?.copyWith(\n                        fontWeight: FontWeight.bold,\n                      ),\n                    ),\n                    const SizedBox(height: 8),\n                    Text(\n                      _currentVersion,\n                      style: theme.textTheme.headlineMedium?.copyWith(\n                        fontWeight: FontWeight.bold,\n                        color: theme.colorScheme.primary,\n                      ),\n                    ),\n                    const SizedBox(height: 16),\n                    Row(\n                      mainAxisAlignment: MainAxisAlignment.center,\n                      children: [\n                        Icon(Icons.info_outline, size: 20),\n                        const SizedBox(width: 8),\n                        Text(\n                          'Installed Patch: ${_currentPatchNumber ?? 'None'}',\n                          style: theme.textTheme.bodyLarge?.copyWith(\n                            fontWeight: FontWeight.w500,\n                          ),\n                        ),\n                      ],\n                    ),\n                  ],\n                ),\n              ),\n            ),\n            const SizedBox(height: 24),\n          ],\n        ),\n      ),\n    );\n  }\n}\n```\n\n---\n\n## ⚙️ Firebase Setup\n\n1. Enable **Remote Config** in your Firebase Console.\n2. Add the following default parameters and values.\n3. Refer to [`example/remoteconfig.template.json`](example/remoteconfig.template.json) for a complete example.\n\n| Key                    | Example Value                                                                                                                                                                                                                                                                                                                                                                                                  | Description                                                                                                               |\n|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|\n| `min_required_version` | `{\"stable\": \"1.0.0\", \"beta\": \"1.0.5\", \"staging\": \"1.0.10\"}`                                                                                                                                                                                                                                                                                                                                                    | Minimum app version required **per track**. JSON map of track versions (`{\"stable\": \"1.0.0\", \"beta\": \"1.0.5\"}`).          |\n| `latest_version`       | `{\"stable\": \"1.0.29\", \"beta\": \"1.0.30\", \"staging\": \"1.0.31\"}`                                                                                                                                                                                                                                                                                                                                                  | Latest available version **per track**. JSON map of track versions (`{\"stable\": \"1.0.29\", \"beta\": \"1.0.30\"}`).            |\n| `patch_enabled`        | `true`                                                                                                                                                                                                                                                                                                                                                                                                         | Global flag to enable or disable patch checking.                                                                          |\n| `patch_info`           | `{ \"1.0.25\": { \"stable\": 1, \"beta\": 0, \"staging\": 0 }, \"1.0.1\": { \"stable\": 1, \"beta\": 2, \"staging\": 3 } }`                                                                                                                                                                                                                                                                                                    | Patch numbers per version and track. The format is `{ \"version\": { \"track\": patchNumber } }`.                             |\n| `redirect_url`         | `{ \"android\": { \"stable\": \"https://play.google.com/store/apps/details?id=com.example.stable\", \"beta\": \"https://play.google.com/store/apps/details?id=com.example.beta\", \"staging\": \"https://play.google.com/store/apps/details?id=com.example.staging\"}, \"ios\": {\"stable\": \"https://apps.apple.com/app/idxxxx\", \"beta\": \"https://apps.apple.com/app/idxxxx\", \"staging\": \"https://apps.apple.com/app/idxxxx\"}}` | Redirection URLs for each platform and track. JSON {\"android\": {\"stable\": \"\u003curl\u003e\", ...}, \"ios\": {\"stable\": \"\u003curl\u003e\", ...}} | \n\n**Example `patch_info` value:**\n\n```json\n{\n  \"1.0.25\": { \"stable\": 1, \"beta\": 0, \"staging\": 0 },\n  \"1.0.1\": { \"stable\": 1, \"beta\": 2, \"staging\": 3 }\n}\n```\n\n\n---\n\n## 📄 Changelog\n\nSee the [Changelog](CHANGELOG.md)\n\n---\n\n## 📱 Example\n\nSee the [`example/`](example) folder for a full demo project.\n\n---\n\n## 📄 License\n\nThis project is licensed under the [MIT License](LICENSE).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjayadevpanthaplavil%2Fupdate-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjayadevpanthaplavil%2Fupdate-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjayadevpanthaplavil%2Fupdate-manager/lists"}