Compare commits
No commits in common. "3b76befdd29a6aab5ff0f605312d4a6776dbeda0" and "d3bb31488c693d25794c339ac0c1410718f39736" have entirely different histories.
3b76befdd2
...
d3bb31488c
13
.idea/deviceManager.xml
generated
13
.idea/deviceManager.xml
generated
@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DeviceTable">
|
|
||||||
<option name="columnSorters">
|
|
||||||
<list>
|
|
||||||
<ColumnSorterState>
|
|
||||||
<option name="column" value="Name" />
|
|
||||||
<option name="order" value="ASCENDING" />
|
|
||||||
</ColumnSorterState>
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
50
.idea/inspectionProfiles/Project_Default.xml
generated
50
.idea/inspectionProfiles/Project_Default.xml
generated
@ -1,50 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<profile version="1.0">
|
|
||||||
<option name="myName" value="Project Default" />
|
|
||||||
<inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="GlancePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="GlancePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="GlancePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewDeviceShouldUseNewSpec" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewParameterProviderOnFirstParameter" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
|
||||||
<option name="composableFile" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
</profile>
|
|
||||||
</component>
|
|
||||||
152
README.md
152
README.md
@ -1,102 +1,106 @@
|
|||||||
|
<div align="center">
|
||||||
|
|
||||||
# 📱 Aplikasi Absensi Akademik UBHARA Jaya
|
# 📱 Aplikasi Absensi Akademik UBHARA Jaya
|
||||||
|
### Mobile (Kotlin) & Backend (Python Flask)
|
||||||
|
|
||||||
[📋 Changelog](./CHANGELOG.md)
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
## 📌 Deskripsi Proyek
|
[📋 Lihat Changelog](./CHANGELOG.md)
|
||||||
Proyek ini merupakan **Tugas Project Akhir Mata Kuliah Pemrograman Mobile** yang mengimplementasikan sistem absensi akademik berbasis **Client-Server**. Aplikasi mobile dibangun menggunakan **Kotlin (Jetpack Compose)**, sedangkan sisi server menggunakan **Python Flask** dengan database **MySQL**.
|
|
||||||
|
|
||||||
Sistem ini dirancang dengan validasi ketat menggunakan **Geofencing (GPS)** dan **Deteksi Wajah (Face Detection)** untuk status kehadiran "Hadir", serta mendukung pengiriman bukti dokumen untuk status "Sakit/Izin". Seluruh data terintegrasi secara real-time ke **N8N Webhook** untuk pelaporan otomatis.
|
</div>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎯 Tujuan Proyek
|
## 📌 Deskripsi Proyek
|
||||||
- Mengimplementasikan arsitektur **REST API** antara Android dan Python Flask.
|
Proyek ini merupakan **Tugas Project Akhir Mata Kuliah Pemrograman Mobile** yang mengimplementasikan sistem absensi akademik berbasis **Client-Server**.
|
||||||
- Menerapkan **Face Detection** menggunakan CameraX untuk memvalidasi kehadiran fisik mahasiswa.
|
|
||||||
- Mencegah kecurangan absensi dengan fitur deteksi **Fake GPS**.
|
Sistem ini dirancang untuk validitas tinggi dengan mengintegrasikan:
|
||||||
- Mengelola status kehadiran otomatis (**Auto-Alfa**) pada server jika mahasiswa lupa absen.
|
* ✅ **Geofencing (GPS)** untuk validasi lokasi kampus.
|
||||||
- Melatih kemampuan Fullstack Mobile Development (Backend, Database, & Mobile UI).
|
* ✅ **Face Detection (CameraX)** untuk validasi biometrik kehadiran.
|
||||||
|
* ✅ **Anti-Fraud** untuk mendeteksi penggunaan *Fake GPS*.
|
||||||
|
* ✅ **Otomatisasi** pelaporan real-time ke **N8N Webhook**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📸 Tampilan Aplikasi (Mockup)
|
||||||
|
<div align="center">
|
||||||
|
<img src="Mockup.png" alt="Mockup Aplikasi Absensi" width="800">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Tujuan & Capaian
|
||||||
|
Proyek ini bertujuan untuk melatih kemampuan **Fullstack Mobile Development** dengan fokus pada:
|
||||||
|
1. **REST API Architecture**: Komunikasi aman antara Android dan Python Flask.
|
||||||
|
2. **Biometric Validation**: Implementasi ML Kit untuk deteksi wajah.
|
||||||
|
3. **Security Awareness**: Pencegahan kecurangan lokasi (*Mock Location*).
|
||||||
|
4. **Database Logic**: Penanganan status otomatis (*Auto-Alfa*) di sisi server.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Fitur Utama
|
## 🚀 Fitur Utama
|
||||||
|
|
||||||
### 📱 Sisi Mobile (Android - Jetpack Compose)
|
| Fitur | Deskripsi |
|
||||||
- **Modern UI**: Antarmuka modern menggunakan **Material3** & **Jetpack Compose**.
|
| :--- | :--- |
|
||||||
- **Smart Attendance**:
|
| **📱 Sisi Mobile** | • **Smart Attendance:** Validasi radius & wajah real-time.<br>• **Anti-Fraud:** Deteksi & blokir Fake GPS.<br>• **Mode Izin/Sakit:** Upload bukti dokumen tanpa validasi radius.<br>• **Riwayat:** Log kehadiran lengkap dengan foto bukti. |
|
||||||
- **Hadir**: Wajib berada di radius kampus & Wajib deteksi wajah (Real-time).
|
| **💻 Sisi Backend** | • **JWT Auth:** Keamanan token pada setiap request.<br>• **Auto-Alfa:** Menandai "TIDAK HADIR" otomatis jika telat.<br>• **N8N Integration:** Kirim data valid ke webhook untuk notifikasi.<br>• **Image Compression:** Optimasi penyimpanan foto (Base64). |
|
||||||
- **Sakit/Izin**: Wajib upload foto surat dokter/bukti (Tanpa validasi radius).
|
|
||||||
- **Anti-Fraud**: Sistem mendeteksi dan menolak jika pengguna mengaktifkan **Fake GPS/Mock Location**.
|
|
||||||
- **Riwayat & Bukti**: Mahasiswa dapat melihat riwayat kehadiran beserta foto bukti yang tersimpan di server.
|
|
||||||
- **Profil Mahasiswa**: Menampilkan data akademik dan fitur logout.
|
|
||||||
|
|
||||||
### 💻 Sisi Backend (Python Flask)
|
|
||||||
- **JWT Authentication**: Keamanan berbasis token untuk setiap request.
|
|
||||||
- **Auto-Alfa Trigger**: Sistem otomatis menandai "TIDAK HADIR" jika jam kuliah berakhir dan mahasiswa belum absen.
|
|
||||||
- **N8N Integration**: Data absensi yang valid dikirim otomatis ke webhook N8N untuk notifikasi/reporting.
|
|
||||||
- **Image Handling**: Kompresi foto (Base64) otomatis untuk efisiensi penyimpanan database.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🗺️ Mekanisme Absensi
|
## 🗺️ Mekanisme Alur Absensi
|
||||||
|
|
||||||
### 1. Absensi Status "HADIR"
|
### 🟢 1. Status "HADIR"
|
||||||
1. Mahasiswa memilih Jadwal Kelas yang aktif.
|
1. Mahasiswa memilih Jadwal Kelas aktif.
|
||||||
2. Sistem mengecek **GPS**:
|
2. **Validasi Sistem:**
|
||||||
- Apakah di dalam radius **500m** dari kampus?
|
* 📍 Lokasi dalam radius **500m**?
|
||||||
- Apakah terdeteksi aplikasi **Fake GPS**?
|
* 🚫 Tidak ada aplikasi **Fake GPS** aktif?
|
||||||
3. Sistem membuka **Kamera Deteksi Wajah**:
|
3. **Validasi Wajah:** Kamera terbuka, shutter hanya aktif jika wajah terdeteksi.
|
||||||
- Tombol shutter hanya aktif jika wajah terdeteksi.
|
|
||||||
4. Data (Lokasi + Foto Wajah) dikirim ke server.
|
4. Data (Lokasi + Foto Wajah) dikirim ke server.
|
||||||
|
|
||||||
### 2. Absensi Status "SAKIT / IZIN"
|
### 🟡 2. Status "SAKIT / IZIN"
|
||||||
1. Mahasiswa memilih status Sakit atau Izin.
|
1. Mahasiswa memilih status Sakit/Izin.
|
||||||
2. Validasi lokasi dilewati (bisa absen dari rumah/RS).
|
2. **Bypass Lokasi:** Validasi radius dilewati.
|
||||||
3. Sistem membuka **Kamera Dokumen** (Tanpa deteksi wajah).
|
3. **Dokumentasi:** Kamera dokumen terbuka (Tanpa deteksi wajah).
|
||||||
4. Mahasiswa memfoto surat keterangan.
|
4. Foto surat/bukti dikirim ke server.
|
||||||
5. Data dikirim ke server.
|
|
||||||
|
|
||||||
### 3. Logika Auto-Alfa (Server)
|
### 🔴 3. Logika Auto-Alfa (Server Side)
|
||||||
- Setiap kali jadwal dimuat, server mengecek jadwal yang `jam_selesai < jam_sekarang`.
|
> *Background Process*
|
||||||
- Jika mahasiswa belum ada record absensi pada jam tersebut, server otomatis menginput status **"TIDAK HADIR"**.
|
* Server memantau jadwal kuliah.
|
||||||
|
* Jika `jam_selesai < jam_sekarang` dan tidak ada data masuk ➔ Input otomatis **"TIDAK HADIR"**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠️ Teknologi yang Digunakan
|
## 🛠️ Tech Stack
|
||||||
- **Mobile Platform**: Android (Kotlin)
|
|
||||||
- **UI Framework**: Jetpack Compose
|
| Komponen | Teknologi |
|
||||||
- **Camera Engine**: CameraX + ML Kit (Face Analysis)
|
| :--- | :--- |
|
||||||
- **Backend Framework**: Python Flask
|
| **Mobile Platform** | Android (Kotlin) |
|
||||||
- **Database**: MySQL
|
| **UI Framework** | Jetpack Compose (Material3) |
|
||||||
- **Integrasi**: N8N Webhook
|
| **Camera & AI** | CameraX + ML Kit (Face Analysis) |
|
||||||
- **Protocol**: HTTP/REST (JSON)
|
| **Backend** | Python Flask |
|
||||||
- **AI**: Gemini & Claude (Sebagai Tools dalam Membantu Pengembangan)
|
| **Database** | MySQL |
|
||||||
|
| **Integrasi** | N8N Webhook |
|
||||||
|
| **AI Assistant** | Gemini & Claude (Development Tools) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔐 Izin Aplikasi (Permissions)
|
## ⚙️ Konfigurasi & Instalasi
|
||||||
Aplikasi memerlukan izin berikut:
|
|
||||||
- `INTERNET`: Koneksi ke Server API.
|
|
||||||
- `ACCESS_FINE_LOCATION`: Validasi koordinat presisi tinggi.
|
|
||||||
- `ACCESS_COARSE_LOCATION`: Validasi koordinat jaringan.
|
|
||||||
- `CAMERA`: Pengambilan foto bukti kehadiran & deteksi wajah.
|
|
||||||
|
|
||||||
---
|
### Prasyarat
|
||||||
|
* Python 3.x
|
||||||
|
* Android Studio (Ladybug/Latest)
|
||||||
|
* Koneksi jaringan yang sama (Laptop & HP)
|
||||||
|
|
||||||
## 📂 Mockup
|
### 1. Setup Backend
|
||||||

