Robotium 哪位大侠有空来解救一下吧。ROBOTIUM 虚拟机怎么执行 ADB SHELL 的命令啊?

magicyang · 2015年01月15日 · 最后由 qing 回复于 2015年02月06日 · 3997 次阅读

正在实践前两天论坛大侠写得关于 ADB 实现 ROBOTIUM 跨进程的问题。
@xuxu @qinggchu
实际操作的时候出了状况。
目前发现所有的 ADB SHELL 命令都实际没有执行。

CMD 直接进 ADB SHELL 都是可以用得。UIAUTOMATOR 可以 DUMP 出来。
但是在 ROBOTIUM 里面就是取不出来。
试了一下连 LS 都取不出。

C:\Users\yangch>adb shell
root@generic_x86:/ # ls
ls
直接进的是 ROOT 用户,这打印说明不用再 ROOT 了吧?

MANIFEST 也增加了 sharedUserId 的权限。
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:sharedUserId="android.uid.system"
/>
哪位大侠以前弄过?这里还有什么坑没填过去?还是 INSTRUMENT 的架构就不能直接调 ADB SHELL?
还是源 APK 也要修改一些内容?暂时搞不定了。。。求解救。
掉得是 XUXU 提供的 ADB 库。
附基本的代码:

        Log.v("mainActivity",ShellUtils.getShellOut(ShellUtils
                 .shell("ls")));
   调用链
    public static Process shell(String command) {
        return process("adb shell " + command);
    }

    public static BufferedReader shellOut(Process ps) {
        BufferedInputStream in = new BufferedInputStream(ps.getInputStream());
        BufferedReader br = new BufferedReader(new InputStreamReader(in));

        return br;
    }

    public static String getShellOut(Process ps) {
        StringBuilder sb = new StringBuilder();
        BufferedReader br = shellOut(ps);
        String line;

        try {
            while ((line = br.readLine()) != null) {
                sb.append(line);
//          sb.append(line + System.getProperty("line.separator"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return sb.toString();
    }

    private static Process process(String command) {
        Process ps = null;
        try {
            ps = Runtime.getRuntime().exec(command);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return ps;
    }
共收到 14 条回复 时间 点赞

谢谢。这里有个坑,我会找个时间填下。
instrumentation 是可以调用 shell 命令的,但不是 adb shell 命令。
你要使用的话,需要将 xuxu.autotest.utils.ShellUtils 类中的 shell 方法改下:

    public static Process shell(String command) {
//      return process("adb shell " + command);
        return process(command);
    }

去掉 adb shell,其实就是直接 Runtime.getRuntime.exec("ls")。
稍后我会在该工具类下单独提供个方法执行 shell 命令。

另外你要获取 ls 命令的输出时,可以将 getShellOut 方法中:


//          sb.append(line + System.getProperty("line.separator"));

将该句的注释去掉,同时将注释掉 sb.append(line);
否则的话打印结果不会换行显示。去掉注释后就可以换行显示了,附张我运行的结果:

Log.v("mainActivity", ShellUtils.getShellOut(ShellUtils.shell("ls -l ")));

@xuxu 谢谢啊,ls 命令是搞定了。
不过下面这个命令,执行后没有生成
ShellUtils.shell("uiautomator dump /data/local/tmp/uidump2.xml");一直都没有对应的文件啊。
这块以前没有接触过,按照大侠你的说法,uiautomator dump 这种用法是 ADB SHELL 才支持,在 INSTRUMENTATION 架构下实际上是不支持的?
呵呵,大侠我主要是想通过你的接口绕进程。关键是上面这个命令。~

@xuxu
好像是我理解错了。。。。SHELL 应该是一样的吧?
这里有什么文件系统权限的坑么?直接 ADB 命令和 ROBOTIUM 调用有啥区别么?
麻烦大侠了~

#3 楼 @yangchengtest 这个跟 uiautomator 的调用权限有关. apk 默认执行的时候很多权限会被限制. adb 则是被赋予来更多的权限, 包括注入事件的权限, 所以 adb 调用 uiautomator 是没问题的.

@seveniruby @xuxu
谢谢两位大侠了,不得不暂时放弃尝试使用该方法在 ROBOTIUM 架构内部来做跨进程了。
反馈一下当下的进展吧:
1.目前用 RUNTIME.EXEC 的返回的 PS 结果是 9。不是 0。
PROCESS 的 WAITFOR 的返回值解释是:the exit value of the native process being waited on。PS 就没看到 PID=9 的进程。。。。
2.将目的路劲放到了 SD 卡里,SD 卡的读写权限我开了,还是不行。
暂时没招了。系统权限的水现在对我来说还是太深了。~

#6 楼 @yangchengtest 百度 cafe 早就解决来跨进程的测试来. 你可以参考下. github 上搜索 cafe 框架

@seveniruby 感谢思寒,呵呵,是我肤浅了,把问题想的太简单了。。。
不过这次填这坑,也算是熟悉了一下 RUNTIME 机制和 ANDROID 简单的 SHELL 了。
后面去学习一下 CAFE 的框架。~
顺带感慨下,还有好多深坑不会啊,如 HTML,JS。再次感谢两位大侠。~

@yangchengtest 关于这个 ShellUtils.shell("uiautomator dump /data/local/tmp/uidump2.xml");没有生成 uidump 的文件这个问题我也遇到过,当时记得是修改了下生成文件的超时时间,后来再试了下就没有问题了,但确实有些人用了这个框架都反应了有这个问题,貌似是不稳定,后续再检查下有没有什么方法来避免这个问题。现在如果实在你那边生成有问题的话,建议手工先导出 uidump.xml,稍微修改下源码,然后放到指定目录让脚本去读,应该就没问题了,你可以试试。

@qinggchu 谢谢回复啊~
我用 RUNTIME.EXEC 延时到 100S 在 SDCARD 都没有取到。RUNTIME 操作没有返回出错,返回的 LOG 最后就是没有写文件这一步。感觉应该和 APK 的系统权限有关系。
从理论上看,如果能先把 UIAUTOMATOR 进程起来,就能解决了。UIAUTOMATOR 的进程没有起来。我回头再看看有没有办法在 APK 里面用命令起进程。
不知道这个区别是不是和 API 的版本有关,我用的是 API19 的。UIAUTOMATOR 今天有大神不是说 ANDROID 4,4 重新封装过,你用的是哪个版本的 API?
呵呵,我最近正好事不多,学点新的填填以前的坑。不行还是回去老老实实用 APPIUM 做跨进程了~。

@yangchengtest 我用的 4.2.2 的版本。你可以试试自己导出 uidump 放到对应的路径上,再试试脚本能不能正确执行,关于 uiautomator 的启动问题,回头再研究研究。

#10 楼 @yangchengtest 报 InputStream Cannot be null 的异常原因基本查明,是 adb 运行在手机内受到 android 系统目录权限的问题导致的。具体的分析可以参考:http://blog.csdn.net/qingchunjun/article/details/43343735
我重新修改了下原来的框架源码,把 uidump 那个方法针对手机环境进行了重写,你可以从http://download.csdn.net/detail/qingchunjun/8419323 下载下来试试看还有没有问题。

@qinggchu 先谢谢啊~
这个我前面已经试过了,我一直都是写在 SDCARD 目录下的。目录权限改的是 777,在 4.4 以后还是没法操作的。
这个问题是这样的,我个人是这么理解,在其他 APP 中调用 UIAUTOMATOR 本身就是一个安全隐患。这样就可以利用此操作嵌入其他 APK,获取数据。4.4 版本后该命令重构过,应该是对该命令加入了权限管理,API 只提供了一个调用 UIAUTOMATOR 实例的方法。这也就造成了在 4.4 下使用该方法,只返回 PID,但是看不到实际进程,没有任何报错,但就是不写文件的现状~
当然这是我根据自己环境和操作后的总结,如果有兴趣的话,你可以试试 4.4 以上的能不能操作。~

4.4 的版本还没有测试过,如果命令重构过的话,就要看看源码里面具体有什么改动了。一般来说,可以直接在 shell 命令行里面直接查询/system/bin 下的 uiautomator 的调用权限,只要有调用权限,调用就应该是正常的。

16楼 已删除
xuxu Robotium 处理跨进程的问题 中提及了此贴 02月04日 13:24
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册