Android远程编译

是否可以利用性能较好的服务器云编译Android项目,再同步到本地,为渣渣的本地设备赋能?

Android远程编译

是否可以利用性能比较好的服务器进行云编译,下载安装包到本地再安装到设备上,为渣渣的本地设备赋能?

一、搭建编译环境

既然是远程编译,肯定要在远程机器上有对应的编译环境。

1.1 Linux安装配置

1.1.1 安装Linux

系统安装跳过,大家根据自己的设备进行安装,我这里安装的是 Ubuntu Server 22.04 LTS

1.1.2 安装配置openssh-server

为了方便在本地笔记本操作服务器,需要安装ssh。

  1. 安装openssh-server
zwenkai@ubuntu:~$ sudo apt-get install openssh-server
  1. 配置开机启动
zwenkai@ubuntu:~$ sudo systemctl enable ssh  # 开启开机自启动
sudo systemctl disable ssh # 关闭开机自启动
reboot
sudo systemctl status ssh  # 查看ssh是否启动

1.1.3 ssh登录

  1. 查看ip地址

如果使用的是云服务器,购买的时候可以选择搭配固定IP套餐,就不需要在设备上查看了。

通过ipconfig命令查看,IPV4的地址为192.168.31.6

zwenkai@ubuntu:~$ ifconfig
enp3s0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether 1c:83:41:31:41:0c  txqueuelen 1000  (以太网)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device memory 0xfc600000-fc6fffff
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (本地环回)
        RX packets 211  bytes 17428 (17.4 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 211  bytes 17428 (17.4 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
wlp4s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.31.6  netmask 255.255.255.0  broadcast 192.168.31.255
        inet6 fe80::3ee3:c403:35db:1541  prefixlen 64  scopeid 0x20<link>
        ether 10:6f:d9:27:bf:01  txqueuelen 1000  (以太网)
        RX packets 3619  bytes 1416277 (1.4 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 190  bytes 22587 (22.5 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  1. 登录ssh
zhouwenkai@zhouwenkaideMacBook-Pro ~ % ssh zwenkai@192.168.31.6
zwenkai@192.168.31.6's password:
Welcome to Ubuntu 22.04 LTS (GNU/Linux 5.15.0-40-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

0 updates can be applied immediately.

Last login: Sat Jul  2 08:40:10 2022 from 192.168.31.230

1.1.4 配置SSH免密登录

通过SSH登录时,需要交互式地输入密码,这样会阻断操作,所以我们希望可以配置免密登录。

  1. 本机生成公私钥

本地客户端通过 ssh-keygen 生成公私钥:(一路回车默认即可)

zhouwenkai@zhouwenkaideMacBook-Pro ~ % ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/zhouwenkai/.ssh/id_rsa):
Created directory '/Users/zhouwenkai/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/zhouwenkai/.ssh/id_rsa
Your public key has been saved in /Users/zhouwenkai/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:8M6T0FaduaBsrGMAHXvY4oZS++vx6U6iIJENS1Vx+vg zhouwenkai@zhouwenkaideMacBook-Pro.local
The key's randomart image is:
+---[RSA 3072]----+
|   .oo..         |
|  .. =o    . o   |
|..o =.+   o +    |
|.* = oo* o . .   |
|= + +...S   .    |
| o o ..B .       |
|o   + =E=        |
|.. . B o .       |
|  ..oo=          |
+----[SHA256]-----+

可以看到,已经创建了私钥和公钥。

zhouwenkai@zhouwenkaideMacBook-Pro ~ % ls ~/.ssh
id_rsa        id_rsa.pub
  1. 上传公钥到服务器

通过 ssh-copy-id 命令,将公钥上传到服务端登录用户的.ssh目录下的authorized_keys文件内。

zhouwenkai@zhouwenkaideMacBook-Pro ~ % ssh-copy-id zwenkai@192.168.31.6
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/Users/zhouwenkai/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
zwenkai@192.168.31.6's password:

Number of key(s) added:        1

Now try logging into the machine, with:   "ssh 'zwenkai@192.168.31.6'"
and check to make sure that only the key(s) you wanted were added.
  1. 测试远程登录

再次通过ssh登录,发现已经不再需要密码啦。

zhouwenkai@zhouwenkaideMacBook-Pro ~ % ssh zwenkai@192.168.31.6
Welcome to Ubuntu 22.04 LTS (GNU/Linux 5.15.0-40-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

0 updates can be applied immediately.

Last login: Sat Jul  2 22:39:51 2022 from 192.168.31.230

1.2 搭建Android环境

1.2.1 创建环境目录

为了统一管理,把所有的环境都放在/buildkit目录下,并创建一个777权限的tmp临时文件夹。

zwenkai@ubuntu:~$ sudo -i
root@ubuntu:~# cd /
root@ubuntu:/# mkdir buildkit
root@ubuntu:/# mkdir /buildkit/tmp
root@ubuntu:/# chmod 777 /buildkit/tmp

1.2.2 配置JDK

官方地址下载Java11(具体的版本根据自己的需求选择),如果没有账号建议注册一个。由于下载JDK需要登录态,不能像低版本一样可以采用wget命令直接在服务端下载,我们先下载到本地,再通过scp的方式上传到服务器。

Android远程编译

本机通过scp上传JDK文件到服务器临时目录。

zhouwenkai@zhouwenkaideMacBook-Pro Downloads % scp jdk-11.0.15.1_linux-x64_bin.tar.gz zwenkai@192.168.31.6:/buildkit/tmp
zwenkai@192.168.31.6's password:
jdk-11.0.15.1_linux-x64_bin.tar.gz                                                     100%  161MB  13.8MB/s   00:11

切换到服务端,解压JDK/buildkit/java目录,并移除原始文件。

root@ubuntu:/# cd buildkit/
root@ubuntu:/buildkit# mkdir java
root@ubuntu:/buildkit# tar -zxvf tmp/jdk-11.0.15.1_linux-x64_bin.tar.gz -C java/
root@ubuntu:/buildkit# rm -rf tmp/jdk-11.0.15.1_linux-x64_bin.tar.gz

配置Java环境变量,通过vim编辑/etc/profile,添加环境变量。

root@ubuntu:/buildkit# vim /etc/profile
# Java环境变量
export JAVA_HOME=/buildkit/java/jdk-11.0.15.1
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

更新环境变量,查询Java版本,输出版本信息就是配置完成了。

root@ubuntu:/buildkit# source /etc/profile
root@ubuntu:/buildkit# java -version
java version "11.0.15.1" 2022-04-22 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.15.1+2-LTS-10)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.15.1+2-LTS-10, mixed mode)

这里多说一句,如果只是用来编译项目的话,可以只配置JAVA_HOME环境变量。

1.2.3 配置Android SDK

Android Studio官网下载commandlinetools工具,以便通过它来管理Android SDK。

Android远程编译
root@ubuntu:/buildkit# wget -O tmp/commandlinetools-linux-8512546_latest.zip  https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip
--2022-07-02 09:15:56--  https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip
正在解析主机 dl.google.com (dl.google.com)... 142.250.186.110, 2a00:1450:4001:829::200e
正在连接 dl.google.com (dl.google.com)|142.250.186.110|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 114168525 (109M) [application/zip]
正在保存至: ‘tmp/commandlinetools-linux-8512546_latest.zip’

tmp/commandlinetools-lin 100%[===============================>] 108.88M  15.0MB/s    用时 8.7s

2022-07-02 09:16:06 (12.5 MB/s) - 已保存 ‘tmp/commandlinetools-linux-8512546_latest.zip’ [114168525/114168525])

解压commandlinetools工具,由于解压后执行会报错,具体参考 cmdline-tools : could not determine SDK root,我们对目录进行下修改,然后删除原始文件。

root@ubuntu:/buildkit# mkdir android-sdk
root@ubuntu:/buildkit# unzip -d android-sdk/cmdline-tools/ tmp/commandlinetools-linux-8512546_latest.zip
root@ubuntu:/buildkit# mv android-sdk/cmdline-tools/cmdline-tools/ android-sdk/cmdline-tools/tools/
root@ubuntu:/buildkit# rm -rf tmp/commandlinetools-linux-8512546_latest.zip

安装需要的platforms和build-tools版本,这类安装的Android30和Android31(具体根据自己的情况选择)。喝杯水,稍做等候,一会儿就会安装完成。

多说一句,后续环境升级了,也可以到远程编译机来下载对应的版本(公司的远程编译机支持多个团队,经常有人找我升级版本 😊)。

root@ubuntu:/buildkit# yes | /buildkit/android-sdk/cmdline-tools/tools/bin/sdkmanager "platforms;android-30" && \
> yes | /buildkit/android-sdk/cmdline-tools/tools/bin/sdkmanager "build-tools;30.0.3" && \
> yes | /buildkit/android-sdk/cmdline-tools/tools/bin/sdkmanager "platforms;android-31" && \
> yes | /buildkit/android-sdk/cmdline-tools/tools/bin/sdkmanager "build-tools;31.0.0"
[=======================================] 100% Unzipping... android-11/frameworkSDK Platform 30
[=======================================] 100% Unzipping... android-11/lib64/lib
[=======================================] 100% Unzipping... android-12/framework
[=======================================] 100% Unzipping... android-12/lib64/lib

配置Android环境变量,通过vim编辑/etc/profile,添加环境变量。

root@ubuntu:/buildkit# vim /etc/profile
# Android环境变量
export ANDROID_HOME=/buildkit/android-sdk/
export PATH=$PATH:$ANDROID_HOME/platform-tools

更新环境变量

root@ubuntu:/buildkit# source /etc/profile

1.3 测试编译项目

1.3.1 clone测试代码

切换为普通用户,并到当前用户家目录,下载测试项目,这里随意clone了一个我的Ksoup项目。

root@ubuntu:/buildkit# su zwenkai # 切换为普通用户
zwenkai@ubuntu:/buildkit$ cd ~
zwenkai@ubuntu:~$ mkdir code
zwenkai@ubuntu:~$ cd code/
zwenkai@ubuntu:~/code$ git clone -b v1.0.1 --depth=1 https://github.com/xuehuayous/Ksoup

1.3.2 编译项目

使用gradle编译项目,第一次编译可能有的慢,需要下载依赖,后续执行就会很快了。

zwenkai@ubuntu:~/code$ cd Ksoup/
zwenkai@ubuntu:~/code/Ksoup$ ./gradlew clean assembleDebug

BUILD SUCCESSFUL in 17s

1.3.3 下载APK并安装到手机

拷贝输出apk到临时文件

root@ubuntu:/buildkit/code/Ksoup# cp /buildkit/code/Ksoup/app/build/outputs/apk/debug/app-debug.apk /buildkit/tmp/

使用scp拷贝文件到本机,然后使用adb安装App到手机。

zhouwenkai@zhouwenkaideMacBook-Pro ~ % scp zwenkai@192.168.31.6:/home/zwenkai/code/Ksoup/app/build/outputs/apk/debug/app-debug.apk .
zwenkai@192.168.31.6's password:
app-debug.apk                                                                    100% 5632KB  17.1MB/s   00:00
zhouwenkai@zhouwenkaideMacBook-Pro ~ % adb install app-debug.apk
* daemon not running; starting now at tcp:5037
* daemon started successfully
Performing Streamed Install
Success

1.4 环境搭建说明

其实编译环境的搭建都不会特别复杂,只不过我们初学一门语言或一个平台时,由于对于改方向技术储备几乎为0,经常导致我们在环境配置上走一些弯路。其实回过头来看,环境配置一般都是比较简单的。

至此,Android编译环境就配置完成了,有同学可能会问为甚么没有配置Gradle环境,主要是项目编译的时候会去下载,就没必要我们手动配置了。如果项目还有flutter环境,后面彩蛋我会说下。

二、跑通远程编译

复杂的流程一般可以拆分为简单步骤的组合,在远程编译也是一样,可以拆分为以下三个步骤:

  1. 上传代码到服务端;
  2. 启动远程编译项目;
  3. 下载APK并安装到手机;

2.1 上传代码到服务端

2.1.1 压缩本地代码

直接zip压缩整个代码库,竟然有613M,这么大肯定是不行的。在压缩的时候把忽略文件和.git排除,再来试一下。

tar --exclude-from=answer-android/.gitignore --exclude=.git --exclude=.gitignore -cvzf answer-android.tar.gz answer-android

这次代码就只有16M了,赞。

drwxr-xr-x   38 zhouwenkai  staff   1.2K  7  2 14:19 answer-android
-rw-r--r--    1 zhouwenkai  staff   613M  7  2 19:10 answer-android.zip
-rw-r--r--    1 zhouwenkai  staff    16M  7  2 19:15 answer-android.tar.gz

2.1.2 上传代码

scp answer-android.tar.gz zwenkai@192.168.31.6:/home/zwenkai/code/

2.2 远程编译项目

zhouwenkai@zhouwenkaideMacBook-Pro code % ssh zwenkai@192.168.31.6 "echo 'export BASH_ENV=/etc/profile && cd code && tar -zxf answer-android.tar.gz && cd answer-android && ./gradlew clean assembleDebug' | bash"

# ... ...

BUILD SUCCESSFUL in 6s
365 actionable tasks: 45 executed, 283 from cache, 37 up-to-date

远程编译项目也非常简单,启动非登录、非交互的ssh连接,这里有个注意点,需要指定加载的环境变量BASH_ENV=/etc/profile

解压上一步上传的压缩代码,然后执行编译命令,6秒完成。这步在我19款16寸MBP(32G内存)上最快是40多秒,经常是1分钟以上。

Android远程编译

虽然远程机5700G为8核16线程、主频3.8G,笔记本i7-9750H为6核12线程、主频2.6G,CPU有所增强,也不应该是这个数量级的差别,我感觉是笔记本同事运行程序非常多(进程715、线程4453),在时间片轮转上花费了较多的时间。当然,这些都是我的猜测,后续可以再研究下,目前没有量化的指标。

2.3 下载运行

依旧是使用scp命令从编译机下载APK到本地。

zhouwenkai@zhouwenkaideMacBook-Pro baidu % scp zwenkai@192.168.31.6:/home/zwenkai/code/answer-android/answer_main/build/outputs/apk/debug/answer_main-debug.apk .
answer_main-debug.apk                                                                                                                                                                                                       100%   74MB  23.9MB/s   00:03

接下来就是安装APK到手机啦~

zhouwenkai@zhouwenkaideMacBook-Pro code % adb install answer_main-debug.apk
Performing Streamed Install
Success

OK,通过上面的简简单单的三步,就完成了远程编译。但想的多的朋友肯定会想,我如果只改了一行代码,都把全量的代码上传,是不是有点浪费?

三、优雅地远程编译

3.1 mainframer远程编译项目

3.1.1 初识mainframer

通过上面的「跑通远程编译」,上传文件 + 编译项目 + 下载产物,已经将原本的本地编译时间大大降低。全量压缩上传,而且是case by case的进行产物下载,感觉不是那么优雅。有没有更好的方案呢?

之前和同事还讨论过远程编译,当时他给我推荐了 mainframer ,后来也没再关注。

Android远程编译

在查资料,Google搜索 Android remote build 的时候,很多文章又把我带到了这个 mainframer 库,那就了解下它的原理吧。

3.1.2 mainframer原理

在学习或使用过程中,原理的了解是非常重要的。这样才能在使用过程中有问题时自己能快速解决,尤其是多年不活跃的代码库。

在了解原理的时候,可以使用看下代码的提交记录,一般第一个release版本,是比较好理解原理的,尽管这个版本不是那么的完善,甚至有bug。

通过介绍可以知道,这个库2.x版本比较稳定,3.x使用 Rust 语言进行了重构,而且可能不稳定。不用说,按照我们的惯例,在了解原理阶段肯定是不会看它最新版本。

老版本使用 Shell 编写的,那我们就来看下它的2.1版本吧。

syncBeforeRemoteCommand  
executeRemoteCommand  
syncAfterRemoteCommand

有三个执行的方法,通过名字就可以看到,和我们之前的思路不谋而合。

  • syncBeforeRemoteCommand 编译之前同步本地文件到远端;
  • executeRemoteCommand 执行远端编译;
  • syncAfterRemoteCommand 编译之后同步构建产物到本地;
  1. 同步本地文件到远端

使用 rsync 命令,将本地和远端差异文件进行同步,而且可以配置忽略同步文件。

function syncBeforeRemoteCommand {
    echo "Sync local → remote machine..."
    startTime="$(date +%s)"

    COMMAND="rsync --archive --delete --rsync-path=\"mkdir -p \"$PROJECT_DIR_ON_REMOTE_MACHINE\" && rsync\" --compress-level=$LOCAL_COMPRESS_LEVEL "

    if [ -f "$COMMON_IGNORE_FILE" ]; then
        COMMAND+="--exclude-from='$COMMON_IGNORE_FILE' "
    fi

    if [ -f "$LOCAL_IGNORE_FILE" ]; then
        COMMAND+="--exclude-from='$LOCAL_IGNORE_FILE' "
    fi

    COMMAND+="--rsh ssh ./ $REMOTE_MACHINE:'$PROJECT_DIR_ON_REMOTE_MACHINE'"

    eval "$COMMAND"

    endTime="$(date +%s)"
    echo "Sync done: took $(formatTime $((endTime-startTime)))."
    echo ""
}
  1. 执行远端编译

使用 ssh 执行远端编译命令,和我们上面的做法是一致的。

function executeRemoteCommand {
    echo "Executing command on remote machine…"
    echo ""
    startTime="$(date +%s)"

    set +e
    if ssh "$REMOTE_MACHINE" "echo 'set -e && cd '$PROJECT_DIR_ON_REMOTE_MACHINE' && echo \"$REMOTE_COMMAND\" && echo "" && $REMOTE_COMMAND' | bash" ; then
        REMOTE_COMMAND_SUCCESSFUL="true"
    fi
    set -e

    endTime="$(date +%s)"
    echo ""

    duration="$((endTime-startTime))"

    if [ "$REMOTE_COMMAND_SUCCESSFUL" == "true" ]; then
        echo "Execution done: took $(formatTime $duration)."
    else
        echo "Execution failed: took $(formatTime $duration)."
    fi

    echo ""
}
  1. 同步构建产物到本地

依然使用 rsync 命令,将远端和本地差异文件进行同步。

function syncAfterRemoteCommand {
    echo "Sync remote → local machine…"
    startTime="$(date +%s)"

    COMMAND="rsync --archive --delete --compress-level=$REMOTE_COMPRESS_LEVEL "

    if [ -f "$COMMON_IGNORE_FILE" ]; then
        COMMAND+="--exclude-from='$COMMON_IGNORE_FILE' "
    fi

    if [ -f "$REMOTE_IGNORE_FILE" ]; then
        COMMAND+="--exclude-from='$REMOTE_IGNORE_FILE' "
    fi

    COMMAND+="--rsh ssh $REMOTE_MACHINE:'$PROJECT_DIR_ON_REMOTE_MACHINE'/ ./"
    eval "$COMMAND"

    endTime="$(date +%s)"
    echo "Sync done: took $(formatTime $((endTime-startTime)))."
}

3.1.3 mainframer使用

其实借鉴 mainframer 的思路,已经能够帮助我们改造。但反过来一想,岂不是就直接使用 mainframer 更好,不合适的地方优化下就好啦。

  • 添加远程机用户名配置
  • 添加远程登录环境变量配置

mainframer 脚本拷贝到项目下,建立.mainframer文件夹,添加如下几个配置文件。

.
├── .mainframer
   ├── config        # 编译配置
   ├── ignore        # 双向同步忽略配置(非必需)
   ├── localignore   # 本地同步到远程胡咧配置(非必需)
   └── remoteignore  # 远程同步到本地忽略配置(非必需)
└── mainframer        # 远程编译脚本

config 配置文件

remote_user=zwenkai          # 远程机登录用户名
remote_machine=192.168.31.6  # 远程机地址
local_compression_level=1    # 本地同步远程压缩等级(非必需)
remote_compression_level=1   # 远程同步本地压缩等级(非必需)

ignore 配置文件(双向同步忽略配置)

.gradle
.git  
.idea  
local.properties

localignore 配置文件(本地同步到远程忽略配置)

build

remoteignore 配置文件(远程同步到本地忽略配置)

*/build/generated  
*/build/intermediates  
*/build/tmp  
*/.gradle

注:这些忽略配置可以根据自己的真实情况进行修改。

3.1.4 运行远程编译

执行命令 ./mainframer ./gradlew clean assDebug 进行远程编译。省略编译过程命令输出如下。

zhouwenkai@zhouwenkaideMacBook-Pro answer-android % ./mainframer ./gradlew clean assDebug
:: mainframer v2.1.0

Sync local  remote machine...
Sync done: took 1 second.

Executing command on remote machine…

./gradlew clean assDebug
Configuration on demand is an incubating feature.
> Task :buildSrc:compileKotlin UP-TO-DATE

# ...

BUILD SUCCESSFUL in 7s
365 actionable tasks: 45 executed, 283 from cache, 37 up-to-date

Execution done: took 8 seconds.

Sync remote  local machine…
Sync done: took 1 second.

Success: took 9 seconds.

四、项目中落地

4.1 优化mainframer

  1. 配置文件基于yaml进行优化,在一个配置文件完成配置项;
  2. 由于项目中存在核心库可以源码调试,那就要求调试的其他不在本项目中的代码库也可以同步到远程编译机;
  3. 添加远程编译统计,便于分析远程编译情况。

源码链接:RemoteBuild

4.2 添加到项目

4.2.1 添加配置到项目

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/xuehuayous/RemoteBuild/main/install)"

4.2.2 配置Android Studio

  1. Run -> Edit Configuration -> +
  2. 选择 Android App,有意义的名字,如:*_remote_build
  3. 删除 Before launch 中默认的 Gradle-aware Make
  4. Before launch 中添加 Run External Tool,取名 remote assembleDebug
    • Program 输入 bash
    • Arguments 输入 ./remotebuild ./gradlew assembleDebug
    • Working director 选择 $ProjectFileDir$
  5. ENJOY IT!

源码链接:RemoteBuild

4.3 添加用户(root账号/远程编译机管理员)

远程编译机这么好的配置,如果只是一个人使用,完全发挥不出他的价值;甚至可以支持小型规模的团队(10人左右Android开发同时使用),毕竟并不是所有人都同时使用。

4.3.1 添加用户,并指定使用的shell

添加用户,并指定使用的shell。

useradd -m `$username` -s /bin/bash

4.3.2 设置用户密码

设置密码,建议使用较长的随机密码,这样可以保证这个同学数据的相对安全。

passwd `$username`

生成32位随机密码方法

tr -cd 'a-zA-Z0-9' </dev/urandom | head -c32

4.4 加入远程编译(其他成员)

4.4.1 配置SSH免密码登录

上传ssh公钥,密码找管理员分配

ssh-copy-id 192.168.2.182 # (远程编译机地址,host/ip)

4.4.2 验证配置,项目中执行

./remotebuild ./gradlew clean assembleDebug

4.4.1 配置 Android Studio

参考4.2.2

4.5 常见问题

4.5.1 Java环境变量找不到

ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation.

处理: 把gradlew文件的第一行改为 #!/usr/bin/env bash,由于远程编译机指定的shell环境为bash,有可能gradlew指定的为 sh。

4.5.2 编译机公钥未保存到本地known_hosts

Host key verification failed.
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at /AppleInternal/Library/BuildRoots/b6051351-c030-11ec-96e9-3e7866fcf3a1/Library/Caches/com.apple.xbs/Sources/rsync/rsync/io.c(453) [sender=2.6.9]

处理: 项目命令行执行./remotebuild ./gradlew assembleDebug一次远程编译,提示中输入yes

zhouwenkai@zhouwenkaideMacBook-Pro doctor-box-android % ./remotebuild ./gradlew assembleDebug
Sync local → remote machine...
The authenticity of host '172.22.149.80 (172.22.149.80)' can't be established.
ED25519 key fingerprint is SHA256:UwZ109j3qpjRRDec8osOVLAHvgYsNNlqft4K+tY+HcQ.
This host key is known by the following other names/addresses:
    ~/.ssh/known_hosts:26: 192.168.31.6
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

五、结语

至此,Android远程编译完成,感兴趣的朋友可以试下,有任何问题也欢迎一起讨论。

原创文章,作者:Kevin,如若转载,请注明出处:https://zwenkai.com/android-remote-build/

(1)
KevinKevin
上一篇 2022年4月22日
下一篇 2022年11月20日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

评论列表(9条)

  • hynson
    hynson 2023年12月26日 上午11:56

    遇到点问题,能加你微信求助一下吗

    • Kevin
      Kevin 2023年12月26日 下午8:37

      @hynson可以把遇到的问题发出来看看呢

    • hynson
      hynson 2023年12月27日 下午3:00

      @Kevinhttps://github.com/buildfoundation/mainframer/issues/290
      as mainfremer这个插件一直ssh连接失败

    • hynson
      hynson 2023年12月27日 下午3:09

      @Kevin看你B站视频也没更新了,我在想要不要自己去开发一个插件

    • Kevin
      Kevin 2023年12月27日 下午4:12

      @hynson我的编写的脚本,https://github.com/WenkaiZhou/RemoteBuild,可以试下,还是比较稳的,我们团队稳定使用了一年多了。B站确实鸽了,我可以把博客更新下,说明更详细点。

    • hynson
      hynson 2023年12月27日 下午4:40

      @Kevin好的 我试试赞

    • hynson
      hynson 2023年12月27日 下午6:27

      @Kevin我把脚本拉到了项目目录下面,按照教程配置了,发现报错哎。还有这个脚本只支持mac吗 有没有支持windows的,方便的话加微信指导一下花

    • Kevin
      Kevin 2023年12月27日 下午7:48

      @hynson是的,目前只有mac版的,不过chatGPT应该很快就能转换出windows版的,留下你的微信吧,我加你。

  • hynson
    hynson 2023年12月28日 上午6:33

    wx:hyson918