它是如何工作的:警告该应用程序将被卸载? [英] How it works: warning that app is going to be uninstalled?

查看:570
本文介绍了它是如何工作的:警告该应用程序将被卸载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所有我们知道,通常的(实际上任何)防病毒应用程序之前卸载用于火象简单的对话:你要卸载的应用程序,你肯定 - 是/否

All we know that usual (in practice any) antivirus application before uninstall used to fire simple dialog like: "You're going to uninstall app, are you sure?" - "yes/no".

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

Yes, I know that I can intercept package delete intent using intent-filter like:

<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>

但问题是简单的事实,这个拦截任何删除请求,而且这将激发我的应用程序和股票两种方式之间选择对话框。因此,如果用户将选择股票的安装程序 - 我不能做任何事情。

But problem is in simple fact that this intercepts any delete requests and moreover this will fire chooser dialog between my app and stock installer. So if user will select stock installer - I won't be able to do anything.

我的目标不是prevent用户无法卸载我的应用程序,而只是通过回滚我的应用程序所做的更改。

My goal is not to prevent user from uninstalling of my app, but just rollback changes made by my app.

这是我看到,​​这种操作可以在这些防病毒软件学习的,所以请大家帮我解释一下它是如何可能?

Learning from those antivirus apps I see that this kind of operation is possible, so please help me and explain how it is possible?

更新

由于有一些球员谁不相信这是真的 - 我要提到 Avast的手机安全软件

Since there are some guys who doesn't believe that it's real - I would refer to Avast Mobile Security:

防盗通过伪装其组件防止自身卸载   各种自preservation技术。

Anti-Theft protects itself from uninstall by disguising its components with various self-preservation techniques.

又如:卡巴斯基互联网安全套装为Android - 这里的特别程序卸载它,这需要输入机密code 。

Another example: Kaspersky Internet Security for Android - here's special procedure for uninstalling it, which requires entering of secret code.

反正它意味着有办法拦截卸载程序以任何prevent卸载或做一些定型工作。

Anyway it means that there's way to intercept uninstallation procedure in order to either prevent uninstall or do some finalizing job.

推荐答案

好。我一直在研究了很多关于这个问题,因为2天,终于找到了野路子,以解决不生根设备:)

Okay. I have been investigating a lot on this problem since 2 days and finally found a "wild way" to solve it without rooting the device :)

1 当用户进入设置 - >管理应用程序 - >选择一个特定的应用 我们接收广播 android.intent.action.QUERY_PACKAGE_RESTART 与应用程序的包充当临时演员的名字。

1. Whenever user goes to Settings -> Manage Apps -> Selects a particular application we receive a broadcast android.intent.action.QUERY_PACKAGE_RESTART with name of the application's package as extras.

2 之后,当我们点击的卸载按钮(带包安装),它会打开一个名为的活动 - com.android.packageinstaller.UninstallerActivity

2. After that when we click on the Uninstall button (with package installer), it opens an activity named - com.android.packageinstaller.UninstallerActivity

控制流将是这样的:

Control flow will be like:

在应用程序设置上卸载按钮,用户点击--->我们得到控制显示的对话/启动另一个活动的/ etc --->我们完成我们的pre-卸载任务--->用户返回到卸载确认画面--->用户确认并卸载应用程序

的方法:

Used Method:

我们将实现我们的应用程序一个BroadcastReceiver听行动 android.intent.action.QUERY_PACKAGE_RESTART ,并配合我们内部的onReceive()方法的包名。如果收到的选择我们想要的应用程序包的广播,然后我们将启动一个后台线程,将继续使用ActivityManager监控前台运行的活动。

We will implement a BroadcastReceiver in our application for listening the action "android.intent.action.QUERY_PACKAGE_RESTART" and match our package name inside onReceive() method. If the broadcast was received for selection of our desired application package, then we'll initiate a background thread that will keep monitoring the foreground running activities using the ActivityManager.

