阅读 111

Linux下快速构建Android编译环境

背景: 在移动互联网时代,大多数的企业内部都有移动客户端,而移动客户端又因为OS的不同产生了两个派系,即安卓(Android)苹果(IOS),而对于互联网技术从业者来说,这两者最直接的区别就是开源闭源,因而也导致了在构建移动客户端时,为了整体的稳定性和可靠性的考虑(甚至有成本的考虑),需要进行分别编译,本篇文章记录下如何在Linux环境下构建Android编译环境.

介绍

通常,开发苹果系列的软件均需要使用一些专有开发工具,比如xcode,而此工具必须运行在Mac OS X设备上(当然你也可以尝试各种黑苹果的方式),所以不论是对于个人开发者还是企业构建服务器来说,都需要购买更多的Mac设备,通常,我知道的企业内部会使用Mac Mini来作为苹果系列的构建环境。

而作为安卓(Android)系列的软件,由于本身是谷歌开源的移动端操作系统,因此对于底层开发环境和构建环境没有太高的要求。一般而言,开发者会使用Android Studio来开发安卓系列的软件,而内置的命令行工具command-line则默认提供了安卓软件的编译工具和环境。值得一提的是,由于Android Studio是开源的,因此该工具也提供了多个平台的支持(Windows,Mac,Linux,Chrome OS)。而这也极大的降低了企业的整体成本,通常开发环境可以在任意的OS环境中进行开发,而企业内部也可以使用Linux环境进行安卓软件的持续集成和交付.

接下来主要讲解下如何在Linux环境下构建安卓的编译环境。

Linux下安卓(Android)编译环境的搭建

前提条件

需要注意的是,对于安卓(Android)应用来说,一些依赖包的管理主要依靠sdkmanager这个命令行工具,该工具可以在Android Studio页面找到,并且支持Windows,Mac,Linux三个不同平台的版本。

