vpn_notice
English · Русский
Flutter package for detecting an active VPN connection and showing a notice on Android and iOS.
- 📱 Material on Android, Cupertino on iOS.
- ⚡ No state-management dependency.
- 🎨 Banner, snack bar, dialog, bottom sheet, or your own overlay.
Screenshots
The example app running on Android and iOS.

Quick start
flutter pub add vpn_notice
On Android, add this permission to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
iOS needs no extra configuration.
Put VpnNoticeGate around the screen where you want the notice to appear:
import 'package:flutter/material.dart';
import 'package:vpn_notice/vpn_notice.dart';
MaterialApp(
home: VpnNoticeGate(
displayType: VpnNoticeDisplayType.banner,
style: const VpnNoticeStyle(
title: 'VPN detected',
message: 'Some content may load differently while connected.',
),
child: const MyHomePage(),
),
);
Important
Place VpnNoticeGate below MaterialApp, not around it or in its builder.
The built-in presentations need a Navigator, ScaffoldMessenger, or
Overlay above their context.
Choose a presentation
| Type | Best for | Android | iOS |
|---|---|---|---|
banner |
Persistent, low-priority notice | Material banner | Blurred top card |
snackBar |
Brief feedback | Floating snack bar | Blurred bottom card |
dialog |
Acknowledgement required | Material dialog | Cupertino alert |
bottomSheet |
Extra context or an action | Material sheet | Cupertino sheet |
By default, the gate shows once. Set showOncePerSession: false to show it
again after each new VPN connection.
Customise the built-in UI
Use VpnNoticeStyle to set the text, icon, colours, text styles, border radius,
and padding. Anything you leave unset comes from the current platform theme.
const style = VpnNoticeStyle(
title: 'VPN detected',
message: 'Some content may load differently while connected.',
actionLabel: 'Got it',
backgroundColor: Colors.black,
foregroundColor: Colors.white,
icon: Icons.vpn_lock_outlined,
);
Pass the same style to any built-in presentation:
VpnNoticeBanner.show(context, style: style);
VpnNoticeSnackBar.show(context, style: style);
VpnNoticeDialog.show(context, style: style);
VpnNoticeBottomSheet.show(context, style: style);
Call VpnNoticeBanner.hide(context) to dismiss a banner. Snack bars close
after four seconds by default.
Build your own overlay
Use builder when the built-in layouts are not enough. It receives an overlay
context and a dismiss callback, so you decide how and where the notice is
shown on both platforms.
VpnNoticeGate(
builder: (context, dismiss) => Positioned(
top: MediaQuery.paddingOf(context).top + 12,
left: 16,
right: 16,
child: Material(
color: Colors.black,
borderRadius: BorderRadius.circular(12),
child: ListTile(
leading: const Icon(Icons.vpn_lock_outlined, color: Colors.white),
title: const Text(
'VPN detected',
style: TextStyle(color: Colors.white),
),
trailing: IconButton(
onPressed: dismiss,
icon: const Icon(Icons.close, color: Colors.white),
),
),
),
),
child: const MyHomePage(),
);
The runnable example has buttons for every built-in presentation and this custom overlay.
Use without a gate
For manual control, create a VpnNoticeController:
final controller = VpnNoticeController();
await controller.start();
if (controller.isVpnActive) {
VpnNoticeSnackBar.show(context);
}
await controller.stop(); // Or call dispose() if you own the controller.
Use await VpnNoticeController().checkOnce() for a one-off check, or listen to
the controller with ValueListenableBuilder.
Compatibility
| Platform | Minimum | Detection |
|---|---|---|
| Android | API 24 | NetworkCapabilities.TRANSPORT_VPN with interface fallback |
| iOS | 13.0 | System proxy settings with interface fallback |
Flutter >=3.44.1 and Dart ^3.12.1 are required. Other platforms do not have
a native implementation, so guard platform calls accordingly.
License
Libraries
- vpn_notice
- Detect an active VPN connection and show a customizable notice to the
user — banner, snackbar, dialog or bottom sheet — with zero third-party
Dart dependencies (native platform code + Flutter's own
plugin_platform_interfaceonly). - vpn_notice_method_channel
- vpn_notice_platform_interface