javaSuperUserRequestHowTo

JAVA – Android Design: come richiedere i permessi di root

Roberto Orgiu -

Cosa siano i permessi di root e come ottenerli sul proprio dispositivo sono domande a cui abbiamo già risposto nelle nostre pagine (e nel nostro forum), ma una domanda è tuttora senza risposta: come li otteniamo per la nostra app?

È presto detto: usiamo le API di Android! Sembra una risposta banale, ma sicuramente ci figuriamo un problema maggiore di quanto non sia in realtà; il trucco sta nel creare un nuovo processo che richiamerà “su” ed eseguirà dei comandi per noi, per poi uscire quando abbiamo finito.

Ma vediamo passo passo il nostro codice, partendo dalla creazione del nostro processo.

Process proc = Runtime.getRuntime().exec("su");

Con questa riga, noi chiediamo alla nostra app di avviare una shell con i privilegi di root, semplice, no?

Vediamo ora come possiamo eseguire altri comandi, dichiarando un oggetto di tipo DataOutputStream collegato al nostro processo:

DataOutputStream dos =
           new DataOutputStream(proc.getOutputStream());

Ora, tramite l’istanza dos dell’oggetto DataOutputStream, possiamo eseguire qualsiasi comando che normalmente eseguiremmo da shell, con l’opzione di farci ritornare il risultato grazie ad un’istanza dell’oggetto  DataInputStream, collegata al nostro proc nello stesso modo, così da poter leggere tranquillamente l’output del nostro comando:

DataInputStream dis =
           new DataInputStream(proc.getInputStream());

Ora, possiamo gestire dis e dos con i loro metodi, usando dis.readLine() dopo che abbiamo eseguito un comando che generi un output:

dos.writeBytes(“echo ‘hello’\n”);
dos.flush();
String msg = dis.readLine();

e così via fino a che non abbiamo esaurito i nostri compiti (notiamo lo ‘\n’ che serve un po’ da invio).

Per evitare spiacevoli inconvenienti (ovvero il crash dell’applicazione), è bene richiamare queste istruzioni per uscire dal processo privilegiato:

dos.writeBytes(“exit\n”);
dos.flush();

E il nostro software è in grado così di richiedere i privilegi di root, ma dobbiamo fare ancora un piccolo passo per verificare che tutto sia andato a buon fine, ovvero dobbiamo controllare l’esito delle nostre istruzioni: per farlo, utilizziamo un altro metodo della nostra variabile proc, che ci permette di sapere se tutto è andato come speravamo

int ret = proc.waitFor();

questa specifica istruzione conviene metterla (come tra l’altro ci suggerisce Eclipse) dentro un blocco try-catch, in modo da poter utilizzare l’eccezione che verrà sollevata nel caso i privilegi di root non venissero concessi.

Non ci resta che controllare il valore di ret per essere certi di avere avuto i permessi necessari:

if( ret != 255 ){
// abbiamo avuto i nostri permessi di root
} else {
//non abbiamo ottenuto i permessi
}

Vi chiederete il perché di questa if, se abbiamo detto che il catch serve proprio per gestire l’eventualità in cui i permessi non venissero concessi, questo è vero, ma dobbiamo distinguere due casi: se il telefono non è rootato, allora verrà sollevata l’eccezione, altrimenti, nel caso l’utente ci negasse i permessi (gli viene mostrata la finestra che tutti conosciamo la prima volta), finiremmo nella clausola else, in quanto il root è presente ma a noi viene negato.

Per illustrarvi fisicamente cosa potete fare con queste conoscenze, abbiamo caricato sul market una piccola applicazione che implementa le conoscenze apprese in queste righe, e voi, come le usereste?

 

Android SDK