执行 shell 命令并在 TextView 中获取输出
Posted
技术标签:
【中文标题】执行 shell 命令并在 TextView 中获取输出【英文标题】:Execute shell commands and get output in a TextView 【发布时间】:2014-06-29 18:07:13 【问题描述】:我想执行一些shell commands
并在TextView
中获取输出。该命令可能具有连续输出,例如 ping 或 logcat
。此外,TextView
应在实时添加命令输出时自动滚动。
为了做到这一点,我这样做了:
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);
这工作正常,但它不会持续更新TextView
。如您所见,我正在以 root 用户身份执行 radio logcat,输出是连续生成的(已经在终端模拟器和 adb shell 中检查过)。但就我而言,输出不是连续添加的。它在几百行之后停止。
这是我的布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
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_
android:layout_ >
<TextView
android:id="@+id/cmdOp"
android:layout_
android:layout_
android:gravity="bottom"
android:text="@string/hello_world" />
</ScrollView>
</RelativeLayout>
输出应继续滚动 TextView。至少这是我所期望的......请问有什么解决方法吗?
【问题讨论】:
【参考方案1】:您可以运行命令并将命令输出显示为文本,如下所示:
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);
注意:“su”命令只有在设备被 root 后才会运行。否则会抛出异常。
【讨论】:
Runtime.getRuntime().exec("ls -l") 适用于 Android 5,但不适用于 Android 7。获取退出代码 1。有什么想法吗?【参考方案2】:我认为问题在于您等待 5s 开始读取输出,并且当程序启动时它到达流的末尾,因为它比生成日志的速度快。因此,您需要再次等待一段时间并再次开始读取缓冲区。以下代码适用于我。我使用 ArrayAdapter + ListView 而不是 TextView。如果我们将 m_bTerminate 设置为 true,那么线程在下一次到达输入流的末尾时就会终止。
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();
【讨论】:
【参考方案3】:使用这个 String 函数并将结果存储到您的 TextView 或任何您想要的地方
public String shell_exec(String cmd)
String o=null;
try
Process p=Runtime.getRuntime().exec(cmd);
BufferedReader b=new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while((line=b.readLine())!=null)o+=line;
catch(Exception e)o="error";
return o;
使用示例:
mytextview.setText(shell_exec("ls -l"));
【讨论】:
以上是关于执行 shell 命令并在 TextView 中获取输出的主要内容,如果未能解决你的问题,请参考以下文章