清晨的雾霾轻了些,但天空还是灰蒙蒙的,就像赶早班人们的心情。
9点,准时赶到办公室,保洁的阿姨刚刚收拾完工具。与往常一样,径直走到自己工位,手机在机箱上轻轻一按,伴随着主板风扇的转动声,电脑系统和一个苦逼程序猿的日常一齐被START。
然而,一个程序猿的日常总是充满诱惑和挑战的!
显示器上的四个色块还没有散去,便听见一个清脆甜美却又略带忧郁的声音说:“如果我能知道每个安卓用户手机中app每天的使用频率,就可以向用户精准的投放一些运营push,不知道哪位开发GG可以帮下忙获取下这个数据嘛~”,不用问,肯定是我们的产品女神Miss L给大伙儿提需求来了。“下班之前我来实现这个功能!”,还没等其他同事从睡意朦胧中反应过来,Miss L已经对我微微一笑,满意的转身离开了,留下的只有空气中令人清新愉悦的迪奥甜心精灵的淡淡清香。
深呼吸过后,猛然醒悟,android系统好好像并没有向开发者提供获取app使用频率或者使用次数的能力,查阅各种典籍之后确认,原来系统中虽然已经记录app的使用数据,但由于涉及用户隐私,这些数据只有系统的开发者(拥有系统签名)才能获取,然而作为应用开发者,即便你有上天入地的本领,也是取之不得。
“山穷水尽疑无路,柳暗花明又一村”,却又恰恰应了此时此景。虽然作为应用开发者,无法获取现成的系统数据,但却可以通过“ActivityManager”活动管理器提供的接口获取其他的辅助信息来完成需求:
-
“getRecentTasks”接口:获取用户最近使用过的应用程序列表,这个列表的中先后顺序按照应用使用的先后顺序逆序排列,当前正在使用的应用程序排在列表的第一位,应用在该列表中的位置越靠后,则该应用的最后一次使用距当前时间越长。可以参考安卓手机长按home页或者点击“最近使用”按钮呼出的“最近使用软件列表”,这个列表的排序与“getRecentTasks”接口获取的列表排序一致。应用程序退出后,“最近使用”列表中还会保留该应用程序的信息。
-
“getRunningTasks”接口:获取当前正在运行的应用列表。这个列表的排序规则与“最近使用”列表的排序规则一致,但是该列表中只包含正在运行的应用程序,应用程序退出后,该应用程序会从当前正在运行的应用列表中删除。
对这两个接口推敲过后,可以得到下面两种算法:
-
每经过一个较长的时间间隔,获取一次“最近使用列表”,并对比相邻两次获取的列表中各个应用之间的相对位置,如果有某两个应用的相对位置发生了改变,或者新获取的列表中出现了一个新的应用,则标记新列表中位置前移或新出现的应用和比该应用排序更靠前的应用各使用过一次。例如第一次获取的应用排序为“A,B,C,D”,相隔一个小时后获取的应用排序为“E,A,C,B,D”,则记E,A,C各使用了一次。
-
每经过一个很短的时间间隔,获取一次“当前正在运行的应用列表”,对比相邻两次获取的列表中第一个应用是否有变化,如果发生变化,则标记新获取的应用列表中第一个应用使用过一次。例如第一次获取的应用列表中排序第一的应用为“A”,相隔一秒钟后获取的应用列表中排序第一的应用变为“B”,则标记“B使用过一次。
很明显,第二个算法的实现相比第一个算法简单很多,但是需要频繁重复的执行(每秒一次),有可能会对功耗造成一定的影响,第一个算法流程复杂但是执行频率低(一个小时一次),不必担心功耗问题,但是可能会产生较大误差。
权衡利弊,决定先快速实现第二个算法。算法实现后,发现并没有带来严重的功耗问题,经过反复测试确认后,这个需求也就顺理成章的Close了。