1.路徑最好不要是自己拼寫的路徑/mnt/shell/emulated/0/wifidog.conf 最好是通過方法獲取的路徑,不然可能導致命令無效 (掛載點的原因) public static final String SDCARD_ROOT=Environment.getExternalStor ...
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";
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:10000
I/auto ( 5542): run is go to end
I/auto ( 5542): read ErrorStream over
I/auto ( 5542): read InputStream over
I/auto ( 5542): run command process end
I/auto ( 5542): run is end
I/auto ( 5542): getResult
I/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:0D
I/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();