Tips·检测应用程序被卸载
2017-02-10 本文已影响177人
幺鹿
前言
我们知道广播ACTION_PACKAGE_REMOVED
可以监听应用程序卸载,但不幸的是这个意图被卸载的程序
是不可知的,所以无法监听到自己的程序被卸载。
正文
当用户操作Settings -> Manage Apps -> Selects a particular application
时,会收到一条包含其应用程序包名作为extras
的广播消息 android.intent.action.QUERY_PACKAGE_RESTART
。
当我们点击卸载按钮
时,会打开卸载确认界面com.android.packageinstaller.UninstallerActivity
。
我们应监听android.intent.action.QUERY_PACKAGE_RESTART
广播,如果发现广播中的extras
中的包名与应用程序匹配,我们就启动一个后台线程,并利用ActivityManager
持续监控前台运行的Activity
。
当后台线程发现前台的活动是com.android.packageinstaller.UninstallerActivity
,这便确认用户是希望卸载我们的APP。在用户确认卸载前的时刻,我们可以做一些事件(比如:弹出对话框挽留用户等),但是需要确保允许用户卸载APP。
代码实现
1、添加权限
<uses-permission android:name="android.permission.GET_TASKS"/>
2、注册广播接收器
<receiver android:name=".UninstallIntentReceiver">
<intent-filter android:priority="0">
<action android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
<data android:scheme="package" />
</intent-filter>
</receiver>
public class UninstallIntentReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// fetching package names from extras
String[] packageNames = intent.getStringArrayExtra("android.intent.extra.PACKAGES");
if(packageNames!=null){
for(String packageName: packageNames){
if(packageName!=null && packageName.equals("YOUR_APPLICATION_PACKAGE_NAME")){
// User has selected our application under the Manage Apps settings
// now initiating background thread to watch for activity
new ListenActivities(context).start();
}
}
}
}
}
3、后台监视器线程 监听前台活动变化
class ListenActivities extends Thread{
boolean exit = false;
ActivityManager am = null;
Context context = null;
public ListenActivities(Context con){
context = con;
am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
}
public void run(){
Looper.prepare();
while(!exit){
// get the info from the currently running task
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(MAX_PRIORITY);
String activityName = taskInfo.get(0).topActivity.getClassName();
Log.d("topActivity", "CURRENT Activity ::"
+ activityName);
if (activityName.equals("com.android.packageinstaller.UninstallerActivity")) {
// User has clicked on the Uninstall button under the Manage Apps settings
//do whatever pre-uninstallation task you want to perform here
// show dialogue or start another activity or database operations etc..etc..
// context.startActivity(new Intent(context, MyPreUninstallationMsgActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
exit = true;
Toast.makeText(context, "Done with preuninstallation tasks... Exiting Now", Toast.LENGTH_SHORT).show();
} else if(activityName.equals("com.android.settings.ManageApplications")) {
// back button was pressed and the user has been taken back to Manage Applications window
// we should close the activity monitoring now
exit=true;
}
}
Looper.loop();
}
}
已知的限制
当用户点击管理应用程序的设置下的卸载按钮,我们将执行我们的预卸载任务然后要求用户确认窗口,但是用户可以确认卸载或可以取消操作,上述实现并没有考虑到用户点击取消卸载按钮的逻辑。
我希望这个方法可以帮到你,这是我目前知道的唯一不需要Root权限能够在卸载前拦截的方法。