zoukankan      html  css  js  c++  java
  • 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("
    ");
                os.flush();
    
                os.writeBytes("exit
    ");
                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 += "
    ";
                                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 += "
    ";
                                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();
  • 相关阅读:
    理解HTTP幂等性
    企业技术树
    数据库MySQL-Oracle-DB2-SQLServer分页查询
    Redis安装教程
    Redis VS Memcached
    Redis简介
    Redis系列文章导读
    坐标轴
    图例
    画网格
  • 原文地址:https://www.cnblogs.com/lipeineng/p/6078859.html
Copyright © 2011-2022 走看看