2013-01-10 2 views
1

Je travaille sur un programme qui doit être capable de déterminer ce qui est sur le périphérique android à Xlocation. J'utilise "su ls Xlocation"comment envoyer une commande à l'exécution en utilisant "su" et récupérer toutes les lignes de DataInputStream

Je veux revenir à la liste des fichiers, mais seulement récupérer le premier élément. Ai-je manqué une commande qui obtient la ligne suivante? Ou y a-t-il autre chose que je dois faire?

ci-dessous est ma commande J'envoie

String[] commands = new String[]{"ls /system/app/"}; 
return doCommand(commands); 

Voici ma méthode actuelle pour doCommand

private boolean doCommand(String[] commands) 
    { 
    ArrayList<String> output = new ArrayList<String>(); 

    boolean ran = false; 
    try 
    { 
     Process process = Runtime.getRuntime().exec("su"); 
     DataOutputStream os = new DataOutputStream(process.getOutputStream()); 
     DataInputStream ins = new DataInputStream(process.getInputStream()); 

     // This part works I sends the command right! 
     for (String single : commands) 
     { 
      os.writeBytes(single + "\n"); 
      os.flush(); 
      os.writeBytes("exit\n"); 
      os.flush(); 
      process.waitFor(); 
      ran = true; 
     } 

     int av = -1; 
     while (av != 0) 
     { 

//////////////////////////// WORKING ON THIS TO GET ALL INFO ///////////////// 
      av = ins.available(); 
      if (av != 0) 
      { 
       byte[] b = new byte[av]; 
       ins.read(b); 
       output.add(new String(b)); 
       System.out.println(new String(b) + "Recieved form modem"); 
      } 
     } 
    } 
    catch(Exception ex){} 
    return ran; 
} 

Comme on le voit actuellement, il ne retourne que vrai ou faux. Cependant, en cours de débogage, je n'ai que le premier élément en sortie. (output = "[first.apk")

Edited Newer Version;

public ArrayList<String> doCommand(String[] commands) 
{ 

    ArrayList<String> output = new ArrayList<String>(); 

    try 
    { 

     Process process = Runtime.getRuntime().exec("su"); 
     DataOutputStream os = new DataOutputStream(process.getOutputStream()); 
     DataInputStream ins = new DataInputStream(process.getInputStream()); 
     for (String single : commands) 
     { 
      os.writeBytes(single + "\n"); 

      //os.flush(); 
      output.add("true"); 
     } 
     os.writeBytes("exit\n"); 


     byte[] bc = new byte[10000]; 
     String st = ""; 
     while(ins.read(bc) != -1) 
     { 
     st += new String(bc); 
     os.flush(); 

     } 
     output.add(st); 


     os.flush(); 
     os.close(); 
     ins.close(); 
     process.waitFor();   
    } 
    catch(Exception ex) 
    {} 

    return output; 
} 

Maintenant obtenir une quantité décente de la production, mais pas encore tout où le répertoire a de grandes pièces à l'intérieur limite de taille de l'octet [10000] J'ai vérifié.

Si quelqu'un veut améliorer cela et obtenir une réponse exacte qui fonctionne, je vérifie toujours ce poste.

Merci

Répondre

2

Vous pouvez essayer d'adapter cette méthode à partir de mon application open source de gestion de l'utilisateur (GitHub) à faire ce que vous voulez. Cela va lire chaque ligne de la sortie suite à une commande terminal:

public static String[] getUserList() 
{ 
    Process p; 
    try { 
     p = Runtime.getRuntime().exec("su"); 
     DataOutputStream os = new DataOutputStream(p.getOutputStream()); 
     BufferedReader bf = new BufferedReader(new InputStreamReader(p.getInputStream())); 

      os.writeBytes("pm list-users"+"\n"); 
      os.writeBytes("exit\n"); 
      ArrayList<String> users = new ArrayList<String>(); 
      String test; 
      bf.readLine(); 
      while((test = bf.readLine()) != null) 
      { 
       users.add(test); 
      } 

      String[] userList = (String[]) users.toArray(new String[users.size()]); 



     os.flush(); 
     return userList; 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return null; 
    } 
} 
+0

