你的位置:首页 > 操作系统

[操作系统]Android 在Android代码中执行命令行


1.路径最好不要是自己拼写的路径/mnt/shell/emulated/0/wifidog.conf

最好是通过方法获取的路径,不然可能导致命令无效  (挂载点的原因)

public static final String SDCARD_ROOT=Environment.getExternalStorageDirectory().getAbsolutePath(); 

public static final String AAA_PATH=SDCARD_ROOT+"/wifidog.conf";

 

Android 命令行执行工具类

package com.example.videotest.utils;import android.os.Environment;import android.util.Log;import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.InputStreamReader;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;import static java.lang.Runtime.getRuntime;/** * 执行命令的类 * Created by Kappa */public class ExeCommand {  //shell进程  private Process process;  //对应进程的3个流  private BufferedReader successResult;  private BufferedReader errorResult;  private DataOutputStream os;  //是否同步,true:run会一直阻塞至完成或超时。false:run会立刻返回  private boolean bSynchronous;  //表示shell进程是否还在运行  private boolean bRunning = false;  //同步锁  ReadWriteLock lock = new ReentrantReadWriteLock();  //保存执行结果  private StringBuffer result = new StringBuffer();  /**   * 构造函数   *   * @param synchronous true:同步,false:异步   */  public ExeCommand(boolean synchronous) {    bSynchronous = synchronous;  }  /**   * 默认构造函数,默认是同步执行   */  public ExeCommand() {    bSynchronous = true;  }  /**   * 还没开始执行,和已经执行完成 这两种情况都返回false   *   * @return 是否正在执行   */  public boolean isRunning() {    return bRunning;  }  /**   * @return 返回执行结果   */  public String getResult() {    Lock readLock = lock.readLock();    readLock.lock();    try {      Log.i("auto", "getResult");      return new String(result);    } finally {      readLock.unlock();    }  }  /**   * 执行命令   *   * @param command eg: cat /sdcard/test.txt   * 路径最好不要是自己拼写的路径,最好是通过方法获取的路径   * example:Environment.getExternalStorageDirectory()   * @param maxTime 最大等待时间 (ms)   * @return this   */  public ExeCommand run(String command, final int maxTime) {    Log.i("auto", "run command:" + command + ",maxtime:" + maxTime);    if (command == null || command.length() == 0) {      return this;    }    try {      process = getRuntime().exec("sh");//看情况可能是su    } catch (Exception e) {      return this;    }    bRunning = true;    successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));    errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));    os = new DataOutputStream(process.getOutputStream());    try {      //向sh写入要执行的命令      os.write(command.getBytes());      os.writeBytes("\n");      os.flush();      os.writeBytes("exit\n");      os.flush();      os.close();      //如果等待时间设置为非正,就不开启超时关闭功能      if (maxTime > 0) {        //超时就关闭进程        new Thread(new Runnable() {          @Override          public void run() {            try {              Thread.sleep(maxTime);            } catch (Exception e) {            }            try {              int ret = process.exitValue();              Log.i("auto", "exitValue Stream over"+ret);            } catch (IllegalThreadStateException e) {              Log.i("auto", "take maxTime,forced to destroy process");              process.destroy();            }           }        }).start();      }      //开一个线程来处理input流      final Thread t1 = new Thread(new Runnable() {        @Override        public void run() {          String line;          Lock writeLock = lock.writeLock();          try {            while ((line = successResult.readLine()) != null) {              line += "\n";              writeLock.lock();              result.append(line);              writeLock.unlock();            }          } catch (Exception e) {            Log.i("auto", "read InputStream exception:" + e.toString());          } finally {            try {              successResult.close();              Log.i("auto", "read InputStream over");            } catch (Exception e) {              Log.i("auto", "close InputStream exception:" + e.toString());            }          }        }      });      t1.start();      //开一个线程来处理error流      final Thread t2 = new Thread(new Runnable() {        @Override        public void run() {          String line;          Lock writeLock = lock.writeLock();          try {            while ((line = errorResult.readLine()) != null) {              line += "\n";              writeLock.lock();              result.append(line);              writeLock.unlock();            }          } catch (Exception e) {            Log.i("auto", "read ErrorStream exception:" + e.toString());          } finally {            try {              errorResult.close();              Log.i("auto", "read ErrorStream over");            } catch (Exception e) {              Log.i("auto", "read ErrorStream exception:" + e.toString());            }          }        }      });      t2.start();      Thread t3 = new Thread(new Runnable() {        @Override        public void run() {          try {            //等待执行完毕            t1.join();            t2.join();            process.waitFor();          } catch (Exception e) {          } finally {            bRunning = false;            Log.i("auto", "run command process end");          }        }      });      t3.start();      if (bSynchronous) {        Log.i("auto", "run is go to end");        t3.join();        Log.i("auto", "run is end");      }    } catch (Exception e) {      Log.i("auto", "run command process exception:" + e.toString());    }    return this;  }}

讲解一下关键点,首先是启动一个sh进程,当然如果你用的是root的设备,可以使用su。

这个进程包含 input、output、error 三个流,这三个流要处理好,否则可能不能正常结束进程,

另外也存在执行的命令已经结束,但是依然还有input流的情况,也需要处理。

其他请参考代码

 

使用方式为2种。首先是阻塞方式,这种调用方式会一直阻塞至命令执行完成,返回命令行的输出结果

public static final String SDCARD_ROOT=Environment.getExternalStorageDirectory().getAbsolutePath();           public static final String AAA_PATH=SDCARD_ROOT+"/wifidog.conf";//读取目标文件(绝对路径)指定内容“#TrustedMACList ”的那一行String cmd3="sed -n '/#TrustedMACList /,//p' "+AAA_PATH;String str3 = new ExeCommand().run(cmd3, 10000).getResult();Log.i("auto", str3+"button3");Toast.makeText(MainActivity.this, str3,Toast.LENGTH_SHORT).show();

LOG   程序执行的顺序

I/auto  ( 5542): run command:sed -n '/#TrustedMACList /,//p' /storage/emulated/0/wifidog.conf,maxtime:10000I/auto  ( 5542): run is go to endI/auto  ( 5542): read ErrorStream overI/auto  ( 5542): read InputStream overI/auto  ( 5542): run command process endI/auto  ( 5542): run is endI/auto  ( 5542): getResultI/auto  ( 5542): #TrustedMACList 00:00:C0:1D:F0:0D,00:00:C0:1D:F0:0D,00:00:C0:1D:F0:0D,00:00:C0:1D:F0:0D,00:00:C0:1D:F0:0D,00:00:DE:AD:BE:AF,00:00:C0:1D:F0:0DI/auto  ( 5542): I/auto  ( 5542): button3

 

 

 

还有一种是异步方式,这种调用方式会直接返回,之后可以使用 getResult() 获取结果,使用 isRunning() 来判断是否完成,比如

 ExeCommand cmd = new ExeCommand(false).run("your cmd", 60000);  while(cmd.isRunning())  {    try {      sleep(1000);    } catch (Exception e) {    }    String buf = cmd.getResult();    //do something  }

 

 

 

 

 

 

 

//修改目标文件指定内容“#TrustedMACList ”
String cmd="sed -i 's/#TrustedMACList /#TrustedMACList 00:00:C0:1D:F0:0D,/g' "+AAA_PATH;String str = new ExeCommand().run(cmd, 10000).getResult();Log.i("auto", str+"button4");Toast.makeText(MainActivity.this, str,Toast.LENGTH_SHORT).show();