同时,安卓(Android)应用的开发工具Android Studio使用[Gradle](https://github.com/gradle/gradle)来进行编译和打包,因此对于安卓(Android)应用而言,也将使用gradle来进行编译和打包操作,该软件可以在Gradle页面找到。

其次,[NDK(原生开发套件)](https://developer.android.google.cn/ndk/guides/)是一套工具,可以使开发者能够在 Android 应用中使用 C 和 C++ 代码,并提供众多平台库,开发者可使用这些平台库管理原生 Activity 和访问物理设备组件,例如传感器和轻触输入。该开发套件可以在NDK页面找到.

最后,如上几个组件的底层语言均使用java进行开发,因此需要安装JDK相关环境。

综上所述,在Linux环境下编译安卓(Android)环境需要如下几个组件:

  • JDK: java语言的基础编译和运行环境
  • sdkmanager: 安卓(Android)应用下的依赖包管理器
  • NDK: 安卓原生开发套件,可调用底层CC++代码
  • Gradle: 安卓系列软件编译工具(类似maven之类的工具)

快速安装基本环境

# 下载基础软件包
$ mkdir -p /opt/servers/ && cd /opt/servers/
# JDK(可以选择openjdk)
$ wget http://dl.bgbiao.top/dav/jdk1.8.0_191.tar.gz
$ tar -zxf jdk1.8.0_191.tar.gz -C /opt/servers/


# 下载并配置sdkmanager
$ wget https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip
$ unzip sdk-tools-linux-4333796.zip 
$ mkdir -p /opt/sdk
$ ln -s /opt/servers/tools /opt/sdk/tools

# 配置环境变量
$ cat /etc/profile
export JAVA_HOME=/opt/servers/jdk1.8.0_191
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$CLASSPATH
export PATH=${JAVA_HOME}/bin:${PATH}
export ANDROID_HOME=/opt/sdk
export PATH=${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}:${PATH}

# 测试sdkmanager使用
$ source /etc/profile
$ sdkmanager --list
Warning: File /root/.android/repositories.cfg could not be loaded.
Installed packages:
  Path    | Version | Description              | Location
  ------- | ------- | -------                  | -------
  tools   | 26.0.1  | Android SDK Tools 26.0.1 | tools/


# 安装指定版本的包
$ sdkmanager --list | grep cmake
Warning: File /root/.android/repositories.cfg could not be loaded.
  cmake;3.10.2.4988404              | 3.10.2       | CMake 3.10.2.4988404
  cmake;3.6.4111459                 | 3.6.4111459  | CMake 3.6.4111459

$ sdkmanager 'cmake;3.6.4111459' 
....

# 下载并安装ndk
$ cd /opt/servers && wget https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip
$ unzip android-ndk-r16b-linux-x86_64.zip
$ ln -s /opt/servers/android-ndk-r16b /opt/ndk

# 配置ndk配置环境(增加如下配置)
$ cat /etc/profile
export NDK_HOME=/opt/ndk
export ANDROID_NDK_HOME=/opt/ndk
export PATH=$NDK_HOME:${ANDROID_NDK_HOME}:$PATH


# 下载并安装gradle
$ cd /opt/servers && wget https://services.gradle.org/distributions/gradle-4.10.1-all.zip
$ unzip gradle-4.10.1-all.zip
$ ln -s /opt/servers/gradle-4.10.1 /opt/gradle

# 配置gradle环境(增加如下配置)
$ cat /etc/profile
export GRADLE_HOME=/opt/gradle
export PATH=${GRADLE_HOME}/bin:${PATH}

# 测试gradle
$ gradle -v

------------------------------------------------------------
Gradle 4.10.1
------------------------------------------------------------

Build time:   2018-09-12 11:33:27 UTC
Revision:     76c9179ea9bddc32810f9125ad97c3315c544919

Kotlin DSL:   1.0-rc-6
Kotlin:       1.2.61
Groovy:       2.4.15
Ant:          Apache Ant(TM) version 1.9.11 compiled on March 23 2018
JVM:          1.8.0_191 (Oracle Corporation 25.191-b12)
OS:           Linux 3.10.0-862.el7.x86_64 amd64

复制代码

安装Android基础依赖

注意: 正式编译之前先生成license,并将licenses目录移动到/opt/sdk/下,和sdkmanager的tools目录平级

# 安装android基础依赖包
$ sdkmanager 'build-tools;28.0.3' 'platforms;android-28' 'cmake;3.6.4111459'

# 生成licences
$ sdkmanager --licenses
$ cp -rp licenses /opt/sdk/
复制代码

编译Android包

# 加载下整体环境变量
$ cat /etc/profile
....
....
export JAVA_HOME=/opt/servers/jdk1.8.0_191
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$CLASSPATH
export PATH=${JAVA_HOME}/bin:${PATH}
export ANDROID_HOME=/opt/sdk
export PATH=${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}:${PATH}
export GRADLE_HOME=/opt/gradle
export PATH=${GRADLE_HOME}/bin:${PATH}
export NDK_HOME=/opt/ndk
export ANDROID_NDK_HOME=/opt/ndk
export PATH=$NDK_HOME:${ANDROID_NDK_HOME}:$PATH

$ source /etc/profile

# 下载安卓(android)应用的源码文件
$ git clone http://git.bgbiao.top/test-app.git

$ cd test-app
$ export ENV="fNormal"
$ gradle clean assemble${ENV}Release
Starting a Gradle Daemon, 2 busy Daemons could not be reused, use --status for details
Parallel execution with configuration on demand is an incubating feature.
<-------------> 0% CONFIGURING [29s]
> root project > Resolve dependencies of :classpath > guava-18.0.pom > 3 KB/5 KB downloaded
> IDLE
> root project > Resolve dependencies of :classpath > commons-lang-2.6.pom > 9 KB/17 KB downloaded
> root project > Resolve dependencies of :classpath > osdetector-gradle-plugin-1.4.0.pom
....
....

BUILD SUCCESSFUL in 7m 7s
501 actionable tasks: 164 executed, 288 from cache, 49 up-to-date


# 查看生成的apk包
$ ls app/build/outputs/apk/fNormal/release/
app-fNormal-release.apk  output.json


# 安装二维码生成器
$ yum install qrencode-3.4.1-3.el7.x86_64 -y

# 将生成的apk包上传到指定的http服务中
$ curl -T app/build/outputs/apk/fNormal/release/app-fNormal-release.apk http://dl.bgbiao.top/dav/

# 给apk下载文件生成一个二维码
$ qrencode -o test-android.png "http://dl.bgbiao.top/dav/app-fNormal-release.apk"

# 上传二维码
$ curl -T test-android.png http://dl.bgbiao.top/dav/
复制代码

接下来,开发者用户即可以使用http://dl.bgbiao.top/dav/test-android.png二维码地址进行扫描安装,对该版本的app功能进行测试验证了。

需要注意的是,通常情况下,开发者如果使用Mac OSX来编写代码,可能会在代码里使用类似#include 'MD5.h'之类的代码,看起来好像没有什么问题,但是因为Mac OSXWindows系统中对大小写不敏感,所以那样写不会有什么太大影响,因为编译器可以找到系统中的md5.h,但是在Linux环境下,系统对大小写很敏感,如果代码里写死了MD5.h,而系统库中是md5.h,那肯定会编译失败,而且一般人看到该异常情况不会想到是大小写的问题。

好了,趟坑算是趟完了,接下来提供一个福利,我自己基于以上构建历史环境打包了一个docker镜像,用以封装Android编译的基本环境.

docker镜像

$ cat Dockerfile
FROM centos:7.5.1804
MAINTAINER "BGBiao <https://bgbiao.top/>"
ENV TZ "Asia/Shanghai"

RUN yum clean all && \
    yum install unzip wget curl -y && \
    mkdir -p /opt/{servers,app} && \
    cd /opt/servers/ && \
    wget  http://dl.bgbiao.top/hadoop/jdk1.8.0_191.tar.gz && \
    wget http://dl.bgbiao.top/dav/android-build/android-ndk-r16b-linux-x86_64.zip && \
    wget http://dl.bgbiao.top/dav/android-build/gradle-4.10.1-all.zip && \
    wget http://dl.bgbiao.top/dav/android-build/sdk-tools-linux-4333796.zip

RUN pushd /opt/servers && \
    tar -zxf jdk1.8.0_191.tar.gz && \
    unzip android-ndk-r16b-linux-x86_64.zip && \
    unzip gradle-4.10.1-all.zip && \
    unzip sdk-tools-linux-4333796.zip && \
    mkdir -p /opt/sdkmanager && \
    ln -s /opt/servers/tools /opt/sdkmanager/tools && \
    ln -s /opt/servers/gradle-4.10.1 /opt/gradle && \
    ln -s /opt/servers/android-ndk-r16b /opt/ndk

COPY profile /opt/servers/setenv.sh
$ cat profile
export JAVA_HOME=/opt/servers/jdk1.8.0_191
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$CLASSPATH
export PATH=${JAVA_HOME}/bin:${PATH}
export ANDROID_HOME=/opt/sdkmanager
export PATH=${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}:${PATH}
export GRADLE_HOME=/opt/gradle
export PATH=${GRADLE_HOME}/bin:${PATH}
export NDK_HOME=/opt/ndk
export ANDROID_NDK_HOME=/opt/ndk
export PATH=$NDK_HOME:${ANDROID_NDK_HOME}:$PATH

# 用户可以根据上述Dockerfile构建镜像,同时也可以直接使用我构建好的一个镜像
$ docker pull xxbandy123/android-build-env:19-12-12

# 使用方式
# 基于上述镜像,用户需要使用sdkmanager 安装依赖的安卓库,同时编排好自己的gradle打包命令,在自己的安卓项目中直接编译即可
$ docker run -itd --name android-build-env:19-12-12 bash 
[root@4c05d4ded28d /]# source /opt/servers/setenv.sh
[root@4c05d4ded28d /]# git clone your-android-app.git
[root@4c05d4ded28d /]# sdkmanager 'build-tools;28.0.3' 'platforms;android-28' 'cmake;3.6.4111459'
[root@4c05d4ded28d /]# sdkmanager --licenses
[root@4c05d4ded28d /]# cp -rp licenses ${ANDROID_HOME}/
[root@4c05d4ded28d /]# ls ${ANDROID_HOME}
build-tools  cmake  licenses  platforms  platform-tools  tools
# 开始执行编译(之后就是漫长的等待了)
[root@4c05d4ded28d /]# cd your-android-app && gradle clean assembleRelease
复制代码

注意事项

  • 1.通常持续集成会使用Jenkins来进行编译打包,因此以上环境再接入Jenkins-salve之前需要安装git客户端名
  • 2.通常客户端在测试包时会通过二维码扫描来下载包,因此环境上需要安装qrencode软件,用于生成二维码
  • 3.需要注意gradle在编译过程中会启动一个守护进程,如果编译异常结束,该守护进程可能不会立即释放,此时立即再次编译将有可能导致OOM
    欢迎关注我的公众号: BGBiao,一起进步~
关注下面的标签,发现更多相似文章
评论