如何使用 ADB 重定向 Android 应用程序 stdout/stderr?

如何使用 ADB 重定向 Android 应用程序 stdout/stderr?

我想让一些 Android 命令行应用程序的软件开发过程更加自动化。几年前,我会在实体 Android 设备上安装 Busybox,拿来显微镜,然后开始在 Emacs for Android 中输入代码。如今,我正在寻找一种更方便的编码方式。

具体来说,我想重定向 Android(NDK)应用程序的 stdout 和 stderr 文件描述符,类似于 qemu-arm64-static 的工作方式。

有人知道这是否可以通过 ADB 实现吗?作为替代方案,我可以将我的应用程序构建为微服务并使用 ADB 端口转发。但这样做会失去很多经典的 UNIX 惯例。

我看到 ADB 具有日志捕获功能,可用于 NDK (log.h) 和 SDK (Log.class) 消息。但遗憾的是,我没有找到将主机 STDIN 重定向到 Android 客户机应用程序 STDIN 的明确方法。

也许有一种方法可以通过 adb 触发 Toybox(mksh)并在那里发送自定义 sh 命令?

答案1

各种来源(例如https://stackoverflow.com/a/36561699/340175https://github.com/android/ndk/issues/671#issuecomment-383890481)建议采用https://codelab.wordpress.com/2014/11/03/how-to-use-standard-output-streams-for-logging-in-android-apps/

为了方便后人理解,该博客文章中的代码如下:

static int pfd[2];
static pthread_t thr;
static const char *tag = "myapp";

int start_logger(const char *app_name)
{
    tag = app_name;

    /* make stdout line-buffered and stderr unbuffered */
    setvbuf(stdout, 0, _IOLBF, 0);
    setvbuf(stderr, 0, _IONBF, 0);

    /* create the pipe and redirect stdout and stderr */
    pipe(pfd);
    dup2(pfd[1], 1);
    dup2(pfd[1], 2);

    /* spawn the logging thread */
    if(pthread_create(&thr, 0, thread_func, 0) == -1)
        return -1;
    pthread_detach(thr);
    return 0;
}

static void *thread_func(void*)
{
    ssize_t rdsz;
    char buf[128];
    while((rdsz = read(pfd[0], buf, sizeof buf - 1)) > 0) {
        if(buf[rdsz - 1] == '\n') --rdsz;
        buf[rdsz] = 0;  /* add null-terminator */
        __android_log_write(ANDROID_LOG_DEBUG, tag, buf);
    }
    return 0;
}

这涉及编写和/或修改代码。

有一种过时的方法可能仍然适用于某些旧版本 Android 模拟器(我还没有尝试过),Stack Overflow 上的一篇姊妹文章中对此进行了讨论:https://stackoverflow.com/questions/10531050/redirect-stdout-to-logcat-in-android-ndk我认为尝试在此重现该问答中的讨论是不明智的,特别是因为选择取决于该主题中讨论的各种因素。一旦取得进展,请更新此主题。

相关内容