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

585 lines
14 KiB
Markdown

# 🔧 Troubleshooting Guide
## Common Issues & Solutions
### 🚨 Build Issues
#### Issue 1: Gradle Sync Failed
**Error**: `Gradle sync failed: Failed to resolve...`
**Solutions**:
1. Clean project: `Build``Clean Project`
2. Invalidate caches: `File``Invalidate Caches / Restart`
3. Sync Gradle: `File``Sync Now`
4. Delete `.gradle` folder and try again
5. Check internet connection (gradle downloads dependencies)
---
#### Issue 2: Missing Dependencies
**Error**: `Unresolved reference: LocationValidator` atau similar
**Solutions**:
1. Verify file exists in correct package structure
2. Check package declaration at top of file
3. Rebuild project: `Build``Rebuild Project`
4. Check that all imports are present
5. File → Invalidate Caches / Restart
---
#### Issue 3: Kotlin Syntax Error
**Error**: `Type mismatch: inferred type is String? but Boolean was expected`
**Solutions**:
1. Check null-safety: use `?.` or `!!` appropriately
2. Verify data class properties match their types
3. Look for missing type annotations
4. Check imports for correct classes
---
### 📍 Location Issues
#### Issue 1: GPS Not Acquiring Location
**Error**: "Lokasi tidak tersedia"
**Causes & Solutions**:
- ❌ Location permission not granted
→ Check Settings → Apps → Permissions → Location (Allow)
- ❌ Location services disabled
→ Enable in Settings → Location → Location Services
- ❌ Cold start GPS (takes time to acquire)
→ Wait 30-60 seconds for GPS to warm up
→ Or enable "Use high accuracy" in location settings
- ❌ Testing in emulator
→ Use Extended Controls → Location to simulate GPS
→ Or use GPX file for GPS simulation
**Quick Check**:
```kotlin
// Test if GPS is available
val hasLocationPermission = ContextCompat.checkSelfPermission(
context, Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
// Test if location services enabled
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
```
---
#### Issue 2: Location Always Invalid
**Error**: "✗ Lokasi tidak valid (2500m, maksimal 100m)"
**Causes & Solutions**:
- ❌ Reference coordinates wrong
→ Update `REFERENCE_LATITUDE` dan `REFERENCE_LONGITUDE` di `AttendanceConfig.kt`
→ Verify with Google Maps
- ❌ Radius too small
→ Increase `ALLOWED_RADIUS_METERS` temporarily for testing
→ Default is 100m, try 200m or 300m
- ❌ Testing from wrong location
→ Go to actual campus location
→ Or use emulator GPS simulation
**How to Fix**:
```kotlin
// File: AttendanceConfig.kt
const val REFERENCE_LATITUDE = -7.025 // ← Update this
const val REFERENCE_LONGITUDE = 110.415 // ← Update this
const val ALLOWED_RADIUS_METERS = 100.0 // ← Or increase this
```
**How to Verify Reference Coordinates**:
1. Go to campus location with device
2. Open Google Maps
3. Long-click on map → Coordinates appear at top
4. Copy latitude and longitude
5. Update in `AttendanceConfig.kt`
---
#### Issue 3: Distance Calculation Wrong
**Error**: Shows 5000m distance when clearly close to reference
**Causes & Solutions**:
- ❌ Latitude/longitude swapped
→ Check: latitude is first, longitude is second
→ Format should be: (-7.025, 110.415) not (110.415, -7.025)
- ❌ Wrong location acquired
→ Check Logcat: `Log.d("Location", "Lat: $lat, Lon: $lon")`
→ Verify with Google Maps
- ❌ Haversine formula bug
→ Run unit tests: `./gradlew test`
→ Check LocationValidatorTest results
**Debug Steps**:
```kotlin
// Add logging to MainActivity
Log.d("AbsensiApp", "Reference: -7.0, 110.4")
Log.d("AbsensiApp", "Student: ${state.location?.latitude}, ${state.location?.longitude}")
Log.d("AbsensiApp", "Distance: ???")
// Or test manually
val distance = LocationValidator.calculateDistance(
-7.0, 110.4,
-7.0035, 110.4042
)
Log.d("Distance Test", "Result: $distance meters")
```
---
### 📸 Camera Issues
#### Issue 1: Camera Permission Denied
**Error**: "Izin kamera ditolak"
**Solutions**:
1. Open Settings → Apps → YourApp → Permissions
2. Find "Camera" permission
3. Tap it → Select "Allow"
4. Return to app and try again
**For Emulator**:
1. Device Manager → Create/Edit device
2. Verify "Camera" is checked in hardware
3. Set Camera: "Emulated"
---
#### Issue 2: Photo Not Captured
**Error**: Camera opens but no photo saved
**Causes & Solutions**:
- ❌ User canceled camera intent
→ Just tap button again to retry
- ❌ Storage permission issue (older Android)
→ Grant `WRITE_EXTERNAL_STORAGE` in Settings
- ❌ Camera intent failure
→ Check if device has camera: `hasSystemFeature(PackageManager.FEATURE_CAMERA)`
**Debug**:
```kotlin
// Check in logcat
Log.d("Camera", "Result Code: $resultCode")
Log.d("Camera", "Data: ${result.data}")
Log.d("Camera", "Bitmap: ${bitmap != null}")
```
---
#### Issue 3: Photo Preview Not Showing
**Error**: PhotoPreviewCard shows "Belum ada foto"
**Causes & Solutions**:
- ❌ Bitmap is null
→ Check Activity.RESULT_OK returned
→ Verify `result.data?.extras?.getParcelable` working
- ❌ UI not updating
→ Ensure state.copy() is called
→ Check LaunchedEffect dependencies
**Quick Fix**:
```kotlin
// Add logging
if (bitmap != null) {
Log.d("Photo", "Bitmap size: ${bitmap.width}x${bitmap.height}")
state = state.copy(foto = bitmap)
} else {
Log.d("Photo", "Bitmap is null!")
}
```
---
### 🌐 Network Issues
#### Issue 1: Cannot Connect to Webhook
**Error**: "Gagal kirim ke server" or timeout
**Causes & Solutions**:
- ❌ No internet connection
→ Check WiFi/mobile data enabled
→ Ping google.com to verify
- ❌ Wrong webhook URL
→ Verify in `AttendanceConfig.kt`
→ Copy exact URL from N8n dashboard
- ❌ Firewall/VPN blocking
→ Disable VPN temporarily
→ Check if institution firewall allows HTTPS
- ❌ N8n server down
→ Test with curl: `curl -X POST https://n8n.lab.ubharajaya.ac.id/webhook/...`
→ Check N8n status page
**Webhook URL Check**:
```kotlin
// File: AttendanceConfig.kt
const val WEBHOOK_PRODUCTION = "https://n8n.lab.ubharajaya.ac.id/webhook/23c6993d-1792-48fb-ad1c-ffc78a3e6254"
// ↑ Copy exact URL, no typos!
```
---
#### Issue 2: Server Returns 400/500 Error
**Error**: "Absensi ditolak server" with error code
**Causes & Solutions**:
- **Status 400**: Data format wrong
→ Verify JSON structure matches expectations
→ Check all fields are present (npm, nama, lat, lon, foto)
→ Check foto is valid Base64
- **Status 401**: Authentication failed
→ Add authentication token if required
→ Contact server admin
- **Status 500**: Server error
→ Check N8n workflow logs
→ Verify database connection
→ Retry after server is fixed
**Test with Test Webhook First**:
```kotlin
// In MainActivity
isTest = true // Set this to test first
// Check results at: https://n8n.lab.ubharajaya.ac.id/webhook-test/...
```
---
#### Issue 3: Timeout (Takes Too Long)
**Error**: Request hangs for 30+ seconds then fails
**Solutions**:
1. Check network speed: Test with speed.test.com
2. Reduce photo size: Decrease `PHOTO_QUALITY` in `AttendanceConfig.kt`
3. Increase timeout: Change `API_TIMEOUT_MS` (but not recommended)
4. Check server response time (might be slow)
```kotlin
// File: AttendanceConfig.kt
const val PHOTO_QUALITY = 70 // Reduce from 80 to 70
const val API_TIMEOUT_MS = 30000 // Current 30 seconds
```
---
### ⚙️ Permission Issues
#### Issue 1: Permission Dialog Not Appearing
**Error**: App crashes or silently fails
**Solutions**:
1. Verify permission in `AndroidManifest.xml`:
```xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.INTERNET"/>
```
2. Check permission launcher is called:
```kotlin
LaunchedEffect(Unit) {
locationPermissionLauncher.launch(
Manifest.permission.ACCESS_FINE_LOCATION
)
}
```
3. For Android 12+, check targetSdk:
```gradle
targetSdk = 36
```
---
#### Issue 2: Permission Stuck on Denied
**Error**: User clicks "Deny" and can't recover
**Solutions**:
1. User must go to Settings manually:
→ Settings → Apps → YourApp → Permissions → Allow
2. Add UI hint in app:
```kotlin
if (state.errorMessage?.contains("Izin") == true) {
Button("Buka Pengaturan") {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
startActivity(intent)
}
}
```
---
### 💾 Data & State Issues
#### Issue 1: Form Not Validating
**Error**: Submit button always disabled or always enabled
**Causes & Solutions**:
- ❌ Validation logic wrong
→ Check `LocationValidator.isLocationValid()` implementation
→ Run unit tests: `./gradlew test`
- ❌ State not updating
→ Verify state.copy() being called
→ Check all conditions in button enabled state
**Validation Checklist**:
```kotlin
// Button should be enabled only when ALL true:
val canSubmit = (
state.location != null && // Location acquired
state.foto != null && // Photo taken
state.validationResult.isValid && // Location valid
!state.isLoadingSubmit // Not currently submitting
)
SubmitButtonWithLoader(
// ...
isEnabled = canSubmit // ← Check this
)
```
---
#### Issue 2: State Lost on Screen Rotation
**Error**: Form data disappears when device rotates
**Solutions**:
This is normal - Compose restores state automatically via `remember {}`
To persist across full app restart:
```kotlin
// Would need ViewModel + SavedStateHandle (advanced feature)
// Currently: state is reset on process death (acceptable for MVP)
```
---
#### Issue 3: Photo Bitmap Memory Issue
**Error**: "OutOfMemoryError: Bitmap too large" or app crashes
**Solutions**:
1. Reduce photo quality:
```kotlin
const val PHOTO_QUALITY = 60 // Reduce from 80
```
2. Compress after capture:
```kotlin
// In bitmapToBase64:
bitmap.compress(Bitmap.CompressFormat.JPEG, PHOTO_QUALITY, outputStream)
```
3. For low-memory devices:
- Scale down bitmap before encoding
- Or use WebP format (better compression)
---
### 🧪 Testing Issues
#### Issue 1: Unit Tests Not Running
**Error**: "No tests found" or tests fail
**Solutions**:
1. Run from command line:
```bash
./gradlew test
```
2. Or in Android Studio:
- Right-click test file → Run 'LocationValidatorTest'
- Or use Test Configuration
3. Verify test file location:
```
app/src/test/java/.../LocationValidatorTest.kt ✓ Correct
app/src/androidTest/java/.../LocationValidatorTest.kt ✗ Wrong
```
---
#### Issue 2: Manual Testing Stuck
**Error**: Can't reproduce the flow
**Quick Test Checklist**:
- [ ] Device/emulator has internet
- [ ] Location services enabled
- [ ] All permissions granted
- [ ] Camera app works
- [ ] Webhook URL correct
**Fastest Flow**:
1. Grant permissions automatically
2. Hardcode valid location (for testing)
3. Take photo
4. Click submit
5. Should complete in < 10 seconds
---
### 🎨 UI Issues
#### Issue 1: Layout Cut Off on Small Screens
**Error**: Buttons/text not visible
**Solutions**:
1. Already implemented: `verticalScroll(rememberScrollState())`
2. Reduce padding: `modifier.padding(16.dp)` → `modifier.padding(8.dp)`
3. Use `Column` scrolling instead of fixed height
```kotlin
Column(
modifier = modifier
.fillMaxSize()
.padding(16.dp)
.verticalScroll(rememberScrollState()) // ← This allows scrolling
)
```
---
#### Issue 2: Dark Mode Not Working
**Error**: Text hard to read or colors wrong
**Solutions**:
1. Theme already supports dynamic colors (Material 3)
2. Verify `Theme.kt` has proper dark/light variants
3. Test: Settings → Display → Dark theme → On/Off
---
#### Issue 3: Loading Spinner Not Showing
**Error**: Button says "Mengirim..." but no spinner
**Solutions**:
1. Check `isLoading` state is true:
```kotlin
state = state.copy(isLoadingSubmit = true)
```
2. Verify spinner code in `SubmitButtonWithLoader`:
```kotlin
if (isLoading) {
CircularProgressIndicator(...) // ← Should show
}
```
---
## 🆘 Emergency Troubleshooting
### App Crashes on Launch
1. Check Logcat for full error stack trace
2. Look for line number where crash happens
3. Most common: Missing permission or dependency
4. Try: `Build` → `Clean Project` → `Rebuild Project`
### Complete State Reset
```bash
# Uninstall app completely
./gradlew uninstallDebug
# Clean all build artifacts
./gradlew clean
# Rebuild everything
./gradlew installDebug
```
### Last Resort: Check Dependencies
```gradle
// Verify all dependencies installed
./gradlew dependencies
// Check for conflicts
./gradlew dependencyInsight --dependency location-services
```
---
## 📊 Debugging Commands
### View All Logs
```bash
adb logcat
```
### Filter Specific Tags
```bash
adb logcat | grep "AbsensiApp"
adb logcat | grep "N8nService"
adb logcat | grep "LocationValidator"
```
### Clear Logs
```bash
adb logcat -c
```
### Install Debug App
```bash
./gradlew installDebug
```
### Uninstall App
```bash
adb uninstall id.ac.ubharajaya.sistemakademik
```
### View App Logs in Real-time
```bash
adb logcat *:S AbsensiApp:D
```
---
## 🔍 Verification Checklist
Before declaring bug fixed, verify:
- [ ] Issue is reproducible
- [ ] Logs show no errors
- [ ] All permissions granted
- [ ] Internet connection active
- [ ] Coordinates correct
- [ ] Server responding
- [ ] Photo quality acceptable
- [ ] Location accuracy good
- [ ] Form submission successful
- [ ] Data received at webhook
---
**Still stuck?**
1. Re-read QUICK_REFERENCE.md
2. Check DOKUMENTASI.md for detailed explanations
3. Review TESTING_CHECKLIST.md for testing procedures
4. Check ARCHITECTURE.md for design understanding
5. Look at comments in actual code files
---
**Last Updated**: January 14, 2026
**Version**: 1.0