vpn_connection_detector 2.0.1 copy "vpn_connection_detector: ^2.0.1" to clipboard
vpn_connection_detector: ^2.0.1 copied to clipboard

VPN connection detection for Flutter with native iOS & Android support. Includes real-time status stream & one-time checks.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:vpn_connection_detector/vpn_connection_detector.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'VPN Connection Detector Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _vpnDetector = VpnConnectionDetector();
  VpnInfo? _vpnInfo;
  bool _isChecking = false;

  @override
  void dispose() {
    _vpnDetector.dispose();
    super.dispose();
  }

  Future<void> _checkVpnInfo() async {
    setState(() => _isChecking = true);

    final info = await VpnConnectionDetector.getVpnInfo();

    setState(() {
      _vpnInfo = info;
      _isChecking = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('VPN Connection Detector'),
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // Stream-based detection
            _buildCard(
              title: 'Real-time VPN Status (Stream)',
              icon: Icons.stream,
              child: StreamBuilder<VpnConnectionState>(
                stream: _vpnDetector.vpnConnectionStream,
                builder: (context, snapshot) {
                  if (snapshot.hasError) {
                    return _buildStatusChip(
                      'Error: ${snapshot.error}',
                      Colors.red,
                      Icons.error,
                    );
                  }

                  if (!snapshot.hasData) {
                    return const Center(
                      child: CircularProgressIndicator(),
                    );
                  }

                  final isConnected =
                      snapshot.data == VpnConnectionState.connected;
                  return _buildStatusChip(
                    isConnected ? 'VPN Connected' : 'VPN Disconnected',
                    isConnected ? Colors.green : Colors.orange,
                    isConnected ? Icons.vpn_lock : Icons.vpn_lock_outlined,
                  );
                },
              ),
            ),

            const SizedBox(height: 16),

            // One-time check
            _buildCard(
              title: 'One-time VPN Check (Static)',
              icon: Icons.check_circle_outline,
              child: FutureBuilder<bool>(
                future: VpnConnectionDetector.isVpnActive(),
                builder: (context, snapshot) {
                  if (!snapshot.hasData) {
                    return const Center(child: CircularProgressIndicator());
                  }

                  final isActive = snapshot.data ?? false;
                  return _buildStatusChip(
                    isActive ? 'VPN Active' : 'VPN Inactive',
                    isActive ? Colors.green : Colors.orange,
                    isActive ? Icons.check_circle : Icons.cancel,
                  );
                },
              ),
            ),

            const SizedBox(height: 16),

            // Detailed VPN Info
            _buildCard(
              title: 'Detailed VPN Information',
              icon: Icons.info_outline,
              child: Column(
                children: [
                  if (_isChecking)
                    const CircularProgressIndicator()
                  else if (_vpnInfo != null)
                    _buildVpnInfoDetails(_vpnInfo!)
                  else
                    const Text('Tap button below to check VPN details'),
                  const SizedBox(height: 12),
                  ElevatedButton.icon(
                    onPressed: _isChecking ? null : _checkVpnInfo,
                    icon: const Icon(Icons.refresh),
                    label: const Text('Get VPN Info'),
                  ),
                ],
              ),
            ),

            const SizedBox(height: 16),

            // Current state
            _buildCard(
              title: 'Current Cached State',
              icon: Icons.cached,
              child: Text(
                _vpnDetector.currentState?.name ?? 'Not determined yet',
                style: Theme.of(context).textTheme.titleMedium,
                textAlign: TextAlign.center,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildCard({
    required String title,
    required IconData icon,
    required Widget child,
  }) {
    return Card(
      elevation: 2,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Icon(icon, size: 20),
                const SizedBox(width: 8),
                Text(
                  title,
                  style: Theme.of(context).textTheme.titleSmall?.copyWith(
                        fontWeight: FontWeight.bold,
                      ),
                ),
              ],
            ),
            const Divider(),
            Center(child: child),
          ],
        ),
      ),
    );
  }

  Widget _buildStatusChip(String label, Color color, IconData icon) {
    return Chip(
      avatar: Icon(icon, color: color, size: 20),
      label: Text(
        label,
        style: TextStyle(
          color: color,
          fontWeight: FontWeight.bold,
        ),
      ),
      backgroundColor: color.withOpacity(0.1),
      side: BorderSide(color: color.withOpacity(0.3)),
    );
  }

  Widget _buildVpnInfoDetails(VpnInfo info) {
    return Column(
      children: [
        _buildInfoRow(
          'Status',
          info.isConnected ? 'Connected' : 'Disconnected',
          info.isConnected ? Colors.green : Colors.orange,
        ),
        if (info.interfaceName != null)
          _buildInfoRow('Interface', info.interfaceName!, Colors.blue),
        if (info.vpnProtocol != null)
          _buildInfoRow('Protocol', info.vpnProtocol!, Colors.purple),
      ],
    );
  }

  Widget _buildInfoRow(String label, String value, Color color) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            '$label: ',
            style: const TextStyle(fontWeight: FontWeight.w500),
          ),
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
            decoration: BoxDecoration(
              color: color.withOpacity(0.1),
              borderRadius: BorderRadius.circular(4),
            ),
            child: Text(
              value,
              style: TextStyle(color: color, fontWeight: FontWeight.bold),
            ),
          ),
        ],
      ),
    );
  }
}
33
likes
160
points
4.81k
downloads

Publisher

unverified uploader

Weekly Downloads

VPN connection detection for Flutter with native iOS & Android support. Includes real-time status stream & one-time checks.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

connectivity_plus, flutter, plugin_platform_interface

More

Packages that depend on vpn_connection_detector

Packages that implement vpn_connection_detector