2026-01-14 19:31:41 +07:00

1117 lines
30 KiB
Markdown

# Aplikasi Absensi Akademik Berbasis Koordinat dan Foto
Sistem Absensi Mahasiswa Universitas Bhayangkara Jakarta Raya
Berbasis Android dengan validasi lokasi GPS dan foto real-time
---
## INFORMASI PROYEK
Nama : Rakha Adi Saputro
NPM : 202310715083
Mata Kuliah : Pemrograman Mobile
Universitas : Universitas Bhayangkara Jakarta Raya
Tahun : 2025-2026
---
## DESKRIPSI SISTEM
Aplikasi absensi mahasiswa modern berbasis Android yang mengimplementasikan arsitektur MVVM (Model-View-ViewModel) dengan pendekatan offline-first. Sistem ini memastikan validitas kehadiran mahasiswa melalui verifikasi lokasi GPS dan pengambilan foto selfie secara real-time saat melakukan absensi.
Fitur utama:
- Validasi lokasi berbasis GPS dengan radius 500 meter dari titik kampus
- Pengambilan foto selfie wajib saat absensi
- Penyimpanan data lokal dengan sinkronisasi otomatis ke backend
- Sistem login offline dengan enkripsi data
- Riwayat absensi tersimpan secara lokal
- Anti-spam: Satu foto untuk satu kali absensi
---
## DEPENDENCY LENGKAP (build.gradle.kts)
### Core Android
```kotlin
// AndroidX Core
implementation("androidx.core:core-ktx:1.17.0")
// Kotlin standard library dan extensions
```
### Jetpack Compose
```kotlin
// Compose BOM (Bill of Materials) - Mengelola versi Compose
implementation(platform("androidx.compose:compose-bom:2024.09.00"))
// Compose UI
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
// Material Design 3
implementation("androidx.compose.material3:material3")
// Material Icons Extended
implementation("androidx.compose.material:material-icons-extended:1.6.0")
```
### Lifecycle & ViewModel
```kotlin
// Lifecycle Runtime
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.9.4")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.7.0")
// ViewModel untuk Compose
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0")
```
### Activity & Navigation
```kotlin
// Activity untuk Compose
implementation("androidx.activity:activity-compose:1.9.0")
```
### Location Services
```kotlin
// Google Play Services Location
implementation("com.google.android.gms:play-services-location:21.0.1")
```
### Database (Room)
```kotlin
// Room components
implementation("androidx.room:room-runtime:2.6.1")
implementation("androidx.room:room-ktx:2.6.1")
kapt("androidx.room:room-compiler:2.6.1") // Annotation processor
```
### Network
```kotlin
// Retrofit
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
// OkHttp
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
```
### Security
```kotlin
// Encrypted SharedPreferences
implementation("androidx.security:security-crypto:1.1.0-alpha06")
```
### Background Work
```kotlin
// WorkManager
implementation("androidx.work:work-runtime-ktx:2.9.0")
```
### Coroutines
```kotlin
// Kotlin Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
```
### Image Loading
```kotlin
// Coil untuk Compose
implementation("io.coil-kt:coil-compose:2.6.0")
```
### JSON Processing
```kotlin
// Gson
implementation("com.google.code.gson:gson:2.10.1")
```
### Testing
```kotlin
// Unit Testing
testImplementation("junit:junit:4.13.2")
// Instrumented Testing
androidTestImplementation("androidx.test.ext:junit:1.3.0")
androidTestImplementation("androidx.test.espresso:espresso-core:3.7.0")
androidTestImplementation(platform("androidx.compose:compose-bom:2024.09.00"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
// Debug
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
```
### Gradle Plugins
```kotlin
plugins {
alias(libs.plugins.android.application) // AGP 8.13.2
alias(libs.plugins.kotlin.android) // Kotlin 2.0.21
alias(libs.plugins.kotlin.compose) // Compose Compiler
id("org.jetbrains.kotlin.kapt") // KAPT untuk Room
}
```
---
## ALASAN PEMILIHAN TEKNOLOGI
### Mengapa Jetpack Compose?
1. **Modern & Declarative**: Lebih intuitif dan less boilerplate dibanding XML
2. **Type-safe**: Compile-time error detection
3. **Reactive**: Automatic UI updates saat state berubah
4. **Performance**: Efficient rendering dengan recomposition
5. **Official**: Recommended oleh Google untuk new projects
6. **Community**: Strong community support dan active development
### Mengapa Room Database?
1. **Type-safe SQL**: Compile-time SQL query verification
2. **Coroutine Support**: Native async/await dengan suspend functions
3. **Reactive Queries**: Flow<T> untuk reactive updates
4. **Migration Support**: Easy database version management
5. **Performance**: Optimized SQLite wrapper
6. **Official**: Part of Android Jetpack
### Mengapa WorkManager?
1. **Guaranteed Execution**: Task akan dijalankan meski app tertutup
2. **Battery Efficient**: System-managed scheduling
3. **Constraints**: Network, battery, storage constraints
4. **Backward Compatible**: Works dari API 14+
5. **Retry Logic**: Built-in retry dengan backoff
6. **Official**: Recommended untuk background work
### Mengapa Retrofit + OkHttp?
1. **Type-safe**: Type-safe REST client
2. **Coroutine Support**: Native suspend functions
3. **Converter**: Auto JSON parsing dengan Gson
4. **Interceptor**: Logging, auth, retry logic
5. **Industry Standard**: Most popular Android HTTP client
6. **Maintained**: Active development dan support
### Mengapa Encrypted SharedPreferences?
1. **Security**: AES256-GCM encryption
2. **Hardware-backed**: Android Keystore System
3. **Transparent**: No manual encryption code needed
4. **Simple API**: Same as regular SharedPreferences
5. **Official**: Part of Jetpack Security
6. **Compliant**: Meets security best practices
### Mengapa Kotlin Coroutines?
1. **Lightweight**: Efficient thread management
2. **Structured Concurrency**: Prevents memory leaks
3. **Sequential Code**: Async code looks synchronous
4. **Exception Handling**: Structured exception propagation
5. **Cancellation**: Automatic cleanup
6. **Official**: First-class support in Android
### Mengapa Coil untuk Image Loading?
1. **Kotlin-first**: Written in Kotlin untuk Kotlin
2. **Compose-native**: AsyncImage composable
3. **Coroutine-based**: Non-blocking operations
4. **Modern**: Uses OkHttp, supports latest formats
5. **Lightweight**: Smaller APK size vs Glide/Picasso
6. **Fast**: Memory & disk caching
---
## PERBANDINGAN ALTERNATIF
### UI Framework
- **Jetpack Compose** vs XML Views
- Compose: Less code, reactive, modern
- XML: Mature, more resources, backward compatible
- **Pilihan**: Compose (future-proof, better DX)
### Database
- **Room** vs Realm vs SQLite
- Room: Type-safe, official, Jetpack integration
- Realm: Fast, cross-platform
- SQLite: Full control, verbose
- **Pilihan**: Room (best practices, official support)
### Image Loading
- **Coil** vs Glide vs Picasso
- Coil: Kotlin-first, Compose-native, modern
- Glide: Mature, feature-rich, large
- Picasso: Simple, lightweight, older
- **Pilihan**: Coil (best for Compose)
### HTTP Client
- **Retrofit** vs Ktor vs Volley
- Retrofit: Type-safe, widely used, mature
- Ktor: Kotlin-native, modern, less adoption
- Volley: Google-made, older, less features
- **Pilihan**: Retrofit (industry standard)
### State Management
- **StateFlow** vs LiveData vs RxJava
- StateFlow: Kotlin-native, Compose-friendly
- LiveData: Lifecycle-aware, older
- RxJava: Powerful, steep learning curve
- **Pilihan**: StateFlow (modern, simple, official)
---
## ARSITEKTUR APLIKASI
### Pattern & Struktur
MVVM (Model-View-ViewModel) dengan Offline-First Architecture
```
presentation/ UI Layer (Jetpack Compose)
├── auth/ Halaman Login & Registrasi
├── absensi/ Halaman Absensi Utama
└── history/ Halaman Riwayat Absensi
data/ Data Layer
├── local/ Local Storage
│ ├── database/ Room Database
│ ├── dao/ Data Access Object
│ └── entity/ Database Entity
├── repository/ Repository Pattern
├── network/ Network Service (n8n)
├── worker/ Background Sync Worker
└── model/ Data Models
utils/ Utility Classes
├── NetworkUtils Network Connection Check
└── ImageUtils Image Processing & Base64
```
---
## TEKNOLOGI & LIBRARY
### Platform & Bahasa
- **Platform**: Android
- **Bahasa**: Kotlin 2.0.21
- **Min SDK**: 28 (Android 9.0 Pie)
- Alasan: Support untuk Security Crypto, modern permission system, dan coverage market share yang memadai
- **Target SDK**: 36 (Android 14+)
- **Compile SDK**: 36
- **JDK**: Java 11 (source & target compatibility)
### UI Framework & Design System
**Jetpack Compose** - Modern Declarative UI Framework
- **Compose BOM**: 2024.09.00
- **androidx.compose.ui**: Core Compose UI
- **androidx.compose.ui.graphics**: Graphics primitives
- **androidx.compose.ui.tooling**: Preview & debugging tools
- **Keunggulan**:
- Less code dibanding XML
- Reactive & declarative
- Type-safe
- Hot reload support
- Interoperability dengan View system
**Material Design 3**
- **androidx.compose.material3**: Material Design 3 components
- **Components yang digunakan**:
- Scaffold (app structure)
- TopAppBar (navigation bar)
- Card (content containers)
- Button & OutlinedButton (actions)
- OutlinedTextField (form inputs)
- Text (typography)
- CircularProgressIndicator (loading states)
- AlertDialog (confirmations)
- **Fitur**: Dynamic color, adaptive layouts, modern color system
**Material Icons Extended**
- **Version**: 1.6.0
- **Library**: androidx.compose.material:material-icons-extended
- **Icons**: Person, Lock, Visibility, VisibilityOff, CameraAlt, MyLocation, History, Logout, Check, Close
- **Total Icons**: 2000+ icons tersedia
### Database & Storage Layer
**Room Database** - SQLite ORM (Object-Relational Mapping)
- **Version**: 2.6.1
- **Components**:
- **room-runtime**: Core library
- **room-ktx**: Kotlin extensions & coroutine support
- **room-compiler**: Annotation processor (KAPT)
- **Fitur yang digunakan**:
- @Entity (table definition)
- @Dao (data access object)
- @Query (SQL queries)
- @Insert, @Update, @Delete
- Flow<T> untuk reactive queries
- Suspend functions untuk coroutines
- Migration support
- **Table**: attendance_history
- **Keunggulan**: Compile-time verification, type-safe queries, reactive streams
**Encrypted SharedPreferences** - Secure Key-Value Storage
- **Library**: androidx.security:security-crypto:1.1.0-alpha06
- **Encryption**: AES256-GCM (Galois/Counter Mode)
- **Key Management**: MasterKey dengan Android Keystore System
- **Key Scheme**: AES256_GCM
- **Value Encryption**: AES256_GCM
- **Key Encryption**: AES256_SIV (Synthetic IV)
- **Fitur**: Transparent encryption/decryption, hardware-backed keys
- **Data yang disimpan**: Username, Password, isRegistered, isLogin (semua terenkripsi)
### Location Services
**Google Play Services Location**
- **Version**: 21.0.1
- **Library**: com.google.android.gms:play-services-location
- **API**: Fused Location Provider API
- **Fitur yang digunakan**:
- FusedLocationProviderClient (high-level API)
- LocationRequest (accuracy & interval settings)
- LocationCallback (location updates)
- Priority: PRIORITY_HIGH_ACCURACY
- **Validasi**:
- 12 campus points dengan koordinat GPS
- Haversine Formula untuk kalkulasi jarak
- Location.distanceBetween() (Android built-in)
- Max radius: 500 meter
- **Keunggulan**: Battery-efficient, most accurate location
### Network & Backend Integration
**Retrofit** - Type-safe HTTP Client
- **Version**: 2.9.0
- **Library**: com.squareup.retrofit2:retrofit
- **Fitur**: REST API calls, coroutine support, request/response converters
- **Usage**: POST data absensi ke n8n webhook
**Gson** - JSON Serialization/Deserialization
- **Gson Version**: 2.10.1
- **Retrofit Converter**: com.squareup.retrofit2:converter-gson:2.9.0
- **Fitur**: Automatic JSON parsing, custom type adapters
- **Usage**: Convert data objects ke JSON payload
**OkHttp** - HTTP Client & Interceptor
- **Version**: 4.11.0
- **Library**: com.squareup.okhttp3:logging-interceptor
- **Fitur**: HTTP logging, connection pooling, interceptors
- **Usage**: Debug network requests/responses, timeout configuration
- **Timeout Settings**: 30 detik connection & read timeout
**n8n Webhook Integration**
- **Backend**: n8n Self-hosted Workflow Automation
- **Host**: n8n.lab.ubharajaya.ac.id
- **Method**: HTTP POST
- **Content-Type**: application/json
- **Endpoint Production**: /webhook/23c6993d-1792-48fb-ad1c-ffc78a3e6254
- **Endpoint Testing**: /webhook-test/23c6993d-1792-48fb-ad1c-ffc78a3e6254
- **Payload**: JSON dengan foto Base64, koordinat, timestamp, mata kuliah
### Background Processing
**WorkManager** - Background Task Scheduler
- **Version**: 2.9.0
- **Library**: androidx.work:work-runtime-ktx
- **Fitur**:
- Guaranteed execution (even after app restart)
- Constraints (network, battery, storage)
- Retry logic dengan exponential backoff
- Work chaining
- CoroutineWorker integration
- **Usage**: AttendanceSyncWorker untuk sync data PENDING ke backend
- **Trigger**: Network available constraint
- **Strategy**: Periodic check & automatic retry
**Kotlin Coroutines** - Asynchronous Programming
- **Version**: 1.7.3
- **Library**: org.jetbrains.kotlinx:kotlinx-coroutines-android
- **Dispatchers**:
- **Dispatchers.Main**: UI operations & state updates
- **Dispatchers.IO**: Network requests & database operations
- **Dispatchers.Default**: CPU-intensive computations
- **Features**: suspend functions, async/await, structured concurrency
- **Usage**: Semua async operations (database, network, location)
**Flow & StateFlow** - Reactive Streams
- **Flow**: Cold stream untuk one-time operations
- **StateFlow**: Hot stream untuk UI state management
- **MutableStateFlow**: Mutable state holder
- **collectAsState()**: Compose integration untuk observe state
- **Usage**: ViewModel state management, database queries, UI updates
### Image Processing
**Coil** - Image Loading Library untuk Compose
- **Version**: 2.6.0
- **Library**: io.coil-kt:coil-compose
- **Fitur**:
- AsyncImage composable
- Memory & disk caching
- Image transformations
- Compose-first design
- Coroutine-based
- **Usage**: Load & display foto absensi di riwayat
**Custom Image Utils**
- **Base64 Encoding**: Convert Bitmap ke Base64 string
- **Bitmap Compression**: JPEG compression dengan quality 80%
- **File I/O**: Save/load foto dari internal storage
- **Camera Integration**: ActivityResultContracts.TakePicture()
- **Usage**: Prepare foto untuk kirim ke backend
### Architecture Components
**Lifecycle** - Lifecycle-Aware Components
- **lifecycle-runtime-ktx**: 2.9.4
- **lifecycle-runtime-compose**: 2.7.0
- **lifecycle-viewmodel-compose**: 2.7.0
- **Fitur**: LifecycleOwner, ViewModelScope, collectAsStateWithLifecycle
- **Usage**: Manage UI lifecycle, survive configuration changes
**ViewModel** - UI State Holder
- **Library**: androidx.lifecycle:lifecycle-viewmodel-compose
- **Features**: Survive configuration changes, ViewModelScope
- **ViewModels**: AuthViewModel, AbsensiViewModel, AttendanceHistoryViewModel
- **State Management**: StateFlow untuk expose state ke UI
**Activity Compose**
- **Version**: 1.9.0
- **Library**: androidx.activity:activity-compose
- **Features**: setContent {} untuk Compose, ComponentActivity, permission handling
- **Usage**: MainActivity sebagai entry point
### Build Tools & Gradle
**Gradle**
- **Version**: 8.13.2
- **Type**: Kotlin DSL (build.gradle.kts)
- **Plugin**: Android Gradle Plugin (AGP)
- **Features**: Dependency management, build variants, ProGuard/R8
**Kotlin Compiler**
- **Kotlin Version**: 2.0.21
- **Compose Compiler Plugin**: org.jetbrains.kotlin.plugin.compose
- **KAPT**: Kotlin Annotation Processing Tool (untuk Room compiler)
- **Target**: JVM 11
**Version Catalog**
- **File**: gradle/libs.versions.toml
- **Fitur**: Centralized dependency management, type-safe accessors
- **Benefits**: Single source of truth, easy updates, IDE support
### Testing Framework
**Unit Testing**
- **JUnit**: 4.13.2 (unit test framework)
- **Location**: src/test/java/
**Instrumented Testing**
- **AndroidX Test JUnit**: 1.3.0
- **Espresso Core**: 3.7.0
- **Compose UI Test**: androidx.compose.ui:ui-test-junit4
- **Location**: src/androidTest/java/
**Debug Tools**
- **Compose UI Tooling**: Preview & inspection
- **Compose UI Test Manifest**: Test configuration
### Utilities & Helpers
**NetworkUtils.kt**
- **Purpose**: Network connectivity checking
- **API**: ConnectivityManager
- **Usage**: Cek internet sebelum sync ke backend
**ImageUtils.kt**
- **Purpose**: Image processing & conversion
- **Functions**: bitmapToBase64, compression, file operations
- **Usage**: Prepare foto untuk upload
### Security & Permissions
**Android Permissions**
- ACCESS_FINE_LOCATION (GPS)
- ACCESS_COARSE_LOCATION (Network location)
- CAMERA (Take photos)
- INTERNET (Network communication)
**Security Features**
- Encrypted local storage
- HTTPS communication
- Hardware-backed key storage (Keystore)
- No hardcoded credentials
- Certificate transparency
---
## FITUR APLIKASI
### 1. SISTEM LOGIN OFFLINE
- Konsep: First-time setup dengan one-time registration
- Metode: Offline (tidak menggunakan server)
- Penyimpanan: Encrypted SharedPreferences
- Enkripsi: AES256-GCM dengan MasterKey
- Data tersimpan:
- Username (terenkripsi)
- Password (terenkripsi)
- isRegistered flag
- isLogin flag
- Flow:
- Pertama kali: Buat username & password
- Selanjutnya: Login dengan kredensial tersimpan
- Validasi: Dilakukan secara lokal
### 2. ABSENSI BERBASIS LOKASI
- Validasi radius: Maksimal 500 meter dari titik kampus
- Jumlah titik kampus: 12 lokasi strategis
- Titik kampus meliputi:
- Kampus Ubhara Jaya (Pusat)
- Fakultas Ilmu Komputer
- Fakultas Ekonomi dan Bisnis
- Fakultas Psikologi
- Perpustakaan Tanoto
- Grha Tanoto
- Masjid Ulul Albab
- Work Caffe Bekasi
- Lapangan Ubhara
- Sekretariat Kapal Baja
- Ruang Sedang Semu
- ATM BRI Ubhara Jaya
- Algoritma: Haversine Formula untuk hitung jarak
- Response: Menampilkan nama lokasi terdekat & jarak
### 3. PENGAMBILAN FOTO ABSENSI
- Mode: Kamera depan (selfie)
- Trigger: Langsung saat proses absensi
- Batasan: Satu foto untuk satu kali absensi (anti-spam)
- Penyimpanan: Internal storage aplikasi
- Format: JPEG dengan kompresi
- Pengiriman: Konversi ke Base64 untuk dikirim ke backend
### 4. PENYIMPANAN DATA LOKAL
Database: Room (SQLite)
Table: attendance_history
Schema:
- id: String (UUID, Primary Key)
- studentId: String (NPM mahasiswa)
- studentName: String (Nama mahasiswa)
- courseName: String (Nama mata kuliah)
- photoPath: String (Path foto di storage)
- dateTime: Long (Timestamp Unix)
- latitude: Double (Koordinat lintang)
- longitude: Double (Koordinat bujur)
- locationName: String (Nama lokasi terdekat)
- distanceMeter: Int (Jarak dari titik kampus)
- attendanceStatus: String (SUCCESS/FAILED)
- syncStatus: String (PENDING/SYNCED)
- createdAt: Long (Timestamp pembuatan)
### 5. SINKRONISASI BACKEND
- Service: n8n Webhook Automation
- Method: POST HTTP Request
- Format: JSON dengan foto Base64
- Strategy: Offline-first dengan background sync
- Worker: AttendanceSyncWorker (WorkManager)
- Retry: Otomatis saat koneksi internet tersedia
- Flow:
1. Simpan data ke local database
2. Cek koneksi internet
3. Jika online: Kirim langsung ke n8n
4. Jika offline: Tandai PENDING
5. Background worker cek pending data
6. Kirim ulang saat internet tersedia
7. Update status menjadi SYNCED
Payload ke n8n:
```json
{
"npm": "202310715083",
"nama": "Rakha Adi Saputro",
"mata_kuliah": "Nama Mata Kuliah",
"latitude": -6.224158,
"longitude": 107.009268,
"timestamp": "2025-01-14T10:30:00Z",
"foto_base64": "base64_encoded_image_string"
}
```
### 6. RIWAYAT ABSENSI
- Screen: AttendanceHistoryScreen
- Data source: Room Database (local)
- Layout: LazyColumn (efficient scrolling)
- Card components:
- Thumbnail foto absensi
- Nama mata kuliah
- Waktu absensi (formatted)
- Koordinat lokasi
- Jarak dari kampus
- Status sinkronisasi (PENDING/SYNCED)
- Filter: Semua data dari lokal
- Offline support: Full offline browsing
### 7. DATA MAHASISWA
Data mahasiswa yang digunakan fixed (hardcoded):
- NPM: 202310715083
- Nama: Rakha Adi Saputro
Catatan: Data ini tidak diambil dari login, tetapi langsung diset di aplikasi
---
## PERMISSIONS ANDROID
Aplikasi memerlukan izin berikut:
```xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA"/>
```
Hardware features:
```xml
<uses-feature android:name="android.hardware.camera" android:required="false"/>
```
---
## BACKEND INTEGRATION
### n8n Workflow Automation
- Platform: n8n (Self-hosted)
- Host: n8n.lab.ubharajaya.ac.id
- Endpoint Production: /webhook/23c6993d-1792-48fb-ad1c-ffc78a3e6254
- Endpoint Testing: /webhook-test/23c6993d-1792-48fb-ad1c-ffc78a3e6254
### Data Destination
1. Google Sheets
- URL: https://docs.google.com/spreadsheets/d/1jH15MfnNgpPGuGeid0hYfY7fFUHCEFbCmg8afTyyLZs
- Columns: NPM, Nama, Mata Kuliah, Latitude, Longitude, Timestamp, Foto
2. ntfy Notification Service
- URL: https://ntfy.ubharajaya.ac.id/EAS
- Purpose: Real-time notification untuk dosen/admin
### Workflow n8n
File: n8n-workflow-EAS.json
Flow:
1. Webhook Trigger (receive POST data)
2. Data Validation
3. Write to Google Sheets
4. Send notification via ntfy
5. Return response to mobile app
---
## STRUKTUR DATA FLOW
```
User Action (Absensi)
|
v
Validasi Lokasi GPS
|
v
Ambil Foto Selfie
|
v
Simpan ke Room Database (Local)
|
v
Update UI (Riwayat bertambah)
|
v
Cek Koneksi Internet
|
+---> [Online] ---> Kirim ke n8n Webhook
| |
| v
| Update syncStatus = SYNCED
|
+---> [Offline] ---> Set syncStatus = PENDING
|
v
WorkManager scheduled
|
v
[Internet tersedia]
|
v
Retry kirim data PENDING
|
v
Update syncStatus = SYNCED
```
---
## CARA KERJA SISTEM
### Flow Lengkap Absensi:
1. PERSIAPAN
- User buka aplikasi
- Jika belum login: tampilkan AuthScreen
- Jika sudah login: tampilkan AbsensiScreen
2. HALAMAN ABSENSI
- Tampilkan NPM dan Nama (hardcoded)
- Input mata kuliah
- Tombol ambil foto
- Request permissions (Camera & Location)
3. PROSES ABSENSI
- User klik tombol absensi
- Sistem cek permission camera
- Buka camera untuk selfie
- User ambil foto
- Foto ditampilkan sebagai preview
- Sistem ambil koordinat GPS otomatis
- Validasi jarak dari titik kampus
4. VALIDASI
- Cek jarak < 500 meter?
- Ya: Lanjut proses
- Tidak: Tampilkan error & batalkan
- Cek foto valid?
- Ya: Lanjut proses
- Tidak: Minta foto ulang
5. PENYIMPANAN
- Generate UUID untuk attendance ID
- Simpan foto ke internal storage
- Simpan data ke Room Database
- Set syncStatus = PENDING
6. SINKRONISASI
- Cek koneksi internet
- Jika online:
- Encode foto ke Base64
- Kirim POST ke n8n webhook
- Jika sukses: Update syncStatus = SYNCED
- Jika gagal: Tetap PENDING
- Jika offline:
- Skip sync
- Data tetap PENDING
- WorkManager akan retry nanti
7. BACKGROUND SYNC
- WorkManager cek setiap internet tersedia
- Ambil semua data PENDING
- Kirim satu per satu ke n8n
- Update status yang berhasil
- Retry yang gagal
8. RIWAYAT
- User bisa lihat semua absensi di HistoryScreen
- Data diambil dari Room Database
- Menampilkan status PENDING/SYNCED
- Full offline support
---
## KEAMANAN
### 1. Enkripsi Data
- Encrypted SharedPreferences dengan AES256-GCM
- MasterKey untuk enkripsi kredensial login
- Password tidak disimpan plain text
### 2. Validasi Lokasi
- Multi-point validation (12 titik kampus)
- Radius enforcement (500 meter maksimal)
- Real-time distance calculation
### 3. Anti-Fraud
- Satu foto untuk satu absensi
- Foto harus diambil real-time (tidak bisa dari gallery)
- Timestamp server-side di n8n
- Validasi koordinat di backend (opsional)
### 4. Offline Security
- Data lokal terenkripsi
- No sensitive data in plain text
- Secure file storage
---
## KONFIGURASI ENDPOINT
File: ApiConfig.kt
Location: data/network/ApiConfig.kt
```kotlin
object ApiConfig {
const val N8N_WEBHOOK_URL =
"https://n8n.lab.ubharajaya.ac.id/webhook/23c6993d-1792-48fb-ad1c-ffc78a3e6254"
// Untuk testing:
// const val N8N_WEBHOOK_URL =
// "https://n8n.lab.ubharajaya.ac.id/webhook-test/23c6993d-1792-48fb-ad1c-ffc78a3e6254"
const val CONNECTION_TIMEOUT = 30000 // 30 detik
const val READ_TIMEOUT = 30000 // 30 detik
}
```
Keuntungan centralized config:
- Mudah switch antara production & testing
- Tidak perlu ubah banyak file
- Maintenance lebih simple
- Deploy lebih aman
---
## ANDROID SDK CONFIGURATION
### SDK Versions
```kotlin
android {
compileSdk = 36
defaultConfig {
applicationId = "id.ac.ubharajaya.sistemakademik"
minSdk = 28
targetSdk = 36
versionCode = 1
versionName = "1.0"
}
}
```
### Min SDK 28 (Android 9.0 Pie) - Coverage & Features
**Alasan pemilihan Min SDK 28:**
1. **Market Coverage**: ~80% devices (2024-2025 data)
2. **Security Features**:
- Mandatory HTTPS
- BiometricPrompt API
- Security Crypto support
3. **Modern APIs**:
- ImageDecoder API
- DisplayCutout support
- Indoor positioning (WiFi RTT)
4. **Location Features**:
- Foreground location access
- Better battery optimization
5. **Camera Features**:
- Multi-camera API
- Session parameters
6. **Performance**:
- ART improvements
- Background restrictions
### Target SDK 36 (Android 14+) - Latest Features
**Benefits:**
1. Google Play requirement compliance
2. Latest security patches
3. Performance optimizations
4. New API features
5. Better battery management
6. Enhanced privacy controls
### Compile SDK 36
- Access to latest Android APIs
- Build tools compatibility
- Preview features
- Development libraries
### Java Compatibility
```kotlin
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
```
**Java 11 Features:**
- Lambda expressions
- Method references
- Stream API
- Optional class
- Try-with-resources
- Type inference (var)
---
## BUILD CONFIGURATION
### Build Types
#### Debug Build
```kotlin
buildTypes {
debug {
isMinifyEnabled = false
isDebuggable = true
applicationIdSuffix = ".debug"
versionNameSuffix = "-DEBUG"
}
}
```
**Features:**
- No code obfuscation
- Full logging enabled
- Faster build time
- Debug symbols included
- Network profiler enabled
#### Release Build
```kotlin
buildTypes {
release {
isMinifyEnabled = false // Set true for production
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
signingConfig = signingConfigs.getByName("release")
}
}
```
**Features:**
- Code shrinking (ProGuard/R8)
- Obfuscation
- Optimization
- Signing required
- Smaller APK size
### Build Features
```kotlin
buildFeatures {
compose = true
}
```
- Enables Jetpack Compose
- Compose compiler integration
- Preview support
### ProGuard/R8 Configuration
File: `proguard-rules.pro`
**Purpose:**
- Code shrinking (remove unused code)
- Obfuscation (rename classes/methods)
- Optimization (inline, etc.)
- APK size reduction
**Keep Rules for:**
- Room entities (@Entity)
- Retrofit interfaces
- Gson models
- Parcelable classes
### APK Outputs
**Debug APK:**
- Path: `app/build/outputs/apk/debug/app-debug.apk`
- Size: ~15-20 MB (with debug symbols)
- Command: `.\gradlew assembleDebug`
**Release APK:**
- Path: `app/build/outputs/apk/release/app-release.apk`
- Size: ~8-12 MB (minified)
- Command: `.\gradlew assembleRelease`
---
## GRADLE BUILD SYSTEM
### Requirements
- Android Studio Ladybug atau lebih baru
- JDK 11 atau lebih tinggi
- Android SDK 28-36
- Gradle 8.13.2
- Koneksi internet (untuk dependency download)
### Build Commands
Development Build:
```bash
.\gradlew assembleDebug
```
Release Build:
```bash
.\gradlew assembleRelease
```
Clean Build:
```bash
.\gradlew clean assembleDebug
```
Install ke Device:
```bash
.\gradlew installDebug
```
Run Tests:
```bash
.\gradlew test
```
### Output Location
APK Debug: app/build/outputs/apk/debug/app-debug.apk
APK Release: app/build/outputs/apk/release/app-release.apk
---
## TESTING
### Akun Testing
Saat pertama kali buka aplikasi:
- Buat username dan password bebas
- Data tersimpan secara offline
- Login selanjutnya gunakan kredensial tersebut
### Testing Lokasi
Opsi 1: Test di lokasi kampus (ideal)
Opsi 2: Mock location untuk development:
- Enable Developer Options
- Select mock location app
- Gunakan koordinat salah satu dari 12 titik kampus
### Testing n8n Webhook
Gunakan endpoint testing:
```
https://n8n.lab.ubharajaya.ac.id/webhook-test/23c6993d-1792-48fb-ad1c-ffc78a3e6254
```
Ganti di ApiConfig.kt untuk testing
### Monitoring
- Google Sheets: Cek data masuk
- ntfy: Cek notifikasi real-time
- Logcat: Monitor logs di Android Studio
---
## TROUBLESHOOTING
### Issue: Foto tidak terkirim ke backend
Solusi:
- Cek koneksi internet
- Cek endpoint n8n aktif
- Lihat syncStatus di riwayat (PENDING berarti belum terkirim)
- Background worker akan retry otomatis
### Issue: Lokasi tidak valid padahal di kampus
Solusi:
- Pastikan GPS aktif
- Tunggu GPS lock (butuh waktu)
- Cek permission lokasi granted
- Pastikan tidak menggunakan VPN yang mengubah lokasi
### Issue: Kamera tidak bisa dibuka
Solusi:
- Cek permission camera granted
- Restart aplikasi
- Pastikan camera tidak digunakan app lain
- Cek hardware camera berfungsi
### Issue: Data tidak tersimpan di database
Solusi:
- Cek storage permission
- Cek disk space mencukupi
- Lihat logcat untuk error Room
- Clear app data dan coba lagi
### Issue: WorkManager tidak sync
Solusi:
- Pastikan internet stabil
- Cek battery optimization (disable untuk app ini)
- Force sync dengan buka riwayat
- Restart device
---
### Author
- NAMA : RAKHA ADI SAPUTRO
- NPM : 202310715083