这发生在一个安静的星期五布道 在当地的masjid。
房间很密集 沉默,那种感觉沉重和故意。
突然间,一罐响铃粉碎了大气层——有人的电话,在硬木地板上震动。
这不是我的手机, 但整个房间的集体绞痛是粘着的。
百人停止了中想,把头转向噪音的来源.
我坐在那里,我自己的手机塞在我的口袋里, 意识到我几乎是 那个人仅仅一周前。
当时是纯洁可避免的人类摩擦的时刻.
我们生活在一个我们设备应该很聪明的时代,但它们在最基本的环境意识上却一直失败。
我发现自己在每次会议、讲座或预约前 手动整理我的音质 这是一种经常性的认知税。
如果我记得,伟大的。
如果我忘了,我冒着社会尴尬的风险。
更糟糕的是,一旦会议结束,我将不可避免地将我的电话留在沉默的余下时间,错过家人或客户的重要电话.
现有的解决方案往往感觉像过度 kill —— 它们需要建立账户, 经常与云端服务器同步背景, 或对像改变音量设置这样简单的任务感到入侵的权限 。
我想要一个完全生活在设备上的东西, 发挥一个沉默的,无形的效用, 不需要"电话回家"来运作。
当我开始建造Muffle时,我提前决定整个建筑将是"零云".
这不仅仅是一个哲学选择;它是一个技术限制,我是为了确保应用程序仍然能发挥作用和值得信赖。
迫使自己避免后端依赖,我不得不严重依赖Android和图案。
最大的挑战就是"Prayer Time"触发器.
大多数开发者会到达一个Firebase Cloud函数,以便根据用户的位置计算这些时间.
相反,我把图书馆整合到本地。
我不得不处理复杂的时区抵消 和地理计算 直接在设备上。
这意味着应用程序必须高效地使用电池寿命;如果我的计算逻辑效率低下,用户会立即注意到他们的每日电池百分比下降.
为了管理这些例行公事,我用一个房间数据库作为当地的真相来源.
用户每次添加规则,都会在当地进行序列化.
核心逻辑运行在使用一个为系统状态变化收听的函数内.
以下是我如何处理音效配置状态过渡的片段: kotlin val audioManager =上下文.get SystemService (Context.AUDIO SERVICE) 当(行动){"SILENT"->音频管理者. ringerMode =音频管理者.
RINGER MODE VIBRATE"->音频管理者. ringerMode =音频管理者.
RINGER MODE VIBRATE "D"->音频管理者. set interruptionFilter (NotificationManager.INTRUPTION FLTER PRIORITY) "NORMAL"->音频管理者.ringerMode =音频管理者.
RINGER MODE NOMAL} 这个简单的执行是应用程序的核心.
通过保持逻辑局部性,该应用程序能活下来的再boots不需要从服务器上重排规则.
它创造了一个"集和遗忘"的经验.
如果用户为一个位置设定了常规,则应用程序用于触发转换.
由于没有服务器,用户的位置历史从不离开他们的设备.
这种隐私第一的方法是用户的主要销售点,他们越来越怀疑背景数据收集。
最让我惊讶的是设备进入"Doze"模式时的脆弱性.
我最初认为设置警报 足以及时触发我的常规 我错了 Android的猛烈电池优化经常会延迟我的扳机几分钟, 我花了两周时间重新设计任务排程器 这是一个陡峭的学习曲线。
我不得不小心地管理警钟 以确保这个装置能醒来足够长的时间 来处理声音的变化,但不够长