Ceci est une bonne réponse et l'a aussi bien mais cela ne résout pas mon problème c'est peut-être mon ignorance. Je ne travaille pas pour le cas "ls/system/app/appname _ *" + "\ n" – SatanEnglish

+0

mais fonctionnera pour "ls/system/app /" MON orginal me donne un retour pour l'appname_ * mais c'est tout s'il y a plus de 1 – SatanEnglish

2

Je suis un peu nouveau pour Java, mais je crois que la question est juste un oubli mineur .. ne dans lequel j'ai rencontré quelques fois avec Python;)

Parce que vous avez ajouté le ci-dessous dans votre boucle while:

 os.writeBytes("exit\n"); 
     os.flush(); 

Après chaque itération que vous essayez de quitter la session. Après la première itération, la session terminale serait déjà fermée, ce qui expliquerait pourquoi seul le premier résultat serait renvoyé.

Je suggère d'ajouter le code de sortie après la fin de la boucle while pour vous assurer de ne pas envoyer le reste des commandes à une session morte. Vous pouvez également recréer un os à chaque itération, mais cela semble un peu redondant. ;)

Edit # 1

Je ne suis pas familier avec l'utilisation d'octets, mais je suis capable d'analyser la sortie de mes commandes avec une même boucle while. J'ai également ajouté stderr à l'entrée pour m'assurer que le tampon est vidé en cas de besoin. Au premier coup d'œil sur votre nouveau code, il apparaît que vous définissez une nouvelle chaîne à chaque itération de la boucle while, au lieu d'ajouter la ligne à une variable. Cela entraînerait l'écrasement de votre variable lors de chaque itération. ;)

Voici un code que j'ai utilisé dans le passé pour accomplir des tâches similaires. J'ai rapidement modifié ma source mais je suis actuellement incapable de faire un test.Gardez à l'esprit que votre os est mon stdout, et vos ins est mon stdin.

Runtime   terminal = (Runtime) Runtime.getRuntime(); 
Process   process = terminal.exec("su"); 
DataOutputStream stdout = new DataOutputStream(process.getOutputStream()); 
InputStream  stderr = process.getErrorStream(); 
BufferedReader stdin = new BufferedReader(new InputStreamReader(stderr)); 
String   line  = ""; 
String   output = ""; 

// Execute command and flush 
stdout.writeBytes("your command here\n"); 
stdout.flush(); 

// Append stdin.readLine() to output variable until line is null 
while ((line = stdin.readLine()) != null) 
    output += line; 

// I've had mixed luck getting waitFor() to work, but technically it should force 
// the shell to wait until the command completes. Uncomment it to try it out. 
//process.waitFor(); 
stdout.writeBytes("exit\n"); 
stdout.flush(); 

// Print output to logcat 
System.out.println(output); 
+0

je dois aller ici et mettre à jour mon code je l'ai un peu mieux depuis ce post. Je reçois maintenant la plupart des résultats. Je vais mettre à jour et oui j'ai fini par mettre la plupart de ce hors de la boucle. Mettra à jour mon code si vous avez plus d'idées faites-moi savoir, cependant, ne pas travailler sur ce projet pour un certain temps. – SatanEnglish

+0

"Il semble que vous définissiez une nouvelle chaîne à chaque itération" Où est-ce le cas? Il y a concaténation sur la chaîne st "st ** '+ =' ** new String (bc);". Ou voulez-vous dire ailleurs? De toute façon, je vais essayer de ré-factoriser ce que vous avez ici et voir si cela va fonctionner pour moi quand j'ai le temps suivant Merci – SatanEnglish

Questions connexes