smart_selfie_capture 0.0.1+2 copy "smart_selfie_capture: ^0.0.1+2" to clipboard
smart_selfie_capture: ^0.0.1+2 copied to clipboard

A Flutter package for capturing selfies with face validation, object detection, and liveness checks. Includes customizable messages and real-time feedback.

example/lib/main.dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:smart_selfie_capture/smart_selfie_capture.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Smart Selfie Capture Demo',
      theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
      home: const DemoHomePage(),
    );
  }
}

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

  @override
  State<DemoHomePage> createState() => _DemoHomePageState();
}

class _DemoHomePageState extends State<DemoHomePage> {
  SelfieResult? _lastResult;

  void _openBasicSelfieCapture() {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => SelfieCaptureScreen(
          config: const SelfieConfig(
            title: 'Basic Selfie',
            subtitle: 'Take a simple selfie',
            enableLivenessCheck: true,
            livenessBlinkCount: 1,
            livenessCheckType: LivenessCheckType.mouthOpen,
          ),
          onCaptureComplete: (result) {
            setState(() {
              _lastResult = result;
            });
            Navigator.pop(context);
            _showResultDialog(result);
          },
        ),
      ),
    );
  }

  void _openAdvancedSelfieCapture() {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => SelfieCaptureScreen(
          config: SelfieConfig(
            title: 'Identity Verification',
            subtitle: 'Verify your identity',
            customMessage: 'Please ensure you are in a well-lit area',
            instructions: [
              'Remove glasses and hats',
              'Look directly at the camera',
              'Blink and open mouth when prompted',
            ],
            validationRules: const ValidationRules(
              requireFrontalFace: true,
              requireEyesOpen: true,
              requireSmile: false,
              minFaceSize: 0.4,
              maxFaceSize: 0.7,
              allowMultipleFaces: false,
            ),
            enableLivenessCheck: true,
            enableObjectDetection: true,
            primaryColor: Colors.deepPurple,
            backgroundColor: Colors.black87,
            livenessBlinkCount: 3,
            livenessCheckType: LivenessCheckType.both,
          ),
          onCaptureComplete: (result) {
            setState(() {
              _lastResult = result;
            });
            Navigator.pop(context);
            _showResultDialog(result);
          },
          onCancel: () {
            Navigator.pop(context);
            ScaffoldMessenger.of(
              context,
            ).showSnackBar(const SnackBar(content: Text('Capture cancelled')));
          },
        ),
      ),
    );
  }

  void _openSmileSelfie() {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => SelfieCaptureScreen(
          config: SelfieConfig(
            title: 'Smile Please!',
            subtitle: 'Capture your best smile',
            customMessage: '😊 Show us your beautiful smile!',
            instructions: [
              'Smile naturally',
              'Look at the camera',
              'Stay still when capturing',
            ],
            validationRules: const ValidationRules(
              requireFrontalFace: true,
              requireEyesOpen: true,
              requireSmile: true,
              minFaceSize: 0.35,
              maxFaceSize: 0.75,
            ),
            enableLivenessCheck: false,
            primaryColor: Colors.orange,
          ),
          onCaptureComplete: (result) {
            setState(() {
              _lastResult = result;
            });
            Navigator.pop(context);
            _showResultDialog(result);
          },
        ),
      ),
    );
  }

  void _showResultDialog(SelfieResult result) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Selfie Captured!'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            if (File(result.imagePath).existsSync())
              ClipRRect(
                borderRadius: BorderRadius.circular(8),
                child: Image.file(
                  File(result.imagePath),
                  height: 200,
                  width: double.infinity,
                  fit: BoxFit.cover,
                ),
              ),
            const SizedBox(height: 16),
            _buildInfoRow('Validated', result.isValidated ? '✓ Yes' : '✗ No'),
            _buildInfoRow(
              'Liveness Check',
              result.livenessCheckPassed ? '✓ Passed' : '✗ Failed',
            ),
            _buildInfoRow(
              'Timestamp',
              '${result.capturedAt.hour}:${result.capturedAt.minute}',
            ),
            const SizedBox(height: 8),
            const Text(
              'Validation Details:',
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
            ...result.validationDetails.entries.map(
              (e) => Padding(
                padding: const EdgeInsets.only(left: 8, top: 4),
                child: Text(
                  '${e.key}: ${e.value}',
                  style: const TextStyle(fontSize: 12),
                ),
              ),
            ),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('OK'),
          ),
        ],
      ),
    );
  }

  Widget _buildInfoRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Flexible(
            child: Text(
              label,
              style: const TextStyle(fontWeight: FontWeight.w500),
            ),
          ),
          Flexible(child: Text(value)),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Smart Selfie Capture Demo'),
        elevation: 2,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            const Text(
              'Choose a capture mode:',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 20),
            _DemoCard(
              title: 'Basic Selfie',
              description: 'Simple selfie capture with face detection',
              icon: Icons.camera_alt,
              color: Colors.blue,
              onTap: _openBasicSelfieCapture,
            ),
            const SizedBox(height: 12),
            _DemoCard(
              title: 'Advanced Verification',
              description:
                  'Full validation with liveness check and stricter rules',
              icon: Icons.verified_user,
              color: Colors.deepPurple,
              onTap: _openAdvancedSelfieCapture,
            ),
            const SizedBox(height: 12),
            _DemoCard(
              title: 'Smile Selfie',
              description: 'Capture with smile detection',
              icon: Icons.sentiment_satisfied_alt,
              color: Colors.orange,
              onTap: _openSmileSelfie,
            ),
            const SizedBox(height: 24),
            if (_lastResult != null) ...[
              const Divider(),
              const SizedBox(height: 16),
              const Text(
                'Last Capture:',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 12),
              Card(
                child: Padding(
                  padding: const EdgeInsets.all(12),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      if (File(_lastResult!.imagePath).existsSync())
                        ClipRRect(
                          borderRadius: BorderRadius.circular(8),
                          child: Image.file(
                            File(_lastResult!.imagePath),
                            height: 150,
                            width: double.infinity,
                            fit: BoxFit.cover,
                          ),
                        ),
                      const SizedBox(height: 12),
                      _buildInfoRow(
                        'Status',
                        _lastResult!.isValidated
                            ? '✓ Validated'
                            : '✗ Not Validated',
                      ),
                      _buildInfoRow(
                        'Liveness',
                        _lastResult!.livenessCheckPassed
                            ? '✓ Passed'
                            : '✗ Failed',
                      ),
                      _buildInfoRow('Path', _lastResult!.imagePath),
                    ],
                  ),
                ),
              ),
            ],
          ],
        ),
      ),
    );
  }
}

