Android应用监听自己是否被卸载,做反馈统计
- 摘要:[size=large]最近做项目的时候碰到这样一个需求:用户卸载应用后提供反馈信息以便更好的改进软件,并统计卸载量。Android可以监听卸载广播,得到什么应用被卸载了,但是系统并没有提供监听自己卸载的方法,于是乎,在网上找了一些方法,根据自己需求做了些修改,最后完成这个需求。调研方案1:监听Android卸载广播注册BroadcastReceiver,监听”android.intent.action.PACKAGE_REMOVED”系统广播,这个方法肯定不行
- 标签:android 应用 自己 卸载 监听
[size=large]最近做项目的时候碰到这样一个需求:用户卸载应用后提供反馈信息以便更好的改进软件,并统计卸载量。Android可以监听卸载广播,得到什么应用被卸载了,但是系统并没有提供监听自己卸载的方法,于是乎,在网上找了一些方法,根据自己需求做了些修改,最后完成这个需求。
调研
方案1:监听Android卸载广播
注册BroadcastReceiver,监听”android.intent.action.PACKAGE_REMOVED”系统广播,这个方法肯定不行,卸载的第一步就是退出当前应用的主进程,而此广播是在已经卸载完成后才发出的,此时主进程都没有了,肯定接收不到这个系统广播了,所以这个方案首先被pass。
方案2:监控Android日志实现
启动一个服务监控android系统的打印日志,当监控到”android.intent.action.DELETE”并且包含自己应用的包名时,意味着自己将要被卸载,这时提示信息给用户,或者弹出网页。这个方案确实可行,网上早已有人实现了,实现的博客地址。
但是这个解决方案有几个很大的弊端:
因为服务要一直监控日志,所以会比较耗电。
程序必须在启动的情况下才可以监控。
点击设置中的卸载按钮即发出此Intent,此时用户尚未在弹框中确认卸载,其实用户还没真正意义上卸载。
pm命令卸载不出发此Intent,意味着被诸如手机安全管家,豌豆荚等软件卸载时,无法提前得知卸载意图。
由于以上问题,这种方案也被舍弃了。
方案3:监控/data/data/{package_name}目录实现
由于Android要卸载一个应用程序的时候,会删除私有目录(/data/data/{package_name}),所以监控这个目录是否被删除也可以实现,据网上的一些博客说,360和豌豆荚使用的就是这种方法。那我们就具体研究一下这个方案。
实现
第一种方法
在Java中线程直接轮询这个目录是否存在,以此为依据判断自己是否被卸载。但是主进程退出,相应的线程必定退出,线程还没等到判断目录是否存在就已经被销毁了。不可行,pass。
第二种方法
用C来实现,通过Fork子进程,然后在子进程中通过监控/data/data/{package_name}目录是否删除实现。在子进程中进程轮询”/data/data/包名”目录是否存在。这个方法,网上实例已经实现了。但用轮询的方法,依然没解决耗电的问题。
第三种方法
同第二种方法类似,不同的是不再采用轮询的方式,而是用linux中 inotify_init、inotify_add_watch监控文件系统目录,判断目录是否被删除,然后提示给用户。这个方法也有成熟的解决方案了,链接在这儿。但这个方案也有几个弊端:
清除数据、插拔USB线、覆盖安装等操作引起程序误判卸载。
重复监听的问题。
用户将已在Internal SD卡安装好的应用移动到external SD卡,导致监听不正常。
第四种方法(目前为止最优)
修复第三种方法提到的一些bug:
原因:
由于inotify_add_watch(fileDescriptor, path, IN_DELETE)这个函数会监听path目录下所有文件的caozuo.html" target="_blank">删除操作导致。
重复调用JNI的init方法
解决方法:
监听不应该针对整个文件夹,而是某个文件。
重复监听的问题,都可以通过加文件锁来防止。[/size]