一旦我们找到了前台活动是 com.android.packageinstaller.UninstallerActivity ,这将是确认用户想卸载我们的应用程序。在这一点上,我们将执行所需的任务(无论是显示一个对话,或者开始另一项活动重叠卸载窗口,等等。)是卸载之前执行。在执行我们的任务后,我们将允许用户继续确认卸载过程。

Once we find the foreground activity to be "com.android.packageinstaller.UninstallerActivity", it'll be confirm that user wants to uninstall our application. At this point we'll perform the desired tasks (either display a dialogue, or start another activity overlapping the uninstallation window, etc..) that are to be performed before uninstallation. After performing our task, we'll allow the user to continue with confirming the uninstallation process.

在manifest.xml的

添加权限:

<uses-permission android:name="android.permission.GET_TASKS"/>

和广播接收器:

<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>

UninstallIntentReceiver.java (广播接收机类)

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

                }
            }
        }
    }

}

ListenActivities类 - 监测的前景活动

ListenActivities class - for monitoring the foreground activities

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

已知的限制:

当用户点击的卸载按钮下的管理应用程序的设置,我们将履行我们的pre-卸载任务,然后PROMT用户的确认窗口,用户可以确认到卸载或可取消的操作。

Known Limitations:

When the user clicks on the Uninstall button under Manage Apps settings, we'll perform our pre-uninstallation tasks and then promt the user to the Confirmation window where user can either confirm to uninstall or can Cancel the operation.

上述的方法是截至目前未覆盖的情况下,如果用户点击取消之后,我们已经完成我们的任务按钮。但是,这很容易与一些ammendments加以解决。

The approach described above is as of now not covering the case if user clicks on Cancel button after we have performed our task. But this could be tackled easily with some ammendments.

例如:我们可以实现一个逻辑来恢复我们做了,如果播出的变化 android.intent.action.PACKAGE_REMOVED 最终未收到

E.g.: We can implement a logic to revert the changes we made if the broadcast "android.intent.action.PACKAGE_REMOVED" was not received in the end.

我希望这种做法将有助于你:)因为这是在我看来,只有这样,我们就可以解决你的问题,而生根设备!

I hope this approach will be helpful to you :) As this is the only way in my opinion we can solve your problem without rooting the device!

[更新1] : 建议的方法来检查是否卸载任务是取消

[Update 1]: Suggested Approach to check if the Uninstallation task was Canceled:

它很有趣,我有完全不同的,比较复杂的想法更早(包括广播,ActivityManager等。等),但在写在这里只是一个想法击中了我的心,其中相对很简单:)

Its kind of funny that I had entirely different and much complex idea earlier(involving broadcasts, ActivityManager, etc.. etc..), but while writing it here just another idea struck into my mind which is comparatively very simple :)

当用户点击卸载按钮下的管理应用程序设置,并且您已经执行了pre-卸载任务后,您只需设置在你的应用程序的一些共享preference已经执行了pre-卸载任务,随时可以卸载。在此之后,你需要不计较什么。

When the User clicks on Uninstall button under Manage Apps settings and after you have performed your pre-uninstallation tasks, you just set some SharedPreference in your app that you have performed the pre-uninstall tasks and are ready for uninstallation. After this you need not to care about anything.

如果用户继续卸载 - >它的好,好,你已经完成所需任务

If the user continues to uninstall -> its well and good as you have already performed required tasks.

而如果用户最后点击取消按钮和消失 - >不要打扰。直到用户进入并再次运行应用程序。应用程序的主要活动现在内部ONSTART()/onResume(),你可以选中共享preference的价值,如果它是为卸载设置,这将意味着用户最终没有继续进行卸载。现在你可以恢复先前所做的更改(倒车执行pre-卸载任务),以确保您的应用程序完美运行!

While if user finally clicks on Cancel button and goes away -> don't bother. Until the user goes and run your application again. Now inside "onStart()" / "onResume()" of your application's main activity, you can check the SharedPreference's value and if it was set for uninstallation, that will mean that user didn't finally proceeded with the uninstallation. And now you could revert the changes made earlier(reversing the pre-uninstall tasks performed) to ensure that your application runs perfectly!

这篇关于它是如何工作的:警告该应用程序将被卸载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