应用程序如何检测到它将被卸载?

编程入门 行业动态 更新时间:2024-10-15 16:18:18
本文介绍了应用程序如何检测到它将被卸载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我们所知道的是,卸载之前通常的(实际上是任何)防病毒应用程序用于触发简单的对话框,例如:您确定要卸载应用程序吗?"- 是/否".

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.

我的目标不是阻止用户卸载我的应用,而是回滚我的应用所做的更改.

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 Mobile Security:

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

Anti-Theft 通过伪装其组件来保护自己免遭卸载使用各种自我保护技术.

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

另一个例子:卡巴斯基安全软件安卓版 - 这里是卸载它的特殊程序,需要输入密码.

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

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

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

控制流程如下:

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

使用的方法:

我们将在我们的应用程序中实现一个 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(); } }

已知限制:

当用户点击管理应用设置下的卸载按钮时,我们将执行我们的预卸载任务,然后提示用户进入确认窗口,用户可以在那里确认卸载或可以取消操作.

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.

上述方法目前还没有涵盖用户在我们执行完任务后点击取消按钮的情况.但这可以通过一些修正轻松解决.

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

当用户单击管理应用程序"设置下的卸载"按钮并在您执行预卸载任务后,您只需在您的应用程序中设置一些 SharedPreference,即您已执行预卸载任务并准备卸载.在此之后,您无需关心任何事情.

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()"中,您可以检查 SharedPreference 的值,如果它被设置为卸载,这将意味着用户最终没有继续卸载.现在您可以恢复之前所做的更改(恢复执行的预卸载任务)以确保您的应用程序完美运行!

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!

更多推荐

应用程序如何检测到它将被卸载?

本文发布于:2023-07-14 10:09:08,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1104060.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:将被   到它   应用程序

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!