dart_patch_updater
π In-app updates for Flutter β without the App Store
Update your Flutter app's business logic instantly from your own server or GitHub Releases.
No Play Store review. No App Store wait. Ship fixes in minutes.
β¨ Features
- π Hot updates β Push business logic changes without app store reviews
- π Secure β SHA-256 checksum + RSA signature verification
- βͺ Auto-rollback β Automatically reverts on failure
- π¦ GitHub Releases support β Use GitHub as your update server
- π± Cross-platform β Android, iOS, macOS, Windows, Linux
- π Offline-safe β Won't brick your app if update fails
- π― Version targeting β Control which app versions receive updates
π What Can Be Updated?
| β Can Update | β Cannot Update |
|---|---|
| Feature flags | Compiled Dart code |
| Pricing rules | Native code (Java/Swift) |
| Validation rules | Flutter framework |
| Workflow definitions | App permissions |
| Business logic configs | App icons/splash |
| API endpoints | Native plugins |
Note: Flutter uses AOT compilation, so you cannot download arbitrary
.dartfiles. This package updates data-driven business logic via a JSON rule engine.
π Quick Start
Installation
dependencies:
dart_patch_updater: ^0.1.0
Basic Usage
import 'package:dart_patch_updater/dart_patch_updater.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final updateManager = UpdateManager(
config: UpdateConfig(
serverUrl: 'https://rawgit.flutter-io.cn/you/repo/main/update.json',
appId: 'com.example.myapp',
appVersion: '2.1.0',
publicKey: '-----BEGIN PUBLIC KEY-----\n...',
useStaticJson: true, // For GitHub Releases
),
);
await updateManager.initialize();
runApp(MyApp(updateManager: updateManager));
}
Check & Apply Updates
// Check for updates
final result = await updateManager.checkForUpdates();
if (result.updateAvailable) {
// Download and apply
final updateResult = await updateManager.downloadAndApply(
onProgress: (progress) => print('${progress.percentage}%'),
);
if (updateResult.success) {
print('Updated to ${updateResult.newVersion}!');
}
}
Use Updated Business Logic
// Feature flags
final isDarkMode = updateManager.getModuleData('feature_flags')?['dark_mode'] ?? false;
// Pricing rules
final discount = updateManager.getModuleData('pricing_rules')?['discount'] ?? 0.1;
π§ Configuration Options
| Parameter | Type | Default | Description |
|---|---|---|---|
serverUrl |
String |
required | Update metadata URL |
appId |
String |
required | Your app's unique ID |
appVersion |
String |
'1.0.0' |
Current app version |
publicKey |
String |
required | RSA public key for verification |
useStaticJson |
bool |
false |
true for GitHub, false for API |
checkOnLaunch |
bool |
true |
Auto-check on app start |
autoDownload |
bool |
false |
Auto-download when available |
autoApply |
bool |
false |
Auto-apply without confirmation |
maxBackupVersions |
int |
3 |
Backup count for rollback |
validateSignatures |
bool |
true |
Verify RSA signatures |
validateChecksums |
bool |
true |
Verify SHA-256 checksums |
π Server Setup
Option 1: GitHub Releases (Recommended)
1. Create update.json in your repo:
{
"update_available": true,
"patch": {
"version": "1.1.0",
"min_app_version": "2.0.0",
"max_app_version": "3.0.0",
"download_url": "https://github.com/you/repo/releases/download/v1.1.0/patch.zip",
"checksum": "sha256:a1b2c3...",
"signature": "base64_signature...",
"mandatory": false,
"released_at": "2025-01-01T00:00:00Z"
}
}
2. Create your patch bundle:
patch.zip
βββ manifest.json
βββ modules/
βββ feature_flags.json
βββ pricing_rules.json
3. Upload to GitHub Releases
Option 2: Custom API Server
UpdateConfig(
serverUrl: 'https://api.yourserver.com',
checkEndpoint: '/api/updates/check',
useStaticJson: false, // Uses POST request
)
π¦ Patch Bundle Structure
manifest.json
{
"version": "1.1.0",
"created_at": "2025-01-01T00:00:00Z",
"requires_restart": false,
"modules": [
{ "name": "feature_flags", "path": "modules/feature_flags.json", "type": "json" },
{ "name": "pricing_rules", "path": "modules/pricing_rules.json", "type": "json" }
]
}
modules/feature_flags.json
{
"dark_mode": true,
"premium_features": true,
"new_checkout_flow": false
}
modules/pricing_rules.json
{
"default_discount": 0.15,
"rules": [
{
"condition": { "gte": ["$order.total", 100] },
"action": { "type": "return", "value": 0.25 }
}
]
}
π Security
Generate an RSA keypair for signing patches:
# Generate private key (keep secret!)
openssl genrsa -out private_key.pem 2048
# Extract public key (embed in your app)
openssl rsa -in private_key.pem -pubout -out public_key.pem
# Sign your patch
openssl dgst -sha256 -sign private_key.pem -out patch.sig patch.zip
base64 patch.sig > signature.txt
βͺ Rollback
// Rollback to previous version
final result = await updateManager.rollback();
// Get available versions
final versions = await updateManager.getAvailableRollbackVersions();
// Rollback to specific version
await updateManager.rollbackToVersion('1.0.0');
π± Platform Support
| Platform | Supported |
|---|---|
| Android | β |
| iOS | β |
| macOS | β |
| Windows | β |
| Linux | β |
| Web | β |
π License
MIT License β see LICENSE for details.
Made with β€οΈ for the Flutter community
Libraries
- dart_patch_updater
- Flutter in-app update package for fetching and applying Dart code patches from a custom server without app store dependencies.