Android 应用程序如何检测到它';要卸载什么?

Android 应用程序如何检测到它';要卸载什么?,android,android-intent,uninstallation,Android,Android Intent,Uninstallation,我们所知道的是,通常(实际上是任何)在卸载前的防病毒应用程序都会触发简单的对话框,比如:“你要卸载应用程序,确定吗?”—“是/否” 是的,我知道我可以使用意图过滤器拦截包删除意图,如: <activity android:name=".UninstallIntentActivity" android:label="@string/app_name" > <intent-filter> <action android:name=

我们所知道的是,通常(实际上是任何)在卸载前的防病毒应用程序都会触发简单的对话框,比如:“你要卸载应用程序,确定吗?”—“是/否”

是的,我知道我可以使用意图过滤器拦截包删除意图,如:

<activity
    android:name=".UninstallIntentActivity"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <action android:name="android.intent.action.DELETE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="package"  />
    </intent-filter>
</activity>

防盗系统通过伪装其组件来保护自身不被卸载 使用各种自我保护技术

另一个例子:安卓系统的卡巴斯基互联网安全,需要输入密码


无论如何,这意味着有办法拦截卸载过程,以防止卸载或完成某些最终工作。

如果您修改内核,则有可能 . 安装后,data/data/your.app.package中创建的所有文件将自动删除

另一种方法是让另一个应用程序检查是否安装了该应用程序。如果没有,它可以做清理工作

更新

除您自己的接收者外,所有接收者都将收到行动包。这已得到证实

更新2

只是另一个想法

我在上搜索时发现,可以通过监视应用程序的logcat来实现这一点 是一个示例logcat监视器

好的方面是,为了监视同一应用程序的logcat,我们不需要有根设备

当我们读取logcat中的每个条目时,我们可以搜索以下字符串

Received broadcast Intent { act=android.intent.action.PACKAGE_REMOVED dat=package:com.package.name flg=0x8000010 (has extras) }
收到此事件后,我们知道我们的应用程序将被取消安装

但我没有尝试


同样,不允许从Android Jellybean监视logcat,为了使应用持久化,您需要有一个根设备,并能够将其安装到系统分区。一旦它在那里,你就可以卸载这些更新,因为它们是与非系统应用程序一起保存的,但是从系统中卸载它并不是那么简单

我知道他们中的一些人还会在系统分区上保存一点数据,以防设备出厂时被重置,但也有一些方法可以让软件包管理器在刚卸载时留下您保存的数据

另一个选择是将其注册为设备管理员。一旦你这样做,他们将无法卸载它,除非他们手动删除它的管理员状态

在这里,看起来他们正在使用root以及其他方法。除了提供一些疯狂的精心设计的服务(看起来他们可能有),没有其他合法的方法可以做到这一点

利用root几乎是这类AV/安全应用的标准做法,没有它,他们对任何其他应用都没有任何真正的权限,因此他们的权限非常有限。我认为超级用户权限不会显示,除非你已经安装了它,所以很多人仍然不知道这是一个选项

<perms>
<item name="android.permission.READ_EXTERNAL_STORAGE" />
<item name="android.permission.GET_TASKS" />
<item name="android.permission.PROCESS_OUTGOING_CALLS" />
<item name="android.permission.WRITE_EXTERNAL_STORAGE" />
<item name="android.permission.WRITE_CALL_LOG" />
<item name="com.avast.android.generic.CENTRAL_SERVICE_PERMISSION" />
<item name="android.permission.WRITE_SMS" />
<item name="android.permission.ACCESS_WIFI_STATE" />
<item name="android.permission.RECEIVE_SMS" />
<item name="android.permission.GET_ACCOUNTS" />
<item name="android.permission.READ_CONTACTS" />
<item name="android.permission.CALL_PHONE" />
<item name="android.permission.WRITE_CONTACTS" />
<item name="android.permission.READ_PHONE_STATE" />
<item name="android.permission.READ_SMS" />
<item name="android.permission.RECEIVE_BOOT_COMPLETED" />
<item name="android.permission.ACCESS_SUPERUSER" />
<item name="com.avast.android.mobilesecurity.permission.C2D_MESSAGE" />
<item name="android.permission.GET_PACKAGE_SIZE" />
<item name="android.permission.WAKE_LOCK" />
<item name="android.permission.ACCESS_NETWORK_STATE" />
<item name="android.permission.USE_CREDENTIALS" />
<item name="android.permission.SEND_SMS" />
<item name="android.permission.RECEIVE_MMS" />
<item name="com.google.android.c2dm.permission.RECEIVE" />
<item name="android.permission.KILL_BACKGROUND_PROCESSES" />
<item name="com.android.vending.BILLING" />
<item name="android.permission.WRITE_SETTINGS" />
<item name="android.permission.INTERNET" />
<item name="android.permission.VIBRATE" />
<item name="android.permission.READ_CALL_LOG" />
<item name="com.avast.android.generic.COMM_PERMISSION" />
<item name="com.dolphin.browser.permission.ACCESS_PROVIDER" />
<item name="com.android.browser.permission.READ_HISTORY_BOOKMARKS" />
</perms>

好的。从2天以来,我一直在调查这个问题,最终找到了一个“疯狂的方法”来解决它,而不必在设备上生根:)

首先,以下是实现解决方案的要点: 1.每当用户进入设置->管理应用->选择特定应用时 我们收到一个广播android.intent.action.QUERY\u PACKAGE\u RESTART,其中应用程序包的名称作为附加项

2.之后,当我们单击卸载按钮(使用软件包安装程序)时,它会打开一个名为-com.android.packageinstaller.UninstallerActivity的活动

控制流如下所示:

在应用程序设置下,用户单击卸载按钮--->我们可以控制显示对话/启动另一个活动/etc--->我们完成卸载前任务--->用户返回卸载确认屏幕--->用户确认并卸载应用程序

使用的方法:

我们将在应用程序中实现一个BroadcastReceiver,用于监听操作“android.intent.action.QUERY\u PACKAGE\u RESTART”,并在onReceive()方法中匹配包名。如果接收到用于选择所需应用程序包的广播,那么我们将启动一个后台线程,该线程将使用ActivityManager监视前台运行的活动

一旦我们发现前台活动是“com.android.packageinstaller.UninstallerActivity”,就会确认用户想要卸载我们的应用程序。此时,我们将执行卸载前要执行的所需任务(显示对话,或启动与卸载窗口重叠的另一个活动,等等)。执行任务后,我们将允许用户继续确认卸载过程

实现/源代码: 在manifest.xml中

添加权限:

<uses-permission android:name="android.permission.GET_TASKS"/>
ListenActivities类-用于监控前台活动

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();
    }
}
类ListenActivities扩展线程{
布尔退出=假;
ActivityManager am=null;
Context=null;
公共列表活动(上下文con){
上下文=con;
am=(ActivityManager)context.getSystemService(context.ACTIVITY\u服务);
}
公开募捐{
Looper.prepare();
当(!退出){
//从当前正在运行的任务中获取信息
列出taskInfo=am.getRunningTasks(最大优先级);
字符串activityName=taskInfo.get(0.topActivity.getClassName();
Log.d(“topActivity”,“当前活动:”
+活动名称);
if(activityName.equals(“com.android.packageinstaller.UninstallerActivity”)){
//用户已单击“管理应用程序设置”下的“卸载”按钮
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();

                }
            }
        }
    }

}
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();
    }
}