EAS-202310715082-FAZRI-ABDU.../PANDUAN_IMPLEMENTASI.md

13 KiB
Raw Permalink Blame History

📖 Panduan Implementasi Aplikasi Absensi Akademik

🎯 Gambaran Umum Implementasi

Aplikasi ini telah diimplementasikan dengan arsitektur yang modular dan clean, memisahkan concerns menjadi beberapa layers:

  1. UI Layer (Compose Components)
  2. Network Layer (API Communication)
  3. Utils Layer (Business Logic)
  4. Config Layer (Configuration Management)
  5. Models Layer (Data Classes)

📂 File Structure Lengkap

Core Application

MainActivity.kt                    # Entry point & main UI screen

Configuration

config/
  └─ AttendanceConfig.kt          # Centralized configuration

Data Models

models/
  └─ AttendanceRecord.kt          # Data classes:
                                   # - AttendanceRecord
                                   # - LocationData
                                   # - ValidationResult
                                   # - AttendanceState
                                   # - ValidationStatus enum

Network Communication

network/
  └─ N8nService.kt                # API service untuk N8n webhook

Utilities

utils/
  ├─ LocationValidator.kt         # Location validation logic:
                                   # - calculateDistance (Haversine)
                                   # - isLocationValid
                                   # - getValidationMessage
                                   # - adjustCoordinates
  └─ ErrorHandler.kt              # Error handling & messages

UI Components

ui/
  ├─ components/
  │   └─ AttendanceComponents.kt   # Reusable components:
  │                                 # - PhotoPreviewCard
  │                                 # - LocationStatusCard
  │                                 # - ErrorAlertCard
  │                                 # - SubmitButtonWithLoader
  └─ theme/
      ├─ Theme.kt                 # Material 3 theme
      ├─ Color.kt                 # Color definitions
      └─ Type.kt                  # Typography definitions

Tests

test/
  └─ java/id/ac/ubharajaya/sistemakademik/
      └─ utils/
          └─ LocationValidatorTest.kt  # Unit tests

🔄 Flow Diagram

┌─────────────────────────────────────────────────────────────┐
│                      MainActivity                           │
│  (Jetpack Compose UI + State Management)                   │
└────────────────────┬────────────────────────────────────────┘
                     │
         ┌───────────┴───────────┐
         │                       │
    ┌────▼─────────┐      ┌──────▼──────────┐
    │ Location     │      │ Camera          │
    │ Permissions  │      │ Permissions     │
    └────┬─────────┘      └──────┬──────────┘
         │                       │
    ┌────▼──────────────────────▼────┐
    │   LocationValidator            │
    │  (Haversine distance calc)      │
    └────┬─────────────────────────────┘
         │
    ┌────▼──────────────────────────┐
    │  Validation Result            │
    │  (Valid/Invalid)              │
    └────┬─────────────────────────┘
         │
    ┌────▼────────────────────────────────┐
    │  N8nService                         │
    │  (HTTP POST to Webhook)             │
    └────┬────────────────────────────────┘
         │
    ┌────▼────────────────────┐
    │  N8n Server             │
    │  (Webhook Processing)   │
    └─────────────────────────┘

🚀 Penggunaan Aplikasi

Alur Pengguna

  1. Buka Aplikasi → MainActivity dimuat
  2. Minta Izin Lokasi → LocationPermissionLauncher diaktifkan otomatis
  3. Ambil Lokasi → Fused Location Provider mengambil GPS
  4. Validasi Lokasi → LocationValidator mengecek jarak
  5. Tampilkan Status → LocationStatusCard menampilkan hasil
  6. Ambil Foto → CameraPermissionLauncher + Intent Camera
  7. Preview Foto → PhotoPreviewCard menampilkan hasil
  8. Validasi Data → Cek semua field terpenuhi
  9. Kirim Data → N8nService POST ke webhook
  10. Tampilkan Hasil → Success/Error message

⚙️ State Management

AttendanceState Data Class

