292 lines
7.4 KiB
Markdown
292 lines
7.4 KiB
Markdown
# 📱 Aplikasi Absensi Akademik - Development Guide
|
|
|
|
## 📋 Ringkasan Perubahan dan Fitur yang Ditambahkan
|
|
|
|
Dokumentasi ini menjelaskan semua fitur yang telah dikembangkan dalam proyek starter ini.
|
|
|
|
---
|
|
|
|
## ✅ Fitur yang Sudah Diimplementasikan
|
|
|
|
### 1. **Autentikasi Pengguna (Login & Register)**
|
|
- Login dengan NPM dan Password
|
|
- Registrasi pengguna baru
|
|
- Validasi data input
|
|
- Toast notifications untuk feedback
|
|
|
|
### 2. **Pengambilan Data Lokasi (GPS)**
|
|
- Menggunakan Google Play Services Location API
|
|
- Otomatis mengambil last known location
|
|
- Menampilkan latitude dan longitude
|
|
- Handling permission requests
|
|
|
|
### 3. **Pengambilan Foto (Selfie)**
|
|
- Akses kamera perangkat
|
|
- Mengambil foto dengan kamera bawaan
|
|
- Menyimpan bitmap hasil foto
|
|
- Handling camera permissions
|
|
|
|
### 4. **Validasi Lokasi Berbasis Radius**
|
|
- ✨ **FITUR BARU**: Fungsi `isWithinAbsensiRadius()` untuk validasi lokasi
|
|
- Radius default: 100 meter dari UBH campus
|
|
- Lokasi default UBH: Lat -6.2030, Lon 107.0045
|
|
- Dapat dikustomisasi sesuai kebutuhan
|
|
|
|
### 5. **Obfuscasi Koordinat untuk Privacy**
|
|
- ✨ **FITUR BARU**: Fungsi `obfuscateCoordinates()`
|
|
- Menambahkan offset random pada koordinat
|
|
- Mencegah kebocoran lokasi rumah mahasiswa
|
|
- Offset default: 0.002 derajat (~200 meter)
|
|
|
|
### 6. **Penyimpanan Riwayat Absensi Lokal**
|
|
- ✨ **FITUR BARU**: Database table `attendance`
|
|
- Menyimpan: timestamp, latitude, longitude, status
|
|
- Tracking absensi yang diterima/ditolak
|
|
- Akses cepat tanpa koneksi internet
|
|
|
|
### 7. **Riwayat Absensi (History Screen)**
|
|
- ✨ **FITUR BARU**: Screen untuk melihat riwayat absensi
|
|
- Menampilkan list attendance dengan detail
|
|
- Status visual: ✓ Diterima (hijau) / ✗ Ditolak (merah)
|
|
- Sorting: Absensi terbaru di atas
|
|
- Formatted timestamp: dd/MM/yyyy HH:mm:ss
|
|
|
|
### 8. **Pengiriman Data ke n8n Webhook**
|
|
- Mengirim data ke webhook: `https://n8n.lab.ubharajaya.ac.id/webhook/...`
|
|
- Data yang dikirim:
|
|
- NPM & Nama mahasiswa
|
|
- Latitude & Longitude
|
|
- Foto dalam format Base64
|
|
- Timestamp
|
|
- Validation status
|
|
- Is within radius flag
|
|
- Error handling dengan try-catch
|
|
|
|
---
|
|
|
|
## 🗂️ Struktur Database
|
|
|
|
### Table: `users`
|
|
```sql
|
|
CREATE TABLE users (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
username TEXT,
|
|
npm TEXT UNIQUE,
|
|
password TEXT
|
|
)
|
|
```
|
|
|
|
### Table: `attendance` (NEW)
|
|
```sql
|
|
CREATE TABLE attendance (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
npm TEXT,
|
|
timestamp INTEGER,
|
|
latitude REAL,
|
|
longitude REAL,
|
|
status TEXT,
|
|
FOREIGN KEY(npm) REFERENCES users(npm)
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 Utility Functions
|
|
|
|
### `calculateDistance(lat1, lon1, lat2, lon2): Float`
|
|
Menghitung jarak dalam meter antara dua koordinat menggunakan formula haversine.
|
|
|
|
### `isWithinAbsensiRadius(studentLat, studentLon, campusLat, campusLon, radiusMeters): Boolean`
|
|
Mengecek apakah mahasiswa berada dalam radius absensi. Default: 100 meter dari UBH.
|
|
|
|
### `obfuscateCoordinates(latitude, longitude, offsetDegrees): Pair<Double, Double>`
|
|
Menambahkan offset random pada koordinat untuk privacy. Default offset: 0.002 derajat.
|
|
|
|
### `bitmapToBase64(bitmap): String`
|
|
Mengkonversi Bitmap foto ke String Base64 untuk pengiriman via JSON.
|
|
|
|
### `kirimKeN8n(context, db, npm, nama, latitude, longitude, foto)`
|
|
Mengirim data absensi ke webhook n8n dengan validasi dan penyimpanan lokal.
|
|
|
|
---
|
|
|
|
## 📱 Screen Navigation
|
|
|
|
```
|
|
┌─────────┐
|
|
│ LOGIN │ ←→ REGISTER
|
|
└────┬────┘
|
|
│
|
|
↓
|
|
┌──────────────┐
|
|
│ ABSENSI │ → HISTORY
|
|
│ (Ambil Foto, │ (Lihat Riwayat)
|
|
│ Ambil Lokasi,
|
|
│ Kirim Data) │
|
|
└──────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 🎯 Cara Menggunakan Aplikasi
|
|
|
|
### 1. **Registrasi Akun Baru**
|
|
- Klik "Belum punya akun? Daftar"
|
|
- Isi Nama Lengkap, NPM, dan Password
|
|
- Klik tombol "Daftar"
|
|
|
|
### 2. **Login**
|
|
- Masukkan NPM dan Password
|
|
- Klik tombol "Login"
|
|
|
|
### 3. **Melakukan Absensi**
|
|
- Aplikasi otomatis meminta izin lokasi
|
|
- Klik "📷 Ambil Foto" untuk mengambil selfie
|
|
- Foto akan ditampilkan (jika berhasil)
|
|
- Klik "Kirim Absensi" untuk mengirim data
|
|
- Sistem akan:
|
|
- Validasi lokasi (harus dalam radius 100m)
|
|
- Menyimpan ke database lokal
|
|
- Mengirim ke server n8n
|
|
- Menampilkan feedback status
|
|
|
|
### 4. **Melihat Riwayat**
|
|
- Klik tombol "Lihat Riwayat" di halaman absensi
|
|
- List akan menampilkan semua absensi dengan status
|
|
- Kembali ke halaman absensi dengan tombol back
|
|
|
|
---
|
|
|
|
## 🔐 Permissions yang Diperlukan
|
|
|
|
Aplikasi membutuhkan permissions berikut (di `AndroidManifest.xml`):
|
|
- `ACCESS_FINE_LOCATION` - Akses GPS presisi tinggi
|
|
- `ACCESS_COARSE_LOCATION` - Akses lokasi kasar
|
|
- `CAMERA` - Akses kamera
|
|
- `INTERNET` - Koneksi internet untuk webhook
|
|
|
|
---
|
|
|
|
## ⚙️ Konfigurasi yang Dapat Disesuaikan
|
|
|
|
### Campus Location (di `MainActivity.kt`)
|
|
```kotlin
|
|
fun isWithinAbsensiRadius(
|
|
studentLat: Double,
|
|
studentLon: Double,
|
|
campusLat: Double = -6.2030, // ← Ubah sesuai lokasi
|
|
campusLon: Double = 107.0045, // ← Ubah sesuai lokasi
|
|
radiusMeters: Float = 100f // ← Ubah radius (default 100m)
|
|
)
|
|
```
|
|
|
|
### Webhook URL (di `MainActivity.kt`)
|
|
```kotlin
|
|
val url = URL("https://n8n.lab.ubharajaya.ac.id/webhook/23c6993d-1792-48fb-ad1c-ffc78a3e6254")
|
|
// Ganti dengan URL production jika diperlukan
|
|
```
|
|
|
|
### Coordinate Obfuscation (di `MainActivity.kt`)
|
|
```kotlin
|
|
fun obfuscateCoordinates(
|
|
latitude: Double,
|
|
longitude: Double,
|
|
offsetDegrees: Double = 0.002 // ← Ubah offset (default ~200m)
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Data Flow
|
|
|
|
```
|
|
User Input (Foto + Lokasi)
|
|
↓
|
|
Validasi Lokasi (dalam radius?)
|
|
↓
|
|
├─ YA → Status: "success"
|
|
└─ TIDAK → Status: "invalid_location"
|
|
↓
|
|
Simpan ke Database Lokal
|
|
↓
|
|
Konversi Foto ke Base64
|
|
↓
|
|
Kirim JSON ke n8n Webhook
|
|
↓
|
|
Tampilkan Feedback ke User
|
|
↓
|
|
Data Tersimpan di Riwayat
|
|
```
|
|
|
|
---
|
|
|
|
## 🐛 Troubleshooting
|
|
|
|
### Lokasi tidak terdeteksi
|
|
- Pastikan GPS aktif di perangkat
|
|
- Beri izin lokasi ke aplikasi
|
|
- Tunggu beberapa detik untuk GPS lock
|
|
|
|
### Foto tidak terekam
|
|
- Pastikan kamera dan izin camera aktif
|
|
- Perangkat harus memiliki kamera depan
|
|
- Coba restart aplikasi
|
|
|
|
### Data tidak terkirim ke server
|
|
- Pastikan koneksi internet aktif
|
|
- Periksa webhook URL di code
|
|
- Data tetap tersimpan lokal dan bisa dikirim ulang
|
|
|
|
### Aplikasi crash saat login
|
|
- Pastikan database sudah terinisialisasi
|
|
- Clear app data dan coba lagi
|
|
|
|
---
|
|
|
|
## 📦 Dependencies
|
|
|
|
```gradle
|
|
// Compose UI
|
|
androidx.compose.ui
|
|
androidx.compose.material3
|
|
|
|
// Location Services
|
|
com.google.android.gms:play-services-location:21.0.1
|
|
|
|
// Material Icons
|
|
androidx.compose.material:material-icons-extended:1.6.0
|
|
|
|
// Core Android
|
|
androidx.activity:activity-compose:1.9.0
|
|
androidx.core:core-ktx
|
|
androidx.lifecycle:lifecycle-runtime-ktx
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 Langkah Selanjutnya (Optional Enhancements)
|
|
|
|
1. **Camera Preview**: Tampilkan preview kamera sebelum ambil foto
|
|
2. **Photo Gallery**: Simpan foto ke galeri perangkat
|
|
3. **Map Integration**: Tampilkan lokasi di Google Maps
|
|
4. **Biometric Auth**: Login dengan fingerprint
|
|
5. **Offline Queue**: Antrian pengiriman data saat offline
|
|
6. **Statistics**: Dashboard statistik absensi
|
|
7. **QR Code**: Verifikasi dengan QR code
|
|
|
|
---
|
|
|
|
## 📝 Development Notes
|
|
|
|
- Proyek menggunakan Jetpack Compose untuk UI
|
|
- Database menggunakan SQLite
|
|
- Location API menggunakan Google Play Services
|
|
- Thread untuk operasi jaringan agar tidak freeze UI
|
|
- Format tanggal Indonesia dengan `java.util.Locale("id", "ID")`
|
|
|
|
---
|
|
|
|
**Terakhir diupdate**: 14 Januari 2026
|
|
**Developer**: AI Assistant (GitHub Copilot)
|
|
|