App Expiry
Ship with confidence. Lock the app until you get paid.
Set an expiry date. Ship your app. Everything else is handled.
Getting Started ยท API Reference ยท Customization ยท pub.dev โ
Overview
๐ Expiry Deadlline App |
๐ผ Branding Watermark |
ExpiryApp(
expiryDate: DateTime(2026, 12, 31),
child: const MyApp(),
)
That's it. One widget wraps everything.
โฆ Features
| ๐ Payment deadline gate | App locks on your terms โ no payment, no access |
| ๐จ Beautiful default UI | Animated lock screen with gradient, shown out of the box |
| ๐ Fully replaceable | Swap in your own expired widget with a single parameter |
| ๐ ExpiryService utility | Query remaining days or duration programmatically |
| ๐ผ Unpaid branding | Stamp every screen with your watermark until the client pays |
| ๐ชถ Zero extra dependencies | Pure Flutter โ nothing added to your dependency tree |
๐ฆ Getting Started
1. Install
# pubspec.yaml
dependencies:
flutter_app_expiry: ^latest-version
flutter pub get
2. Wrap your app
import 'package:flutter/material.dart';
import 'package:flutter_app_expiry/flutter_app_expiry.dart';
void main() {
runApp(
ExpiryApp(
expiryDate: DateTime(2026, 12, 31), // ๐ set your date
child: const MyApp(),
),
);
}
Done. The app runs normally until expiryDate โ then the lock screen takes over automatically.
๐จ Customization
Option A โ Use your own expired screen
ExpiryApp(
expiryDate: DateTime(2026, 12, 31),
expiredWidget: const MyCustomExpiredScreen(), // full control
child: const MyApp(),
)
Option B โ Customize the built-in screen
ExpiryApp(
expiryDate: DateTime(2026, 12, 31),
expiredTitle: 'Trial Ended',
expiredMessage: 'Please purchase a license to continue.',
contactInfo: 'support@yourapp.com',
child: const MyApp(),
)
Option C โ Embed DefaultExpiredScreen directly
DefaultExpiredScreen(
expiryDate: DateTime(2026, 12, 31),
title: 'License Expired',
message: 'Renew to keep going.',
contactInfo: 'hello@example.com',
)
๐ผ Watermark Overlay
Need to brand a demo build or remind unpaid clients they're on a trial? The watermark overlay floats above your entire app UI โ persistent, unobtrusive, and impossible to miss.
Common use cases:
- Demo apps โ make it clear the build isn't production-ready
- Unpaid clients โ reinforce that a license is still pending
- Internal builds โ distinguish staging from release
Text watermark (default)
ExpiryApp(
expiryDate: DateTime(2026, 12, 31),
watermark: WatermarkConfig(
text: 'DEMO',
color: Colors.red,
opacity: 0.15,
angle: -0.4,
repeat: true,
tileSpacing: 140.0,
),
child: const MyApp(),
)
Image watermark
Pass any asset image path via imagePath. Make sure the asset is declared in your pubspec.yaml.
ExpiryApp(
expiryDate: DateTime(2026, 12, 31),
watermark: WatermarkConfig(
imagePath: 'assets/logo.png', // your asset path
imageSize: Size(80, 80), // tile size (optional, default 80ร80)
opacity: 0.15,
angle: -0.4,
repeat: true,
tileSpacing: 140.0,
),
child: const MyApp(),
)
Note: When
imagePathis set,text,textStyle, andcolorare ignored โ image mode takes priority.
Single centered image (no tiling):
WatermarkConfig(
imagePath: 'assets/logo.png',
repeat: false, // renders once, centered
)
The watermark renders above your app's UI at all times and ignores all touch events so it never blocks user interaction.
๐งฎ ExpiryService
Need to react to expiry in your own logic? Use ExpiryService for programmatic checks:
final service = ExpiryService();
final expiry = DateTime(2026, 12, 31);
// Check expiry state
final expired = service.isExpired(expiry); // bool
// How much time is left?
final days = service.remainingDays(expiry); // int (e.g. 42)
final duration = service.remainingDuration(expiry); // Duration
Great for showing in-app banners like "Your trial expires in 7 days".
๐ API Reference
ExpiryApp
| Parameter | Type | Required | Description |
|---|---|---|---|
expiryDate |
DateTime |
โ | The date the app will be blocked |
child |
Widget |
โ | Your root app widget |
expiredWidget |
Widget? |
โ | Fully custom expired screen |
expiredTitle |
String? |
โ | Title on the default screen |
expiredMessage |
String? |
โ | Message on the default screen |
contactInfo |
String? |
โ | Contact text on the default screen |
watermark |
WatermarkConfig? |
โ | Watermark overlay for demo/trial branding |
expiredWidgettakes precedence โ if provided,expiredTitle,expiredMessage, andcontactInfoare ignored.
WatermarkConfig
| Parameter | Type | Default | Description |
|---|---|---|---|
text |
String? |
'DEMO' |
Text label shown as watermark. Ignored when imagePath is set. |
textStyle |
TextStyle? |
null |
Custom style for text. Falls back to color + 24sp bold. |
imagePath |
String? |
null |
Asset path to an image watermark (e.g. 'assets/logo.png'). Takes priority over text. |
imageSize |
Size |
Size(80, 80) |
Width and height of each image tile. |
opacity |
double |
0.15 |
Overall opacity of the watermark (0.0โ1.0). |
angle |
double |
-0.4 |
Rotation in radians. Negative = diagonal tilt. |
repeat |
bool |
true |
Tile the watermark across the whole screen. |
tileSpacing |
double |
140.0 |
Spacing between tiles when repeat is true. |
color |
Color |
Colors.grey |
Text color when no textStyle is provided. Text mode only. |
showOnExpiredScreen |
bool |
false |
Whether to show the watermark on the expired screen too. |
ExpiryService
| Method | Returns | Description |
|---|---|---|
isExpired(DateTime) |
bool |
true if the date has passed |
remainingDays(DateTime) |
int |
Full calendar days remaining |
remainingDuration(DateTime) |
Duration |
Precise duration until expiry |
๐ Project Structure
flutter_app_expiry/
โโโ lib/
โ โโโ flutter_app_expiry.dart # Public barrel export
โ โโโ src/
โ โโโ expiry_service.dart # Core expiry logic
โ โโโ expiry_screen.dart # Default animated UI
โ โโโ expiry_widget.dart # ExpiryApp wrapper widget
โ โโโ watermark_overlay.dart # Watermark overlay widget
โโโ example/
โ โโโ lib/main.dart
โโโ pubspec.yaml
โโโ CHANGELOG.md
โโโ README.md
โโโ LICENSE
๐ค Contributing
Issues and pull requests are welcome! If you find a bug or have a feature idea, please open an issue.
- Fork the repo
- Create your feature branch:
git checkout -b feat/amazing-thing - Commit your changes:
git commit -m 'feat: add amazing thing' - Push and open a PR
๐ License
MIT ยฉ see LICENSE for details.
Made with โฅ for the Flutter community
Libraries
- flutter_app_expiry
- A Flutter package to enforce app expiration (trial period) based on a specific date.