Ejecutar comandos de shell y obtener resultados en un TextView

Quiero ejecutar algunos shell commands y obtener la salida en un TextView . El comando puede tener una salida continua como ping o logcat . Además, TextView debe desplazarse automáticamente a medida que se añade la salida del comando en tiempo real. Para ello, he hecho esto:

 package com.example.rootapp; import java.io.DataOutputStream; import java.io.InputStream; import android.app.Activity; import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.widget.TextView; public class MainActivity extends Activity { TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String[] cmdArray={"logcat -b radio"}; try { runAsRoot(cmdArray); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void runAsRoot(String[] cmds) throws Exception { tv=(TextView)findViewById(R.id.cmdOp); tv.setMovementMethod(new ScrollingMovementMethod()); Process p = Runtime.getRuntime().exec("su"); DataOutputStream os = new DataOutputStream(p.getOutputStream()); InputStream is = p.getInputStream(); for (String tmpCmd : cmds) { os.writeBytes(tmpCmd+"\n"); int readed = 0; byte[] buff = new byte[4096]; boolean cmdRequiresAnOutput = true; if (cmdRequiresAnOutput) { while( is.available() <= 0) { try { Thread.sleep(5000); } catch(Exception ex) {} } while( is.available() > 0) { readed = is.read(buff); if ( readed <= 0 ) break; String seg = new String(buff,0,readed); tv.append(seg); } } } } } 

Esto funciona bien, pero no actualiza el TextView continuamente. Como se puede ver, estoy ejecutando radio logcat como usuario root, la salida se genera continuamente (ya está marcada en el emulador de terminal y adb shell). Pero en mi caso, la salida no se agrega continuamente. Se detiene después de unas 100 líneas. Aquí está mi diseño:

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/cmdOp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="bottom" android:text="@string/hello_world" /> </ScrollView> </RelativeLayout> 

La salida debe seguir desplazándose por el TextView. Al menos esto es lo que espero …… Cualquier solución para esto, por favor?

2 Solutions collect form web for “Ejecutar comandos de shell y obtener resultados en un TextView”

 // try this way,hope this will help you... Note : "su" command is only run if your device rooted otherwise is gave you exception. public class MainActivity extends Activity { TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView)findViewById(R.id.cmdOp); tv.setText("Output :"+"\n"+runAsRoot()); } public String runAsRoot() { try { // Executes the command. Process process = Runtime.getRuntime().exec("ls -l"); // Reads stdout. // NOTE: You can write to stdin of the command using // process.getOutputStream(). BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream())); int read; char[] buffer = new char[4096]; StringBuffer output = new StringBuffer(); while ((read = reader.read(buffer)) > 0) { output.append(buffer, 0, read); } reader.close(); // Waits for the command to finish. process.waitFor(); return output.toString(); } catch (IOException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } } } 

Creo que el problema es que usted espera 5s para empezar a leer la salida y cuando el programa comienza llega al final de la secuencia, ya que es más rápido que la velocidad de la log se genera. Por lo tanto, es necesario esperar de nuevo durante algún tiempo y empezar a leer el búfer de nuevo. El código siguiente funciona para mí. Utilizo ArrayAdapter + ListView en vez de TextView. Si ponemos m_bTerminate a true entonces el hilo muere la próxima vez que llegue al final del flujo de entrada.

 Process p = Runtime.getRuntime().exec(m_command); InputStream is = p.getInputStream(); while(!m_bTerminate) { while(is.available() <= 0) { try{ Thread.sleep(1000, 0); } catch(Exception e) {m_log.e(e);} } byte[] buff = new byte[4096]; int read = is.read(buff); if(0 < read) { m_List.add(new String(buff, 0, read)); m_handler.sendEmptyMessage(Handler.MSG_RADIO_LOG_NOTIFY_DATASET_CHANGED); //if we call notify datasetchanged directly it raises //android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views //m_Adapter.notifyDataSetChanged(); } } m_log.p(TAG, Log.DEBUG, "Command executed. Destroying thread."); is.close(); p.destroy(); 
  • ¿Ejecutar comandos de Shell a través de código java en Android?
  • ¿Es posible ejecutar un comando de shell como root con sólo el binario su y sin SuperSU o Superuser apk instalado?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.