class _DemoCard extends StatelessWidget {
  final String title;
  final String description;
  final IconData icon;
  final Color color;
  final VoidCallback onTap;

  const _DemoCard({
    required this.title,
    required this.description,
    required this.icon,
    required this.color,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 2,
      child: InkWell(
        onTap: onTap,
        borderRadius: BorderRadius.circular(12),
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Row(
            children: [
              Container(
                padding: const EdgeInsets.all(12),
                decoration: BoxDecoration(
                  color: color.withValues(alpha: 0.1),
                  borderRadius: BorderRadius.circular(12),
                ),
                child: Icon(icon, color: color, size: 32),
              ),
              const SizedBox(width: 16),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      title,
                      style: const TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    const SizedBox(height: 4),
                    Text(
                      description,
                      style: TextStyle(fontSize: 14, color: Colors.grey[600]),
                    ),
                  ],
                ),
              ),
              Icon(Icons.arrow_forward_ios, color: Colors.grey[400], size: 16),
            ],
          ),
        ),
      ),
    );
  }
}
1
likes
160
points
1
downloads

Publisher

verified publisheraishayy.com

Weekly Downloads

A Flutter package for capturing selfies with face validation, object detection, and liveness checks. Includes customizable messages and real-time feedback.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

camera, flutter, google_mlkit_face_detection, google_mlkit_object_detection, image, path, path_provider, plugin_platform_interface

More

Packages that depend on smart_selfie_capture

Packages that implement smart_selfie_capture