370 votes

Déterminer si l'appareil fonctionne sur un appareil rooté

Mon application comporte une certaine fonctionnalité qui ne fonctionnera que sur un appareil où l'option Root est disponible. Plutôt que de faire échouer cette fonctionnalité lorsqu'elle est utilisée (et d'afficher un message d'erreur approprié à l'utilisateur), je préférerais une capacité à vérifier silencieusement si Root est disponible en premier lieu, et si ce n'est pas le cas, de cacher les options respectives en premier lieu.

Existe-t-il un moyen de le faire ?

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 ?

295voto

Kevin Points 4235

Voici une classe qui vérifiera la présence de Root de trois manières différentes.

/** @author Kevin Kowalewski */
public class RootUtil {
    public static boolean isDeviceRooted() {
        return checkRootMethod1() || checkRootMethod2() || checkRootMethod3();
    }

    private static boolean checkRootMethod1() {
        String buildTags = android.os.Build.TAGS;
        return buildTags != null && buildTags.contains("test-keys");
    }

    private static boolean checkRootMethod2() {
        String[] paths = { "/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/system/sd/xbin/su",
                "/system/bin/failsafe/su", "/data/local/su", "/su/bin/su"};
        for (String path : paths) {
            if (new File(path).exists()) return true;
        }
        return false;
    }

    private static boolean checkRootMethod3() {
        Process process = null;
        try {
            process = Runtime.getRuntime().exec(new String[] { "/system/xbin/which", "su" });
            BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
            if (in.readLine() != null) return true;
            return false;
        } catch (Throwable t) {
            return false;
        } finally {
            if (process != null) process.destroy();
        }
    }
}

9 votes

Si deux questions appellent des réponses identiques, il s'agit dans 99 % des cas de doublons, qu'il faut donc signaler comme tels au lieu de poster la même réponse dans les deux cas. Merci de votre compréhension.

0 votes

Il n'est pas identique à 100 %. La réponse que j'ai fournie contient du code pour tenter des commandes enracinées, ce qui n'entraînerait pas une demande de Super Utilisateur à l'utilisateur. La vérification des clés de test ne fonctionne pas sur tous les appareils rootés (cela n'a pas fonctionné sur le mien). Le test de SuperUser.apk n'est pas non plus parfait, les utilisateurs peuvent le désinstaller après avoir obtenu le root.

2 votes

Il se peut que ce soit le cas, mais je vous signale simplement que les réponses exactes en double sont signalé par la communauté. Vous devez adapter vos réponses et répondre aux spécificités du problème du PO. Les réponses copiées-collées risquent d'attirer des votes négatifs.

61voto

Intrications Points 8182

La bibliothèque RootTools propose des méthodes simples pour vérifier la présence de Root :

RootTools.isRootAvailable()

Référence

13 votes

IsRootAvailable() vérifie simplement l'existence de su dans le chemin et de quelques autres répertoires codés en dur. J'ai entendu dire que certains outils de déverrouillage laissent su à cet endroit, ce qui donne un faux positif.

13 votes

RootTools.isAccessGiven() ne se contente pas de vérifier la présence d'un dispositif racine, mais demande également l'autorisation racine ; un dispositif non racine renverra donc toujours un message faux avec cette méthode.

2 votes

@aggregate1166877, vous avez raison, mais ce n'est pas suffisant, et si je ne demande pas l'autorisation de Root quand je la demande ? Je veux juste savoir s'il est enraciné, mais je n'ai pas besoin de l'autorisation Root pour le moment.

61voto

aegean Points 3854

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.

5 votes

C'est très inquiétant. J'avais une classe de détection d'appareil enraciné qui faisait la même chose - après avoir lu ceci, j'ai confirmé ce qu'aegean a détaillé ci-dessus. Des processus zombies occasionnels sont laissés derrière, des ralentissements de l'appareil, etc...

1 votes

Je confirme le problème avec RootTools 3.4 sur un GT-S5830i Android 2.3.6. La plupart des zombies se sont vus allouer de la mémoire et le problème est systématique. Je dois redémarrer l'appareil après 3-4 tests. Je recommande de sauvegarder les résultats des tests dans les préférences partagées.

2 votes

Google recommande maintenant à l'aide de ProcessBuilder() et de la commande start().

23voto

noobProgrammer Points 585

http://code.google.com/p/roottools/

Si vous ne souhaitez pas utiliser le fichier jar il suffit d'utiliser le code :

public static boolean findBinary(String binaryName) {
        boolean found = false;
        if (!found) {
            String[] places = { "/sbin/", "/system/bin/", "/system/xbin/",
                    "/data/local/xbin/", "/data/local/bin/",
                    "/system/sd/xbin/", "/system/bin/failsafe/", "/data/local/" };
            for (String where : places) {
                if (new File(where + binaryName).exists()) {
                    found = true;

                    break;
                }
            }
        }
        return found;
    }

Le programme essaiera de trouver le dossier su :

private static boolean isRooted() {
        return findBinary("su");
    }

Ejemplo:

if (isRooted()) {
   textView.setText("Device Rooted");

} else {
   textView.setText("Device Unrooted");
}

0 votes

Merci de votre attention ! Je l'utilise comme checkRootMethod4() con Réponse de Kevin .

3 votes

Ne jamais ajouter == true à un booléen, cela n'ajoute rien et n'est pas très esthétique.

0 votes

Cela ralentira le téléphone de l'utilisateur de l'application.

13voto

saulobrito Points 1390

Au lieu d'utiliser isRootAvailable(), vous pouvez utiliser isAccessGiven(). Directement de RootTools wiki :

if (RootTools.isAccessGiven()) {
    // your app has been granted root access
}

RootTools.isAccessGiven() ne vérifie pas seulement qu'un appareil est enraciné, il appelle également su. appelle également su pour votre application, demande l'autorisatio votre application a obtenu les permissions d'accès à la racine. Ceci peut être utilisé comme première vérification dans votre application pour vous assurer qu'on vous accordera lorsque vous en aurez besoin.

Référence

0 votes

Mais l'utilisateur doit donner l'accès à la racine, n'est-ce pas ? Donc si mon but est d'empêcher mon application de fonctionner si l'appareil est enraciné, mes options sont vraiment limitées.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X