dart_patch_updater logo

dart_patch_updater

πŸš€ In-app updates for Flutter β€” without the App Store

pub version build status license

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 .dart files. 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

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.