很多朋友在使用TrineaAndroidCommon@Github中的ShellUtils工具类了,那就大致介绍下他的功能吧。
1、API介绍
1 |
public CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) |
其中commands表示依次执行的shell命令数组
isRoot表示是否以su用户执行(需要手机已经root)
isNeedResultMsg表示是否存储命令执行成功及失败后的信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/** * result of command * * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-5-16 */ public static class CommandResult { /** result of command **/ public int result; /** success message of command result **/ public String successMsg; /** error message of command result **/ public String errorMsg; public CommandResult(int result){ this.result = result; } public CommandResult(int result, String successMsg, String errorMsg){ this.result = result; this.successMsg = successMsg; this.errorMsg = errorMsg; } } |
CommandResult 为返回的数据结构,如下其中result表示执行的结果,根据linux命令执行规则,0表示成功,其他为相应错误码。
successMsg存储执行成功后的输出信息,errorMsg存储执行失败后的输出信息。
如果isNeedResultMsg为false,successMsg和errorMsg会始终为空,而result依然为正常结果。
其他接口,Shell命令支持执行String(单个命令), List(多个命令),String[](多个命令)
2、使用
(1)引入公共库
引入TrineaAndroidCommon@Github(欢迎star和fork^_^)作为你项目的library(如何拉取代码及添加公共库)。
(2) 调用上面介绍的execCommand函数,
注意有些命令可能运行时间较长,所以最好在线程中执行execCommand
3、使用场景
以目前自己的几个场景举下例子
(1) 静默安装和卸载
这个很多朋友已经用过了Android root权限静默安装或卸载应用,原理是执行命令:pm install apkFilePath及pm uninstall packageName
具体代码可见:PackageUtils installSilent(Context context, String filePath, String pmParams)
(2) 获取系统设置->存储->首选安装位置
原理是执行命令:pm get-install-location
具体代码可见:PackageUtils getInstallLocation()
(3) Android修改hosts文件
原理是执行命令:
mount -o rw,remount /system
echo “127.0.0.1 localhost” > /etc/hosts
echo “185.31.17.184 github.global.ssl.fastly.net” >> /etc/hosts
chmod 644 /etc/hosts
代码如下:
1 2 3 4 5 6 |
List<String> commnandList = new ArrayList<String>(); commnandList.add("mount -o rw,remount /system"); commnandList.add("echo \"127.0.0.1 localhost\" > /etc/hosts"); commnandList.add("echo \"185.31.17.184 github.global.ssl.fastly.net\" >> /etc/hosts"); commnandList.add("chmod 644 /etc/hosts"); CommandResult result = ShellUtils.execCommand(commnandList, true); |
用echo命令改hosts文件很牛逼哦,不用重启可以直接生效的哦。
(4) 拷贝文件
原理是执行命令:
mount -o rw,remount /system
cp /mnt/sdcard/xx.apk /system/app/
代码如下:
1 2 |
String[] commands = new String[] { "mount -o rw,remount /system", "cp /mnt/sdcard/xx.apk /system/app/" }; CommandResult result = ShellUtils.execCommand(commands, true); |
注意一般拷贝文件是不需要root的,上面用root是因为需要拷贝到/system/app/下面
请教楼主,如果我把编译版本设置为 compileSdkVersion 23 buildToolsVersion “23.0.3″,gradle提示很多过时的方法,报错,请问这种情况下,如何解决?我是小白,还请赐教!
请教楼主,我的手机是eng版本,有root权限,执行ShellUtils.execCommand(new String[]{” cat /sys/kernel/debug/tcore/tee_version”}, true);报错如下:
07-12 09:11:00.585: W/System.err(8408): java.io.IOException: Error running exec(). Command: [su] Working Directory: null Environment: null
07-12 09:11:00.591: W/System.err(8408): at java.lang.ProcessManager.exec(ProcessManager.java:211)
07-12 09:11:00.602: W/System.err(8408): at java.lang.Runtime.exec(Runtime.java:174)
07-12 09:11:00.611: W/System.err(8408): at java.lang.Runtime.exec(Runtime.java:247)
07-12 09:11:00.615: W/System.err(8408): at java.lang.Runtime.exec(Runtime.java:190)
07-12 09:11:00.617: W/System.err(8408): at com.example.cmdtest.ShellUtils.execCommand(ShellUtils.java:135)
07-12 09:11:00.619: W/System.err(8408): at com.example.cmdtest.ShellUtils.execCommand(ShellUtils.java:80)
07-12 09:11:00.621: W/System.err(8408): at com.example.cmdtest.MainActivity.onCreate(MainActivity.java:33)
07-12 09:11:00.624: W/System.err(8408): at android.app.Activity.performCreate(Activity.java:6286)
07-12 09:11:00.626: W/System.err(8408): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1113)
07-12 09:11:00.628: W/System.err(8408): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2500)
07-12 09:11:00.630: W/System.err(8408): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2613)
07-12 09:11:00.631: W/System.err(8408): at android.app.ActivityThread.-wrap11(ActivityThread.java)
07-12 09:11:00.634: W/System.err(8408): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1469)
07-12 09:11:00.636: W/System.err(8408): at android.os.Handler.dispatchMessage(Handler.java:111)
07-12 09:11:00.637: W/System.err(8408): at android.os.Looper.loop(Looper.java:207)
07-12 09:11:00.640: W/System.err(8408): at android.app.ActivityThread.main(ActivityThread.java:5695)
07-12 09:11:00.641: W/System.err(8408): at java.lang.reflect.Method.invoke(Native Method)
07-12 09:11:00.644: W/System.err(8408): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
07-12 09:11:00.645: W/System.err(8408): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)
07-12 09:11:00.647: W/System.err(8408): Caused by: java.io.IOException: Permission denied
07-12 09:11:00.652: W/System.err(8408): at java.lang.ProcessManager.exec(Native Method)
07-12 09:11:00.654: W/System.err(8408): at java.lang.ProcessManager.exec(ProcessManager.java:209)
07-12 09:11:00.655: W/System.err(8408): … 18 more
怎么解决啊,跪求指教
请教楼主,执行你上面的第4种,拷贝文件命令。报下面错误,是什么情况呢?
01-02 11:39:09.875: W/System.err(29417): java.io.IOException: Error running exec(). Command: [su] Working Directory: null Environment: null
在 shell/命令行自己用 adb 执行试试
多谢楼主回复。
在窗口用命令行是可以的,没报错。
把命令改成下面这一条也报错。String[] commands = new String[] { “mount -o rw,remount /system” };
会否与system下面的su文件有关系?我是手动拷贝了一个进去的。
谢谢!
刚刚没注意,在窗口的话,要先执行 adb root 然后adb shell 后没问题。
如果重启后,直接adb shell ,提示 mount: Permission denied
用工具把手机Root之后执行命令成功了。看来必须把手机Root才行。
已经成功了 这个lib 真好
我的程序 List commandList = new ArrayList(); commandList.add(“mount -o rw,remount /system”); commandList.add(“ping 9.9.9.9 -n 1 -w 5000″); //commandList.add(“echo “185.31.17.184 github.global.ssl.fastly.net” >> /etc/hosts”); commandList.add(“chmod 777 /data/data/nand_test”); CommandResult result = ShellUtils.execCommand(commandList, true); 第一个命令,运行到下面语句的时候报错 os.write(command.getBytes());01-06 16:31:42.792: W/System.err(12280): java.io.IOException: write failed: EPIPE (Broken pipe)01-06 16:31:42.792: W/System.err(12280): at libcore.io.IoBridge.write(IoBridge.java:470)01-06 16:31:42.792: W/System.err(12280): at java.io.FileOutputStream.write(FileOutputStream.java:187)01-06 16:31:42.792: W/System.err(12280): at java.io.DataOutputStream.write(DataOutputStream.java:98)01-06 16:31:42.802: W/System.err(12280): at java.io.OutputStream.write(OutputStream.java:82)01-06 16:31:42.802: W/System.err(12280): at com.spreadtrum.test.util.ShellUtils.execCommand(ShellUtils.java:143)01-06 16:31:42.802: W/System.err(12280): at com.spreadtrum.test.util.ShellUtils.execCommand(ShellUtils.java:68)01-06 16:31:42.802: W/System.err(12280): at com.spreadtrum.test.iprecondition.ComPublicFunction.runShellCommand2(ComPublicFunction.java:605)01-06 16:31:42.802: W/System.err(12280): at com.spreadtrum.test.task.RomOperationTask.doInBackground(RomOperationTask.java:87)01-06 16:31:42.812: W/System.err(12280): at com.spreadtrum.test.task.RomOperationTask.doInBackground(RomOperationTask.java:1)01-06 16:31:42.812: W/System.err(12280): at android.os.AsyncTask$2.call(AsyncTask.java:288)01-06 16:31:42.812: W/System.err(12280): at java.util.concurrent.FutureTask.run(FutureTask.java:237)01-06 16:31:42.812: W/System.err(12280): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)01-06 16:31:42.812: W/System.err(12280): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)01-06 16:31:42.822: W/System.err(12280): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)01-06 16:31:42.822: W/System.err(12280): at java.lang.Thread.run(Thread.java:841)01-06 16:31:42.822: W/System.err(12280): Caused by: libcore.io.ErrnoException: write failed: EPIPE (Broken pipe)01-06 16:31:42.822: W/System.err(12280): at libcore.io.Posix.writeBytes(Native Method)01-06 16:31:42.832: W/System.err(12280): at libcore.io.Posix.write(Posix.java:202)01-06 16:31:42.832: W/System.err(12280): at libcore.io.BlockGuardOs.write(BlockGuardOs.java:197)01-06 16:31:42.832: W/System.err(12280): at libcore.io.IoBridge.write(IoBridge.java:465)01-06 16:31:42.832: W/System.err(12280): … 14 more
mount -o rw,remount /system 去掉,或者加上 write_external 权限看是否可以
谢谢楼主。这个权限本来就有。去掉那个命令也还是一样的错误。
那就不知道了,你可以试试上面的实例程序是否有问题
今天有个新发现我现在试验一个root过的手机。isroot设置为false,就可以执行命令了。估计是因为我的app的user是system,是/data/data的owner。但是却没有权限去执行su?所以使用su就是有上面的错误了。
soga,可以修改用户或目录权限验证下
Pingback: 如何在Android中执行monkey命令 | XiXi的博客
请问LZ,假如我需要执行某一个运行的命令,直到发出停止的信号才结束的这个命令,然后才返回执行结果。就像运行某个监控指令,然后一直运行着,直到手动去关闭它才停止。这个发出的停止信号貌似不能放在同一个execCommand啊,而且我需要模拟这个键盘上按下的ctrl+c的终止信号,这个怎么弄呢?
这个没试过,你得自己搜索
你好,请问一下,跑monkey命令的时候得到错误信息是killed,这是什么原因?
Google 吧,monkey 我也没在程序中执行过
您好,请问,在没有root的情况下,可以用您的库来跑monkey命令吗?
跟你adb shell一样
正好要用到。