Hey devs! Just shipped version 1.2.0 of Amalanku, an Islamic habit tracker and spiritual companion app. This release includes some interesting technical challenges I'd love to share with the community.
๐ฏ What is Amalanku?
Amalanku is a free Android app that helps users track their daily Islamic practices (amal). Think of it as a spiritual habit tracker with:
- ๐ Daily task tracking (prayers, Quran, dhikr, etc.)
- ๐ Analytics and progress visualization
- ๐ PDF monthly reports generation
- ๐ Smart notification system
- ๐ Prayer time integration
Download: Google Play Store
Website: amalanku.com
โจ What's New in 1.2.0
๐ Home Widget Implementation
Added a Prayer Times Widget that displays salah schedule on the home screen.
Technical highlights:
- Used Android's AppWidgetProvider
- Implemented auto-refresh based on prayer times
- Optimized battery usage with smart update intervals
- Responsive layout for different widget sizes
Challenge: Keeping the widget updated without draining battery.
Solution:
// Calculate next prayer time and schedule exact update
val nextPrayerTime = calculateNextPrayer()
val updateIntent = Intent(context, SalatWidgetProvider::class.java)
val pendingIntent = PendingIntent.getBroadcast(context, 0, updateIntent, flags)
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC, nextPrayerTime, pendingIntent)
๐จ Dynamic Theming Based on Time
Switched from Material You dynamic colors to a custom time-based green theme.
Implementation:
- Different color intensities for different times of day
- Smooth transitions between time periods
- Maintains accessibility contrast ratios
fun getThemeForTime(hour: Int): ColorScheme {
return when (hour) {
in 0..5 -> nightTheme // Darker, softer green
in 6..11 -> morningTheme // Fresh, bright green
in 12..17 -> afternoonTheme // Balanced green
else -> eveningTheme // Warm, calm green
}
}
๐ PDF Generation Fixes
Fixed critical issues with monthly PDF reports (Laporan Bulanan).
Problems solved:
- PDF rendering inconsistencies across devices
- Crashes when no PDF reader installed
- Memory issues with large reports
Solutions:
// Graceful PDF reader check
fun openPdf(file: File, context: Context) {
val uri = FileProvider.getUriForFile(context, "$packageName.provider", file)
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, "application/pdf")
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
}
if (intent.resolveActivity(context.packageManager) != null) {
context.startActivity(intent)
} else {
// Show dialog to install PDF reader or share file
showPdfReaderDialog(uri, context)
}
}
๐พ Backup & Restore System
Implemented comprehensive data backup functionality.
Architecture:
- JSON export of Room database
- Encryption option for sensitive data
- Version compatibility checking
- Incremental backup support
Tech stack:
// Export data structure
data class BackupData(
val version: Int,
val timestamp: Long,
val tasks: List<Task>,
val completions: List<Completion>,
val settings: UserSettings,
val checksum: String // Verify data integrity
)
// Backup process
suspend fun createBackup(): File {
val data = BackupData(
version = BACKUP_VERSION,
timestamp = System.currentTimeMillis(),
tasks = taskDao.getAllTasks(),
completions = completionDao.getAllCompletions(),
settings = settingsDao.getSettings(),
checksum = "" // Calculate after serialization
)
val json = gson.toJson(data)
return writeToFile(json)
}
๐ธ Share Summary as Image
Generate shareable summary images using Canvas API.
Features:
- Custom graphics with statistics
- Brand styling (colors, fonts, logo)
- Optimized image compression
- Multiple sharing options
Implementation approach:
suspend fun generateSummaryImage(summary: AmalSummary): Bitmap {
return withContext(Dispatchers.Default) {
val bitmap = Bitmap.createBitmap(1080, 1920, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
// Draw background gradient
drawBackground(canvas)
// Draw statistics
drawStats(canvas, summary)
// Draw charts
drawProgressChart(canvas, summary.dailyProgress)
// Add branding
drawWatermark(canvas)
bitmap
}
}
๐ Smart Notifications
Added two notification types:
- Monthly Muhasabah - End-of-month reflection reminder
- Daily Tahajjud - Late-night prayer notification
Technical considerations:
- WorkManager for reliable scheduling
- Notification channels for Android 8+
- User-configurable timing
- Quiet hours respect
// Schedule monthly muhasabah
val workRequest = PeriodicWorkRequestBuilder<MuhasabahWorker>(
repeatInterval = 30,
repeatIntervalTimeUnit = TimeUnit.DAYS
)
.setInitialDelay(calculateDaysUntilEndOfMonth(), TimeUnit.DAYS)
.setConstraints(
Constraints.Builder()
.setRequiresBatteryNotLow(true)
.build()
)
.build()
WorkManager.getInstance(context).enqueue(workRequest)
โก UX Improvements
Fixed task page scrolling and added haptic feedback:
// Prevent scroll-to-top on task selection
taskRecyclerView.apply {
itemAnimator = null // Disable default animations
setHasFixedSize(true)
}
// Haptic feedback on task completion
fun onTaskChecked(task: Task) {
view.performHapticFeedback(HapticFeedbackConstants.CONFIRM)
updateTaskCompletion(task)
}
๐ฏ Technical Challenges & Learnings
Challenge 1: Widget Updates vs Battery Life
Problem: Real-time prayer time updates drain battery.
Solution: Calculate exact next prayer time and use setExactAndAllowWhileIdle() instead of periodic updates.
Challenge 2: PDF Cross-Device Compatibility
Problem: Different devices render PDFs differently.
Solution: Used iText library with explicit font embedding and consistent page dimensions.
Challenge 3: Backup Data Integrity
Problem: Corrupted backups = lost user data.
Solution: Added checksums, version tracking, and validation before restore.
๐ Performance Metrics
After optimization:
- App size: ~8MB
- Cold start: <2s
- Widget update: <100ms
- PDF generation: <1s for 30-day report
- Backup creation: <500ms
๐ ๏ธ Tech Stack
- Language: Kotlin
- Architecture: MVVM + Clean Architecture
- Database: Room
- DI: Hilt
- Async: Coroutines + Flow
- UI: Jetpack Compose (migrating from XML)
- Background: WorkManager
- Analytics: Firebase Analytics (privacy-focused)
๐ฎ What's Next?
Planning for v1.3.0:
- Cloud sync (optional)
- Streak gamification
- Community challenges
- Widget customization options
- Dark mode improvements
๐ญ Lessons Learned
- Battery optimization matters - Users won't tolerate drain, even for useful features
- Graceful degradation - Always have a plan B (like the PDF reader check)
- Data integrity is critical - One corrupted backup can lose user trust forever
- Haptic feedback is underrated - Small touches make big UX differences
- Test on cheap devices - Your flagship phone isn't representative
๐ค Open to Feedback
Building apps with spiritual/religious purposes comes with unique UX challengesโrespecting tradition while embracing modern design, balancing reminders without being annoying, etc.
Would love to hear from developers who've built similar apps or have ideas on making habit tracking more effective!
Try it: Download on Google Play
Tags: #android #kotlin #showdev #opensource #mobiledev #habittracking
Top comments (0)