|
Pastikan server berjalan pada jaringan lokal:
|
||||||
|
```bash
|
||||||
|
# Install dependencies
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
## Catatan Konfigurasi:
|
# Jalankan server
|
||||||
- **Server**: Pastikan `app.py` berjalan (`python app.py`) pada jaringan yang sama dengan HP.
|
python app.py
|
||||||
- **Endpoint**: Sesuaikan `BASE_URL` pada file `MainActivity.kt` (Object `AppConstants`) dengan IP Laptop Anda.
|
|
||||||
```kotlin
|
|
||||||
const val BASE_URL = "[http://192.168.](http://192.168.)x.x:5000"
|
|
||||||
```
|
|
||||||
- **Fake GPS**: Pastikan mematikan aplikasi Mock Location saat pengujian fitur Hadir.
|
|
||||||
|
|
||||||
## Pengecekan & Monitoring:
|
|
||||||
- **Monitoring**: https://ntfy.ubharajaya.ac.id/EAS
|
|
||||||
- **Data Spreadsheet**: https://docs.google.com/spreadsheets/d/1jH15MfnNgpPGuGeid0hYfY7fFUHCEFbCmg8afTyyLZs/edit?gid=0#gid=0
|
|
||||||
|
|
||||||
## Webhook N8N:
|
|
||||||
- **Test**: https://n8n.lab.ubharajaya.ac.id/webhook-test/23c6993d-1792-48fb-ad1c-ffc78a3e6254
|
|
||||||
- **Production**: https://n8n.lab.ubharajaya.ac.id/webhook/23c6993d-1792-48fb-ad1c-ffc78a3e6254
|
|
||||||
@ -88,7 +88,7 @@ import androidx.compose.ui.unit.sp
|
|||||||
object AppConstants {
|
object AppConstants {
|
||||||
// Backend API URL - GANTI SESUAI SERVER ANDA
|
// Backend API URL - GANTI SESUAI SERVER ANDA
|
||||||
// const val BASE_URL = "http://10.0.2.2:5000" // Untuk emulator Android
|
// const val BASE_URL = "http://10.0.2.2:5000" // Untuk emulator Android
|
||||||
const val BASE_URL = "http://192.168.100.99:5000" // Untuk device fisik
|
const val BASE_URL = "http://192.168.xxx.xxx:5000" // Untuk device fisik
|
||||||
|
|
||||||
// Koordinat Kampus (UBHARA Jaya)
|
// Koordinat Kampus (UBHARA Jaya)
|
||||||
const val KAMPUS_LATITUDE = -6.223325
|
const val KAMPUS_LATITUDE = -6.223325
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
# Gunakan image Python yang ringan sebagai dasar
|
|
||||||
FROM python:3.9-slim
|
|
||||||
|
|
||||||
# Set working directory di dalam kontainer
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Salin file requirements.txt terlebih dahulu (untuk efisiensi cache Docker)
|
|
||||||
COPY requirements.txt .
|
|
||||||
|
|
||||||
# Install semua library yang dibutuhkan
|
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
|
||||||
|
|
||||||
# Salin seluruh file backend ke dalam kontainer
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Ekspos port 5000 agar bisa diakses dari luar kontainer
|
|
||||||
EXPOSE 5000
|
|
||||||
|
|
||||||
# Perintah untuk menjalankan server Flask
|
|
||||||
CMD ["python", "app.py"]
|
|
||||||
@ -24,7 +24,7 @@ CORS(app)
|
|||||||
DB_CONFIG = {
|
DB_CONFIG = {
|
||||||
'host': 'localhost',
|
'host': 'localhost',
|
||||||
'user': 'root',
|
'user': 'root',
|
||||||
'password': '',
|
'password': '@Rique03',
|
||||||
'database': 'db_absensi_akademik'
|
'database': 'db_absensi_akademik'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,9 +11,6 @@ pluginManagement {
|
|||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
plugins {
|
|
||||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0"
|
|
||||||
}
|
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
repositories {
|
repositories {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user