Dans mon application, je vérifiais si l'appareil était enraciné ou non en exécutant la commande "su". Mais aujourd'hui, j'ai supprimé cette partie de mon code. Pourquoi ?
Parce que mon application est devenue un tueur de mémoire. Comment ? Laissez-moi vous raconter mon histoire.
Certains se sont plaints que mon application ralentissait les appareils (j'ai bien sûr pensé que ce n'était pas possible). J'ai essayé de comprendre pourquoi. J'ai donc utilisé MAT pour obtenir des heap dumps et les analyser, et tout semblait parfait. Mais après avoir relancé mon application plusieurs fois, j'ai réalisé que l'appareil devenait vraiment plus lent et que l'arrêt de mon application ne le rendait pas plus rapide (à moins de redémarrer l'appareil). J'ai de nouveau analysé les fichiers dumps alors que l'appareil était très lent. Mais tout était encore parfait pour le fichier dump. J'ai alors fait ce qu'il fallait faire en premier. J'ai listé les processus.
$ adb shell ps
Surprise, il y avait plusieurs processus pour ma demande (avec la balise de processus de ma demande au manifeste). Certains d'entre eux étaient des zombies, d'autres non.
Avec un exemple d'application qui n'a qu'une seule activité et qui n'exécute que la commande "su", je me suis rendu compte qu'un processus zombie était créé à chaque lancement de l'application. Au début, ces processus zombies allouent 0 Ko, puis quelque chose se produit et les processus zombies détiennent presque les mêmes Ko que le processus principal de mon application et ils deviennent des processus standard.
Il existe un rapport de bogue pour le même problème sur bugs.sun.com : http://bugs.sun.com/view_bug.do?bug_id=6474073 Ceci explique que si la commande n'est pas trouvée, les zombies seront créés avec la méthode exec(). Mais je ne comprends toujours pas pourquoi et comment ils peuvent devenir des processus autonomes et détenir des KBs significatifs. (Cela ne se produit pas tout le temps)
Vous pouvez essayer si vous le souhaitez avec l'exemple de code ci-dessous ;
String commandToExecute = "su";
executeShellCommand(commandToExecute);
Méthode simple d'exécution des commandes ;
private boolean executeShellCommand(String command){
Process process = null;
try{
process = Runtime.getRuntime().exec(command);
return true;
} catch (Exception e) {
return false;
} finally{
if(process != null){
try{
process.destroy();
}catch (Exception e) {
}
}
}
}
En résumé, je n'ai pas de conseil à vous donner pour déterminer si votre appareil est enraciné ou non. Mais si j'étais vous, je n'utiliserais pas Runtime.getRuntime().exec().
D'ailleurs, RootTools.isRootAvailable() pose le même problème.
20 votes
Il n'existe aucun moyen fiable de le faire ; les réponses ci-dessous vérifient des caractéristiques communes, mais un appareil donné peut ne pas être enraciné de la même manière. Si la vérification de l'enracinement devient courante, les solutions d'enracinement commenceront probablement à faire des efforts pour se cacher. Puisqu'elles peuvent modifier le comportement du système d'exploitation, elles disposent de nombreuses options pour le faire.
0 votes
Il peut être préférable d'indiquer que la fonction n'est pas disponible en raison de l'absence de capacité de la racine, ce qui permet de mieux informer l'utilisateur, plutôt que de masquer les capacités de votre application, ce qui ajoute de l'ambiguïté à l'expérience globale.
0 votes
Les réponses ci-dessous sont-elles valables pour Racine sans système ?
2 votes
Cela fonctionne, mais si l'outil Root cloaking/hiding tel que MagiskHide est activé, vous êtes condamné, car c'est finalement une impasse et il n'y a aucun moyen de s'en sortir.