data class AttendanceState(
    val location: LocationData? = null,              // GPS coordinates
    val foto: Bitmap? = null,                        // Camera image
    val isLoadingLocation: Boolean = false,          // GPS acquiring
    val isLoadingSubmit: Boolean = false,            // API submitting
    val validationResult: ValidationResult = ...,    // Location validation
    val errorMessage: String? = null,                // Error feedback
    val isLocationPermissionGranted: Boolean = false,
    val isCameraPermissionGranted: Boolean = false
)

State Updates

State diupdate secara reactive menggunakan:

var state by remember { mutableStateOf(AttendanceState()) }
state = state.copy(location = newLocation)  // Immutable update

📍 Validasi Lokasi Detil

Haversine Formula

Untuk menghitung jarak akurat antara dua koordinat:

Formula:
a = sin²(Δφ/2) + cos(φ1) × cos(φ2) × sin²(Δλ/2)
c = 2 × atan2(√a, √(1a))
d = R × c

Di mana:
- φ adalah latitude (dalam radian)
- λ adalah longitude (dalam radian)
- R adalah radius bumi (6,371 km)

Contoh Validasi

// Referensi lokasi kampus
const val REFERENCE_LATITUDE = -7.0
const val REFERENCE_LONGITUDE = 110.4

// Lokasi mahasiswa (dari GPS)
val studentLatitude = -7.0035
val studentLongitude = 110.4042

// Hitung jarak
val distance = LocationValidator.calculateDistance(
    REFERENCE_LATITUDE, REFERENCE_LONGITUDE,
    studentLatitude, studentLongitude
)
// Result: ~500 meter

// Validasi terhadap radius (100m)
val isValid = distance <= 100.0  // false

📡 API Integration Detail

Request Format

{
  "npm": "202310715082",
  "nama": "Fazri Abdurrahman",
  "latitude": -7.0035,
  "longitude": 110.4042,
  "timestamp": 1705250400000,
  "foto_base64": "iVBORw0KGgoAAAANSUhEUgAAAAEA..."
}

Response Handling

HttpURLConnection.HTTP_OK (200)        // Success - absensi diterima
HttpURLConnection.HTTP_BAD_REQUEST (400)  // Error - data invalid
HttpURLConnection.HTTP_UNAUTHORIZED (401) // Error - auth failed
HttpURLConnection.HTTP_INTERNAL_ERROR (500) // Error - server error

Error Callback

interface SubmitCallback {
    fun onSuccess(responseCode: Int, message: String)
    fun onError(error: Throwable, message: String)
}

🎨 UI Components Detail

1. PhotoPreviewCard

PhotoPreviewCard(
    bitmap = state.foto,           // Bitmap dari camera
    onRetake = { /* reset foto */ }
)
  • Menampilkan preview foto
  • Button "Ambil Ulang" untuk mengganti foto
  • Placeholder jika belum ada foto

2. LocationStatusCard

LocationStatusCard(
    latitude = state.location?.latitude,
    longitude = state.location?.longitude,
    validationMessage = state.validationResult.message,
    isLoading = state.isLoadingLocation
)
  • Menampilkan koordinat GPS
  • Pesan validasi (✓ valid atau ✗ invalid)
  • Loading spinner saat mengambil lokasi

3. ErrorAlertCard

ErrorAlertCard(
    message = state.errorMessage,
    onDismiss = { /* hide error */ }
)
  • Card merah untuk error messages
  • Dismissable dengan tombol X
  • Auto-hide saat tidak ada error

4. SubmitButtonWithLoader

SubmitButtonWithLoader(
    text = "Kirim Absensi",
    onClick = { /* submit */ },
    isLoading = state.isLoadingSubmit,
    isEnabled = canSubmit
)
  • Button dengan loading indicator
  • Disabled saat proses
  • Spinner bertekstur saat loading

🔐 Permission Handling

Automatic Permission Request

LaunchedEffect(Unit) {
    locationPermissionLauncher.launch(
        Manifest.permission.ACCESS_FINE_LOCATION
    )
}
  • Dipanggil otomatis saat app launch
  • Request CAMERA saat user klik "Ambil Foto"

Permission Check

if (ContextCompat.checkSelfPermission(context, 
    Manifest.permission.ACCESS_FINE_LOCATION) 
    == PackageManager.PERMISSION_GRANTED)

