quicui 2.0.8
quicui: ^2.0.8 copied to clipboard
Over-the-air (OTA) updates for Flutter apps. Download and install code updates instantly with QuicUI Code Push system.
QuicUI #
A Flutter plugin for instant Over-The-Air (OTA) code updates. Push Dart code changes to your users in seconds.
Table of Contents #
- Features
- Quick Start
- Complete Setup Guide
- Usage
- API Reference
- Platform Support
- Troubleshooting
- Related Projects
Features #
- π Instant OTA Updates β Deploy Dart code changes in seconds
- π Secure β Signature verification and hash validation
- π¦ Small Downloads β XZ/GZIP compression (~95% smaller)
- β Rollback Support β Automatic rollback on failures
- π― YAML Configuration β Auto-loads from
quicui.yaml - π Hidden Secrets β Server URL and API keys are internal only
- π± Android Support β Full production support (iOS coming soon)
Quick Start #
1. Install CLI & Initialize #
# Install CLI from pub.dev
dart pub global activate quicui_cli
# Initialize in your Flutter project
cd your_flutter_app
quicui init
2. Download QuicUI SDK #
quicui engine download
3. Add this package #
# pubspec.yaml
dependencies:
quicui: ^2.0.6
4. Initialize in your app #
import 'package:quicui/quicui.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await QuicUICodePush.instance.initialize();
runApp(MyApp());
}
5. Create release & push updates #
# First release (baseline)
quicui release --version 1.0.0
# After making changes, push update
quicui patch --version 1.0.1
That's it! Users receive updates on next app launch.
Complete Setup Guide #
Prerequisites #
| Requirement | Version |
|---|---|
| Flutter | 3.0.0+ |
| Dart | 3.0.0+ |
| QuicUI CLI | Latest |
| QuicUI Flutter SDK | Required |
β οΈ Important: This package requires the QuicUI-patched Flutter SDK. Standard Flutter SDK will not support code push functionality.
Step 1: Install QuicUI CLI #
# Install from pub.dev (recommended)
dart pub global activate quicui_cli
# Or install from source
git clone https://github.com/Ikolvi/quicui-cli.git
cd quicui-cli
dart pub get
dart pub global activate --source path .
# Verify installation
quicui --version
Step 2: Initialize Your Project #
cd your_flutter_app
quicui init
This will:
- Detect your app ID from
android/app/build.gradle - Auto-generate a unique API key from the QuicUI server
- Create
quicui.yamlwith your configuration
π QuicUI Initialization
ββββββββββββββββββββββββββββββββββββββββββββ
π Generating API key...
β
API key generated successfully
β
Created quicui.yaml
Step 3: Download QuicUI Flutter SDK #
quicui engine download
The SDK is downloaded to ~/.quicui/flutter/ β completely isolated from your system Flutter installation.
Step 4: Add the Package #
# pubspec.yaml
dependencies:
quicui: ^2.0.6
flutter pub get
Step 5: Configuration #
Your quicui.yaml (auto-generated):
# QuicUI Code Push Configuration
server:
url: "https://pcaxvanjhtfaeimflgfk.supabase.co/functions/v1"
api_key: "quicui_abc123..." # Auto-generated
app:
id: "com.example.myapp"
name: "My App"
version:
current: "1.0.0"
build:
architectures:
- arm64-v8a
# - armeabi-v7a # Uncomment for 32-bit support
patch:
compression: xz # Options: xz, gzip, none
Step 6: Create Your First Release #
quicui release --version 1.0.0
This builds your app with the QuicUI SDK and uploads the baseline binary.
Step 7: Publish to Play Store #
Build and publish your app normally:
quicui build-aab --project .
Upload the resulting AAB to Google Play Store.
Step 8: Push Updates #
After making code changes:
quicui patch --version 1.0.1 --notes "Bug fixes"
Users receive the update on next app launch!
Usage #
Basic Usage #
import 'package:quicui/quicui.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize (auto-loads from quicui.yaml)
await QuicUICodePush.instance.initialize();
runApp(const MyApp());
}
Manual Update Check #
import 'package:quicui/quicui.dart';
Future<void> checkForUpdates() async {
final quicui = QuicUICodePush.instance;
// Check for updates
final patch = await quicui.checkForUpdates();
if (patch != null) {
print('Update available: ${patch.version}');
// Download and install
final success = await quicui.downloadAndInstall(patch);
if (success) {
// Restart to apply the update
await quicui.restartApp();
}
}
}
Background Update Check #
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
_checkForUpdates();
}
}
Future<void> _checkForUpdates() async {
final quicui = QuicUICodePush.instance;
final patch = await quicui.checkForUpdates();
if (patch != null) {
_showUpdateDialog(patch);
}
}
void _showUpdateDialog(PatchInfo patch) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Update Available'),
content: Text('Version ${patch.version} is available.\n\n${patch.releaseNotes ?? ""}'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Later'),
),
ElevatedButton(
onPressed: () async {
Navigator.pop(context);
final success = await QuicUICodePush.instance.downloadAndInstall(patch);
if (success) {
await QuicUICodePush.instance.restartApp();
}
},
child: const Text('Update Now'),
),
],
),
);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
}
Error Handling #
import 'package:quicui/quicui.dart';
Future<void> initWithErrorHandling() async {
try {
await QuicUICodePush.instance.initialize();
} on QuicUIConfigNotFoundException catch (e) {
// quicui.yaml not found - run "quicui init"
print('Config not found: ${e.message}');
} on QuicUIConfigInvalidException catch (e) {
// Invalid configuration
print('Invalid config: ${e.message}');
print('Missing fields: ${e.missingFields}');
} on QuicUIException catch (e) {
// Generic QuicUI error
print('QuicUI error: ${e.message} (code: ${e.code})');
}
}
Silent Updates #
// Check and install updates silently in background
Future<void> silentUpdate() async {
final quicui = QuicUICodePush.instance;
final patch = await quicui.checkForUpdates();
if (patch != null && !patch.critical) {
// Download in background
await quicui.downloadAndInstall(patch);
// Will apply on next app restart
}
}
Critical Updates #
Future<void> handleCriticalUpdate() async {
final quicui = QuicUICodePush.instance;
final patch = await quicui.checkForUpdates();
if (patch != null && patch.critical) {
// Force update for critical patches
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: const Text('Critical Update Required'),
content: const Text('This update is required to continue using the app.'),
actions: [
ElevatedButton(
onPressed: () async {
final success = await quicui.downloadAndInstall(patch);
if (success) {
await quicui.restartApp();
}
},
child: const Text('Update Now'),
),
],
),
);
}
}
API Reference #
QuicUICodePush #
| Method | Description |
|---|---|
QuicUICodePush.instance |
Get singleton instance |
initialize() |
Initialize the client (required first) |
checkForUpdates() |
Check for available patches |
downloadAndInstall(patch) |
Download and install a patch |
restartApp() |
Restart app to apply installed patch |
getCurrentPatch() |
Get currently applied patch info |
rollback() |
Rollback to previous version |
Properties #
| Property | Type | Description |
|---|---|---|
isInitialized |
bool |
Whether client is initialized |
currentVersion |
String? |
Current app version |
PatchInfo #
| Property | Type | Description |
|---|---|---|
version |
String |
Patch version |
downloadUrl |
String |
URL to download patch |
hash |
String |
SHA-256 hash for verification |
size |
int |
Compressed size in bytes |
releaseNotes |
String? |
Optional release notes |
critical |
bool |
Whether update is critical |
Exceptions #
| Exception | Description |
|---|---|
QuicUIConfigNotFoundException |
quicui.yaml not found |
QuicUIConfigInvalidException |
Invalid configuration |
QuicUIException |
Generic error |
Platform Support #
| Platform | Architecture | Status |
|---|---|---|
| Android | arm64-v8a | β Production Ready |
| Android | armeabi-v7a | β Production Ready |
| Android | x86_64 | β οΈ Emulator only |
| iOS | arm64 | π§ Coming Soon |
| Web | β | β Not Supported |
| Desktop | β | β Not Supported |
Environment Variables #
| Variable | Description |
|---|---|
QUICUI_API_KEY |
Override API key from yaml |
export QUICUI_API_KEY="your-custom-api-key"
Troubleshooting #
"quicui.yaml not found" #
Run quicui init in your Flutter project root:
cd your_flutter_app
quicui init
"API key missing" #
Either:
- Re-run
quicui initto regenerate - Set environment variable:
export QUICUI_API_KEY="your-key" - Add manually to
quicui.yamlunderserver.api_key
"SDK incompatible" / Updates not working #
You need the QuicUI Flutter SDK:
quicui engine download
Then build with: quicui release --version 1.0.0
Updates not applying #
Make sure to call restartApp() after successful downloadAndInstall():
final success = await quicui.downloadAndInstall(patch);
if (success) {
await quicui.restartApp(); // Don't forget this!
}
Network errors #
Check your server URL in quicui.yaml and ensure the device has internet access.
How It Works #
βββββββββββββββββββ βββββββββββββββββββ
β Your App β β QuicUI Server β
β (with client) β β (Supabase) β
ββββββββββ¬βββββββββ ββββββββββ¬βββββββββ
β β
β 1. Check for updates β
β βββββββββββββββββββββββββββββββββββββΆβ
β β
β 2. Patch info (version, URL, hash) β
β ββββββββββββββββββββββββββββββββββββββ
β β
β 3. Download patch file β
β βββββββββββββββββββββββββββββββββββββΆβ
β β
β 4. Compressed patch (~200KB) β
β ββββββββββββββββββββββββββββββββββββββ
β β
βΌ β
βββββββββββββββββββ β
β Decompress & β β
β Apply bspatch β β
ββββββββββ¬βββββββββ β
β β
βΌ β
βββββββββββββββββββ β
β Restart with β β
β new code β β
βββββββββββββββββββ
Security #
- Hash Validation β SHA-256 verification before installation
- Secure Transport β HTTPS for all API calls
- Signature Verification β Patches can be signed
- Automatic Rollback β Reverts on installation failure
- No Exposed Secrets β API keys stored securely
Related Projects #
| Project | Description | Link |
|---|---|---|
| QuicUI CLI | Command-line tool for building & deploying | github.com/Ikolvi/quicui-cli |
| QuicUI Server | Supabase backend for patches | github.com/Ikolvi/QuicUiServer |
| This Package | Flutter client SDK | github.com/Ikolvi/QuicUICodepush |
| pub.dev | Package on pub.dev | pub.dev/packages/quicui |
Example #
See the example directory for a complete working app.
cd example
flutter run
Contributing #
Contributions are welcome! Please check our GitHub Issues.
License #
BSD 3-Clause License - see LICENSE for details.
Made with β€οΈ by the QuicUI Team