【Android】做一款类似我要当学霸里的学习监督的APP


  我要当学霸这款App有个学习监督的功能,当你启动它的时候,你将无法使用其他App,以此达到帮助人提高自觉性,起到监督学习的效果。最近和同学做了个小App,正好有这个功能,所以就来说说它是怎么实现的。

PS:本篇描述的是我们做这个小App过程中的一些尝试。


效果

首先还是先来看下效果是怎么样的:
【Android】做一款类似我要当学霸里的学习监督的APP  【Android】做一款类似我要当学霸里的学习监督的APP

实现思路

  先说下我们这个小App的功能:学习监督的功能(即禁掉其他App的使用) + 桌面小宠物(用来给用户提示的)。
  从上图也可以看出,当启动我们这个小App时,开启监督功能后,再点击其他App(如QQ)的时候,桌面小宠物是会给出一些温馨提示的,然后再把刚才你打开的App关闭掉。

那么它是怎么实现呢?首先我们肯定需要监测到用户打开了什么App,那这点怎么实现呢?

1. getRunningTasks()

  最开始想到的是能否用Activity堆栈,也就是ActivityManager里的一个getRunningTasks()方法,调用这个方法也就可以获取当前正在运行中的任务栈,而处于栈顶的也就是我们在这个时刻打开的App。我们只要不断地读取这个任务栈,也就能达到了监测用户打开App的功能了,完美解决。
  但很遗憾,使用的时候才发现这个方法已经被抛弃了。我们看下源代码里怎么说的:
【Android】做一款类似我要当学霸里的学习监督的APP
也就是说在安卓5.0以上的机器,这个方法已经不再为第三方应用使用的了。所以只能另想办法了。

2. getRunningAppProcesses()

  接下去没思路了,就到网上随便搜一些关键词,出来了很多博客,有说用getRunningAppProcesses(),先看下这个方法的介绍:
【Android】做一款类似我要当学霸里的学习监督的APP
  返回正在运行中的应用进程集合,然后再通过进程找到对应的包名就可以了。可是返回的集合序列并没有什么特定的排序方式,也就是随机的,那么我们该怎么判断哪个进程才是刚打开的App创建的呢?
  要么可以先指定一些应用程序,只要判断返回的集合里有我们指定的应用程序,那么就可以判断是打开了那个应用。
  要么可以比较上一时刻返回的集合和这一时刻返回的集合,对比看多了哪些进程,少了哪些进程也就可以判断出打开或关闭了某个应用。
  好,实现的思路大概有了,接下去可以敲代码了。当敲完在真机上测试时,发现不管怎么样返回的都只有该应用的信息。
  网上搜了下,发现这个方法权限又被官方弱化了:
【Android】做一款类似我要当学霸里的学习监督的APP
  我测试用的真机是5.0.+的安卓系统,网上也有解释说有的手机厂家在5.0版本上就已经弱化了getRunningAppProcesses的权限,难怪只会返回应用本身的信息。可这样一来就又跟第一个思路一样了,这个方法也不能采用了。

3. Linux系统内核会把process进程信息保存在/proc目录下

  上面两种思路都不行,只能再找思路了,后来在*中,无意间搜到了国外一牛人的解决方法,他是利用Linux系统的漏洞,Linux系统内核会把process进程信息保存在/proc目录下,只要读取到进程信息,就可以根据进程的属性来判断是否是前台进程了。这个牛人还把它封装成了个开源项目,附上Github地址:https://github.com/jaredrummler/AndroidProcesses
  这样一来就可以获取到所有的进程信息,但就算拿到所有进程信息又要怎么通过进程判断出用户打开了哪个App呢?
  进程有个属性可以用来区分它是前台进程还是后台进程,关于这两者的区别我不是很理解,但我猜想,是否可以将前台进程类比成正在运行中的进程?如果可以这样,那么再利用第2个思路中提到的方案,就可以实现监测用户打开App的功能了。
  于是,我便去尝试一下。后来真机测试时,发现当打开大多数应用时都可以达到预期的效果。但是有个别应用无论用户打开与否,总能被检测到是处于前台进程中,后来在网上发现有人这么解释:

在聊天类型的App中,常常需要常驻后台来不间断的获取服务器的消息,这就需要我们把Service设置成START_STICKY,kill 后会被重启(等待5秒左右)来保证Service常驻后台。如果Service设置了这个属性,这个App的进程就会被判断是前台,代码上的表现就是appProcess.importance的值永远是 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,这样就永远无法判断出到底哪个是前台了。

  于是,这个思路也只能放一边了。

4. 某大神总结

  尝试了各种方法,始终达不到想要的效果。一次偶然情况下,在Github搜到了完美的解决方案,先附上Github地址:https://github.com/wenmingvs/AndroidProcess
【Android】做一款类似我要当学霸里的学习监督的APP
  你可以看到这个大神,对监测运行中的进程进行了非常详细的讲解,而且列举了目前能实现的各种方法,也分别介绍了各自的优缺点。
  得益于这个大神的分享,我把它的项目clone下来学习,最后选择了方法五:通过Android无障碍功能实现
  至此,监测用户打开App的功能终于可以实现,有点不足的是每次使用需要用户自己授权,可能会引起用户反感,但想想也是,这种涉及安全性问题的,如果不通过用户自行授权,就好像有点恶意软件的嫌疑了,hhh。

(小小吐槽:早知道有这么个大神给出了这么详细的介绍,我就不用自己花那么多时间去各种尝试了。哭丧脸)

  好了,监测用户打开App的功能解决了,那么剩下的就是实现桌面宠物了。这个挺简单的,也就是悬浮窗,只是在布局文件里换成动图而已,而要实现动图,这里是使用的也是一个开源项目:android-gif-drawable
  之后只需要当监测到用户打开App时,发送广播通知我们的App,做出一些相应的动作,比如桌面宠物给出温馨提示、关闭用户打开的App等等。


上一篇:[BZOJ1691][Usaco2007 Dec]挑剔的美食家


下一篇:pdo 整套类的封装,保存修改查询