Comment une application détecter qu'il va être désinstallé? [dupliquer]

cette question a déjà une réponse ici:

  • est-il possible de détecter Android app uninstall? 7 réponses
  • effectuer une tâche lors de la désinstallation dans android [dupliquer] 4 réponses

Tout ce que nous savons que l'application antivirus habituelle (dans la pratique tout) avant désinstallation utilisé pour tirer simple dialogue comme: "vous allez désinstaller application, Êtes-vous sûr?"- "oui/non".

Oui, je sais que je peux intercepter paquet de supprimer l'intention à l'aide de intent-filter comme:

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

mais le problème est dans le simple fait que cela intercepte n'importe supprimer des requêtes et de plus, cela lancera le dialogue chooser entre mon application et l'installateur de stock. Donc, si l'utilisateur sélectionne stock installer - Je ne serai pas en mesure de faire quoi que ce soit.

Mon but n'est pas d'empêcher l'utilisateur de désinstaller de mon application, mais juste annulation des modifications faites par mon application.

apprendre de ces applications antivirus je vois que ce genre d'opération est possible, alors s'il vous plaît aidez-moi et expliquer comment il est possible?

mise à Jour

Puisqu'il y a des gars qui ne croient pas que c'est réel - je ferais référence à Avast Sécurité Mobile :

Anti-Theft se protège de la désinstallation en déguisant ses composants avec diverses techniques d'auto-préservation.

un autre exemple: Kaspersky sécurité Internet pour Android - voici la procédure spéciale pour désinstaller , qui il faut entrer le code secret.

de toute façon, cela signifie qu'il y a moyen d'intercepter la procédure de désinstallation afin d'empêcher la désinstallation ou de faire un travail de finalisation.

55
demandé sur Dan Dascalescu 2013-09-09 10:28:11

4 réponses

OK. J'ai beaucoup enquêté sur ce problème depuis 2 jours et j'ai finalement trouvé un "wild way" pour le résoudre sans enraciner l'appareil :)

tout d'abord, voici les points forts pour atteindre la solution:

1. chaque fois que l'utilisateur va à Paramètres - > Gérer les applications - > sélectionne une application particulière nous recevons une émission android.intention.action.QUERY_PACKAGE_RESTART avec le nom du paquet de la demande comme extras.

2. après cela, lorsque nous cliquons sur le bouton désinstaller (avec l'installateur de paquets), il ouvre une activité nommée - com.Android.packageinstaller.Désinstallation de l'activité

le débit de commande sera comme:

sous Paramètres de L'application, L'utilisateur clique sur le bouton "Désinstaller" - - - > Nous obtenons de contrôle pour afficher un dialogue / démarrer une autre activité / etc ---> Nous finissons notre Pré-tâche de Désinstallation ---> l'Utilisateur est Renvoyé à l'écran de confirmation de la Désinstallation ---> l'Utilisateur confirme et désinstalle l'application

Méthode Utilisée:

Nous allons mettre en œuvre un BroadcastReceiver dans notre application pour écouter l'action " Android.intention.action.QUERY_PACKAGE_RESTART " et correspondent à notre nom de paquet dans la méthode onReceive (). Si le message a été reçu pour la sélection de notre paquet d'application désiré, alors nous allons lancer un thread de fond qui va continuer à surveiller les activités de premier plan en utilisant L'ActivityManager.

une fois que nous trouvons l'activité de premier plan à être " com.Android.packageinstaller.Désinstaller l'activité ", il sera confirmer que l'utilisateur veut désinstaller notre application. À ce moment-là, nous exécuterons les tâches désirées (soit afficher un dialogue, soit démarrer une autre activité chevauchant la fenêtre de désinstallation, etc.)..) qui doivent être exécutées avant la désinstallation. Après avoir effectué notre tâche, nous permettrons à l'utilisateur de continuer à confirmer le processus de désinstallation.

La Mise En Œuvre De La Source / Code:

dans le manifeste.xml

ajouter permission:

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

et récepteur de radiodiffusion:

<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 (classe de récepteur de radiodiffusion)

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

                }
            }
        }
    }

}

Classe D'activités de liste - pour la surveillance des activités de premier plan

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

Limitations Connues:

lorsque l'utilisateur clique sur le bouton désinstaller sous Gérer les paramètres des applications, nous exécuterons nos tâches de pré-désinstallation, puis nous promettons l'utilisateur à la fenêtre de Confirmation où l'utilisateur peut soit confirmer à désinstaller ou peut annuler l'opération.

l'approche décrite ci-dessus ne couvre plus le cas si l'utilisateur clique sur le bouton Cancel après que nous ayons effectué notre tâche. Mais cela pourrait être facilement résolu par des amendements.

par exemple: Nous peut mettre en œuvre une logique pour revenir sur les changements que nous avons faits si la diffusion " android.intention.action.PACKAGE_REMOVED " n'a finalement pas été reçu.

j'espère que cette approche sera utile pour vous :) Car c'est la seule façon à mon avis, nous pouvons résoudre votre problème sans l'enracinement de l'appareil!

