惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
云风的 BLOG
云风的 BLOG
小众软件
小众软件
IT之家
IT之家
T
Tailwind CSS Blog
WordPress大学
WordPress大学
S
SegmentFault 最新的问题
美团技术团队
博客园 - 叶小钗
V
V2EX
博客园 - Franky
大猫的无限游戏
大猫的无限游戏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
阮一峰的网络日志
阮一峰的网络日志
博客园 - 【当耐特】
罗磊的独立博客
博客园_首页
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
爱范儿
爱范儿
宝玉的分享
宝玉的分享
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
月光博客
月光博客
有赞技术团队
有赞技术团队

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I Built a Hydration Reminder App — Here's What I Learned ...
Khiêm Duy · 2026-06-24 · via DEV Community

Khiêm Duy

Every developer I know has built at least one "productivity" side project for themselves. Mine was a water reminder app.

Sounds trivial. It was more interesting than I expected.

Here's what I learned from building Thirsty Bot — specifically about the surprisingly hard problem of making notifications that people don't immediately swipe away and disable.

The Core UX Problem: Notification Fatigue

The average Android user receives 46 notifications per day. Most get dismissed without reading.

If your app sends reminders that feel like noise, users will either:

  1. Swipe and ignore (short term)
  2. Disable all notifications from your app (permanent death)

So the core challenge of a reminder app isn't "how do I send a notification" — it's how do I send a notification that the user is glad to receive.

What I Tried (And What Worked)

❌ Fixed interval reminders

Every 2 hours, send a reminder. Simple to implement, terrible UX. Users quickly learn to ignore them because they're predictable and interruptive.

❌ Generic messages

"Time to drink water!" gets old after the third notification. Users stop reading after a week.

✅ Smart scheduling within user-defined windows

Let users set their "active hours" (e.g., 8am–10pm). Space reminders evenly across that window. Never send notifications outside of it. This alone dramatically improved retention — users stopped turning off notifications because the app wasn't waking them up.

✅ Rotating, personality-driven messages

I wrote 40+ unique reminder messages with different tones — humorous, motivating, slightly alarming, curious. Examples:

  • "Your brain is 75% water. Feed it. 🧠"
  • "Dehydration is a silent productivity killer. Drink up."
  • "Hey, remember water? It remembers you. 💧"

Engagement went up noticeably. Users mentioned the notifications specifically in feedback.

✅ Immediate progress feedback

After logging a drink, show a satisfying animation and updated progress ring. Make the action feel rewarding.

The Technical Stuff

The reminder scheduling uses Android's AlarmManager with setExactAndAllowWhileIdle() for reliability across Doze mode. This is non-trivial on modern Android — battery optimization is aggressive and will kill WorkManager tasks in background-restricted apps.

For the goal calculation: I settled on the Holliday-Segar formula as a baseline (35ml/kg body weight), with a multiplier for activity level.

For drink type hydration coefficients: water = 1.0, coffee = 0.8, tea = 0.85, juice = 0.9.

What I'd Do Differently

  • Add widgets on day one. Users want the progress ring on their home screen.
  • Onboarding matters more than I thought. Users who skipped the weight/goal setup were 3x more likely to abandon the app in week one.
  • iOS from day one if possible. A significant portion of interested users are iOS-only.

Try It

Thirsty Bot is free on Android: https://play.google.com/store/apps/details?id=com.nextgensoft.thirstybot

Happy to answer questions about the implementation in the comments — notification scheduling on Android is a rabbit hole worth talking about.