🧪 Testing

Unit Test LocationValidator

./gradlew test

Test cases:

  • ✓ Distance calculation accuracy
  • ✓ Validation logic (within/outside radius)
  • ✓ Message generation
  • ✓ Coordinate adjustment
  • ✓ Mathematical properties (symmetry, triangle inequality)

Manual Testing Checklist

[ ] Permissions diminta dengan benar
[ ] Lokasi GPS terakses saat connected
[ ] Card lokasi menampilkan koordinat
[ ] Validasi menunjukkan jarak akurat
[ ] Camera intent terbuka saat "Ambil Foto" diklik
[ ] Foto preview ditampilkan setelah capture
[ ] Form disabled saat lokasi invalid
[ ] Submit button hanya enable jika semua valid
[ ] Loading spinner muncul saat submit
[ ] Success message muncul setelah 200 response
[ ] Error message muncul setelah gagal
[ ] Form reset setelah 2 detik sukses

🛠️ Customization Guide

Ubah Koordinat Referensi

File: AttendanceConfig.kt

const val REFERENCE_LATITUDE = -7.025    // Ubah ke lokasi kampus
const val REFERENCE_LONGITUDE = 110.415

Ubah Radius Area

const val ALLOWED_RADIUS_METERS = 150.0  // Ubah ke radius yang diinginkan

Ubah Data Mahasiswa

const val STUDENT_NPM = "202310715082"
const val STUDENT_NAMA = "Fazri Abdurrahman"

Ubah Webhook URL

const val WEBHOOK_PRODUCTION = "https://your-webhook-url/..."
const val WEBHOOK_TEST = "https://your-test-webhook-url/..."

Ubah Photo Quality

const val PHOTO_QUALITY = 80  // 0-100, lebih tinggi = lebih besar file

📊 Monitoring & Debugging

Enable Logging

// Di N8nService, tambahkan:
Log.d("N8nService", "Request: $json")
Log.d("N8nService", "Response Code: $responseCode")

Check Permission Status

val hasLocationPermission = ContextCompat.checkSelfPermission(
    context, Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED

Validate GPS

  • Buka Google Maps untuk confirm GPS aktif
  • Verifikasi koordinat akurat di Maps
  • Test di lokasi berbeda untuk validate radius

Test Webhook

  1. Gunakan WEBHOOK_TEST terlebih dahulu
  2. Cek response di N8n dashboard
  3. Verify data received dengan benar
  4. Switch ke WEBHOOK_PRODUCTION saat siap

🚨 Common Issues & Solutions

Issue Cause Solution
GPS tidak berfungsi Location permission ditolak Buka Settings > Permissions > Location
Lokasi selalu invalid Koordinat referensi salah Update REFERENCE_LATITUDE/LONGITUDE
Foto tidak terakses Camera permission ditolak Buka Settings > Permissions > Camera
Submit gagal Network issue Check internet connection
Webhook 404 URL salah Verify webhook URL di AttendanceConfig

📚 Dependencies

// Sudah terinclude di build.gradle.kts:
- androidx.core:core-ktx
- androidx.lifecycle:lifecycle-runtime-ktx
- androidx.compose.* (UI framework)
- com.google.android.gms:play-services-location (GPS)
- Material 3 (Design system)

🔄 Next Steps / Future Features

Phase 2 (Future)

  • Attendance history dengan Room Database
  • User login screen dengan authentication
  • Support multiple courses/classes
  • Attendance statistics & reports
  • Push notifications untuk deadline
  • Offline mode dengan sync

Phase 3 (Advanced)

  • Biometric verification (fingerprint)
  • QR code verification
  • Face recognition
  • Real-time attendance dashboard
  • Mobile app backend server

📞 Support & Contact

Untuk pertanyaan atau issues:

  1. Check logs di Android Studio Logcat
  2. Review error messages di app
  3. Test dengan webhook test terlebih dahulu
  4. Verify configurations di AttendanceConfig.kt

Last Updated: January 14, 2026
Version: 1.0
Status: Production Ready