[Jour 1] : Approche suggérée pour vérifier si la tâche de désinstallation était annulée :

son genre de drôle que j'ai eu idée tout à fait différente et beaucoup complexe plus tôt(impliquant des émissions, ActivityManager, etc.. etc..), mais en l'écrivant ici juste une autre idée a frappé dans mon esprit qui est comparativement très simple :)

lorsque l'utilisateur clique sur le bouton Désinstaller sous Gérer les paramètres des applications et après que vous avez effectué vos tâches de pré-désinstallation, vous venez de définir un certain SharedPreference dans votre application que vous avez effectué le pré-désinstaller les tâches et sont prêts pour la désinstallation. Après cela, vous n'avez pas besoin de vous soucier de rien.

Si l'utilisateur continue à désinstaller -> son bien, comme vous l'avez déjà effectué les tâches requises.

alors que si l'utilisateur clique finalement sur annuler bouton et s'en va -> ne vous embêtez pas. Jusqu'à ce que l'utilisateur va et exécuter votre application à nouveau. Maintenant dans " onStart ()" / "onResume ()" de l'activité principale de votre application, vous pouvez vérifiez la valeur de SharedPreference et si elle a été définie pour la désinstallation, cela signifie que l'utilisateur n'a pas finalement procédé à la désinstallation. Et maintenant vous pouvez revenir en arrière les changements effectués plus tôt(en inversant les tâches pré-désinstallation effectuées) pour vous assurer que votre application fonctionne parfaitement!

114
répondu AnniJais 2013-09-17 07:34:29

une autre option pour détecter la désinstallation d'app est d'utiliser le code natif.

vous devez surveiller pour votre répertoire en utilisant inotify cadre dans le processus Fourché.

quand il est supprimé, vous pouvez lancer une commande système par exemple. am commande qui démarre Intent

PoC de telle solution: https://github.com/pelotasplus/ActionAfterUninstall/blob/master/app/src/main/jni/hello-jni.c

6
répondu pixel 2015-06-18 18:08:22

il est tout simplement pas possible dans Android

il n'y a aucun moyen pour votre application de savoir qu'elle est désinstallée (sans modifier le noyau). Tous les fichiers créés dans le fichier / data / your.App.paquet est supprimé automatiquement lors de l'installation.

une Autre approche pourrait être d'une autre application qui vérifie si cette application est installée ou non. Si pas, il peut faire le travail de nettoyage.

UPDATE

L'intention ACTIVE_PACKAGE_REMOVED sera envoyée à tous les récepteurs sauf le vôtre. Ceci est confirmé ici .

UPDATE 2

juste une autre pensée.

comme j'ai cherché ceci sur j'ai trouvé que, cela peut être fait en surveillant logcat pour votre application ici est un exemple de moniteur logcat

la bonne chose est que pour surveiller logcat pour la même application, nous n'avons pas besoin d'un dispositif enraciné

et comme nous lisons chaque entrée dans logcat nous pouvons rechercher la chaîne de caractères suivante

Received broadcast Intent { act=android.intent.action.PACKAGE_REMOVED dat=package:com.package.name flg=0x8000010 (has extras) }

comme cet événement est reçu nous savons que notre application va maintenant être non installé""

Ne pas essayer si

encore une fois la surveillance logcat n'est pas autorisé de Android Jellybean

6
répondu Android Fanatic 2016-02-04 18:22:39

pour que votre application persiste, vous aurez besoin d'un périphérique enraciné et être en mesure de l'installer sur la partition système. Une fois que c'est sur là, vous pouvez désinstaller les mises à jour, car ils sont enregistrés le long côté applications non-système, mais ce n'est pas aussi sec pour désinstaller à partir du système.

je sais que certains d'entre eux vont également enregistrer un peu de données sur la partition système juste au cas où les appareils est réinitialisation de l'usine, mais il ya aussi des moyens d'obtenir le gestionnaire de paquets à laissez derrière vous vos données sauvegardées dans le cas où il est juste désinstallé.

une autre option serait de l'enregistrer comme administrateur de périphérique. Une fois que vous aurez fait cela, ils ne pourront pas le désinstaller à moins qu'ils ne suppriment manuellement son statut d'administrateur.

enter image description here

<item name="android.permission.ACCESS_SUPERUSER" />

ici, il semble qu'ils utilisent root ainsi que d'autres méthodes. De faire quelques fous élaborer service, ce qu'ils semblent avoir, il n'y a aucun moyen légitime de faire autrement.

tirer avantage de root est une pratique presque standard pour les applications AV / security comme celle-ci, sans elle, ils n'ont pas d'autorité réelle sur les autres applications, donc ils sont très limités. Je pense que la permission du Super-Utilisateur n'est pas affichée à moins que vous ne l'ayez installée non plus, donc beaucoup de gens ne savent toujours pas que c'est une option.

<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>
0
répondu Jon 2013-09-13 15:21:57