A Flutter-based admin application for the ZeroProxy Smart Attendance System. This app allows administrators and teachers to manage sessions, register students with facial recognition, view live attendance, and export attendance data.
- System Overview
- Project Structure
- Getting Started
- Features & Screens
- Key Technical Concepts
- Dependencies
ZeroProxy is an attendance platform that uses a local Wi-Fi hotspot, facial recognition, and cryptographic integrity checks to prevent proxy attendance.
This repository contains ZeroProxy Admin, the Flutter app used by staff. It communicates with a secure Node.js server (running on a Raspberry Pi or local server) over a local network.
zeroproxy_admin/
│
├── lib/
│ ├── main.dart # App entry point
│ ├── app.dart # MaterialApp, global theme (Poppins font, brand colors)
│ │
│ ├── core/
│ │ ├── constants/
│ │ │ └── app_constants.dart # serverUrl, adminToken, Admin_Password
│ │ └── network/
│ │ ├── secure_http_client.dart # TLS-pinned HTTP client factory
│ │ └── network_error_handler.dart # Classifies exceptions → user-friendly messages
│ │
│ ├── features/
│ │ ├── dashboard/screens/
│ │ │ └── dashboard_screen.dart # Home: stats, session banner, nav grid, offline banner
│ │ │
│ │ ├── session/screens/
│ │ │ ├── live_session_screen.dart # Real-time attendance view (polls every 3s)
│ │ │ ├── manage_session_screen.dart # Browse/edit all past sessions (polls every 5s)
│ │ │ └── registered_students_screen.dart # Paginated student list, lazy-load images
│ │ │
│ │ ├── registration/
│ │ │ ├── screens/
│ │ │ │ ├── registration_screen.dart # Enroll new student: capture → detect → upload
│ │ │ │ ├── image_preview_screen.dart # Overlay detected face bounding boxes
│ │ │ │ └── cropped_faces_form.dart # Student ID + password form after face crop
│ │ │ └── widgets/
│ │ │ └── face_painter.dart # CustomPainter to draw face bounding boxes
│ │ │
│ │ └── export/screens/
│ │ └── export_screen.dart # Select sessions → CSV ZIP or Google Sheets export
│ │
│ ├── services/ml/
│ │ └── recognizer.dart # TFLite FaceNet model wrapper (512-dim embeddings)
│ │
│ └── shared/
│ ├── screens/
│ │ └── success_screen.dart # Shown after successful student registration
│ └── widgets/
│ ├── wifi_status_indicator.dart # Polls /wifi-status, shows online/offline badge
│ └── offline_banner.dart # OfflineBanner (top bar) + NetworkErrorState (full screen)
│
├── assets/
│ ├── face_net.tflite # FaceNet model for on-device face embedding
│ ├── admin_app_logo.png / LOGO.jpg # Brand assets
│ ├── certs/server.crt # TLS certificate (must match the server's cert)
│ └── fonts/ # Poppins Regular, SemiBold, Bold
└── pubspec.yaml
| Tool | Version |
|---|---|
| Flutter SDK | ^3.10.4 (Dart ^3.10.4) |
| ZeroProxy Server | A running instance of the ZeroProxy backend server |
Configure the app to connect to your ZeroProxy server:
String serverUrl = "https://172.16.0.1:8080"; // The zero-proxy server's IP and port
String adminToken = "YOUR_ADMIN_TOKEN"; // Must match the server's ADMIN_TOKEN
String Admin_Password = 'YOUR_UI_PASSWORD'; // Password for sensitive in-app actions (e.g. Syncing subjects)
⚠️ Security Note: These values are hardcoded for ease-of-use on a closed local network.
The app uses SecureHttpClient to securely communicate with the local server.
- Obtain the
server.crtfile from your backend server administrator. - Place the
server.crtfile into theassets/certs/directory of this Flutter project. - Run
flutter pub getto ensure the asset is loaded.
# Get dependencies
flutter pub get
# Run on a connected device or emulator
flutter runNote: To connect to the backend, the device running this app must be on the same Wi-Fi network as the ZeroProxy server.
- Greeting header with current date/time.
- Wi-Fi status indicator (shows live connectivity status of the server).
- Session banner — shows the currently active course or a "Start New Session" button.
- Stats row: Total Sessions, Total Students, Today's Sessions (auto-refreshes every 10s).
- Offline banner — displayed below the header if the server is unreachable, with a Retry button.
- Auto-refresh on resume — data is re-fetched whenever the app comes back from the background.
- Navigation grid to access all major features.
- Polls the server every 3 seconds with a 5-second timeout per request.
- Shows the current course, date, start time, and total attendance count.
- Lists every attendance record with the student ID and exact time they marked present.
- If polling fails mid-view (e.g. Wi-Fi drops), existing data stays visible with an offline banner — the screen never goes blank.
- View full attendance history organized in an expandable hierarchy (Course → Session → Student Record).
- Polls every 5 seconds; auto-refreshes on app resume.
- Keeps showing existing data with an offline banner if connectivity drops mid-use.
- Delete session with confirmation dialog.
- Manually add a student to a session (for fallback scenarios).
- Remove a student from a session.
- Paginated list of all registered students.
- Search by Student ID and filter by enrolled subject dynamically.
- Lazy image loading — student photos are only retrieved from the server when tapping to view details, saving bandwidth.
- Bottom sheet profile view: Student ID, admission year, branch code, and enrolled subjects.
- Sync subjects from Google Sheets (protected by the
Admin_Password). - Delete a student record.
- Step 1 — Face Capture: Opens the camera, uses
google_mlkit_face_detectionto find faces, and draws bounding boxes overlaying the camera feed. - Uses an on-device FaceNet TFLite model (
services/ml/recognizer.dart) to convert the cropped face into a 512-dimensional embedding array. - Step 2 — Student Details: Enter the Student ID and assign a password.
- Sends the student ID, hashed password, compressed image, and 512-dim embedding to the backend.
- Checkbox-based session selector to pick specific sessions to export.
- CSV ZIP Download — Downloads a
.zipfile of.csvattendance reports directly to the device. - Export & Clear to Google Sheets — Pushes selected sessions to the institution's Google Sheets and permanently clears those records from the local database.
All network requests go through SecureHttpClient.create(). This custom HTTP client loads the bundled server.crt and configures an IOClient that explicitly trusts only that certificate. This prevents Man-in-the-Middle (MITM) attacks on the local Wi-Fi network.
All HTTP calls include explicit timeouts (8s for data requests, 30s for CSV downloads) to prevent the app from hanging indefinitely if the server is unreachable. Errors are handled at two levels:
NetworkErrorHandler(core/network/network_error_handler.dart) — classifies any caught exception into a clean, user-facing message. Distinguishes between no connectivity (SocketException), request timeouts (TimeoutException), TLS failures, and server errors.OfflineBanner— a slim yellow banner shown at the top of a screen when polling fails mid-use. Existing data remains visible; the user is not thrown to a blank error screen.NetworkErrorState— a full-screen error widget (icon + message + retry button) used only when the initial data load fails and there is nothing to show yet.WidgetsBindingObserver— the Dashboard and Manage Sessions screens listen forAppLifecycleState.resumedand automatically refresh their data when the app returns from the background.
To reduce server load, facial embeddings are generated on the device during student registration.
- The camera captures an image.
google_mlkit_face_detectionlocates the face bounding box.- The image is cropped to just the face using
dart:ui. tflite_flutterruns inference onassets/face_net.tfliteto output a 512-float vector.- This vector is uploaded to the server to act as the student's biometric signature.
| Package | Purpose |
|---|---|
google_mlkit_face_detection |
On-device face detection during registration |
tflite_flutter |
Run the FaceNet TFLite model to generate embeddings |
image |
Image manipulation and processing (face cropping) |
image_picker |
Camera access for photo capture |
http |
Core networking library |
device_info_plus |
Read device/platform information |
permission_handler |
Manage dynamic Camera and Storage permissions |
path_provider |
Access temporary / documents directories for file operations |
flutter_file_dialog |
Native "Save File" dialog for CSV zip exports |
open_filex |
Open downloaded or exported files natively |
flutter_staggered_animations |
Smooth list entry animations |
intl |
Date/time and currency formatting |
cupertino_icons |
iOS style icons |







