本文详细记录Mac下使用PD虚拟机安装ubuntu18.4桌面版,编译Android Native WebRTC的过程。
注意如果仅仅是使用WebRTC没必要手动编译源码,直接用官方提供的预编译包即可:
The easiest way to get started is using the official prebuilt libraries available at JCenter. These libraries are compiled from the tip-of-tree and are meant for development purposes only.
On Android Studio 3 add to your dependencies:
implementation 'org.webrtc:google-webrtc:1.0.+'
On Android Studio 2 add to your dependencies:
compile 'org.webrtc:google-webrtc:1.0.+'
The version of the library is 1.0… The hash of the commit can be found in the .pom-file. The third party licenses can be found in the THIRD_PARTY_LICENSES.md file next to the .aar-file.
只有需要研究和修改源代码时才有必要下载代码并自己编译。
按照官网的教程WebRTC源码编译看似简单,但坑很多,尤其是为了能连上谷歌配置代理就要折腾很久,而且虚拟机本身也不省心。
为此新创建了一个虚拟机从头开始配置,因为之前折腾的东西可能没有全部记住,当时也没有记录,从头开始保证一个命令都不差地记录下来。当然,这里使用的每一个环节的软件和系统发生变化都会导致不一致的配置过程,仅供参考。
安装配置Ubuntu虚拟机
详细安装步骤:
1.安装选择镜像方式,不要选择下面的下载Ubuntu,很慢
2.进入这个页面后点击“手动选择”
3.选择下载好的iso文件
4.选择后识别出Ubuntu,继续
5.设置用户名密码
6.设置在mac系统内虚拟机文件的文件名和位置
7.创建中,这里等了大概一个小时
安装Parallels Tools
1.从菜单中选择安装Parallels Tools
2.会自动 mount 一个 CDROM
很不幸,直接双击 install-gui 无法安装,命令行运行 install 也无法安装。网上查了很久,最终发现了一篇文章,可以完美解决这个问题:
https://gist.github.com/rudolfratusinski/a4d9e3caff11a4d9d81d2e84abc9afbf
这里是按照上面步骤修改好的安装文件:百度网盘 (adsh),没试过直接用行不行。
3.安装完成后直接重启
重启后分辨率自动调到最大,可以与mac共享剪贴板了。此时虚拟机文件仅仅7G左右。我又创建了个快照变成8G了。。。
下载WebRTC代码
修改 Ubuntu 源
推荐使用清华大学开源软件镜像站
https://mirror.tuna.tsinghua.edu.cn/help/ubuntu/
- 备份原生source.list sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
- 修改替换为清华镜像版本,推荐使用gedit:sudo gedit /etc/apt/sources.list
- 执行 sudo apt update
配置代理
这里使用环境变量配置 http proxy 的方法。后面还有个坑,需要结合代码下载步骤说明。
使用主机sockes提供的http代理。虚拟机网络模式使用默认的共享网络。在PD的偏好设置里可以找到网络设置,可以查看共享网络地址段:10.211.55.1~254,主机是第一个节点因此IP是10.211.55.2。
查看地址段
设置mac上的SS的http代理监听地址为0.0.0.0才能允许任意IP使用:
设置ss的http代理地址
最后设置ubuntu的环境变量。
# 可以写入 .bashrc 文件中
export ALL_PROXY=http://10.211.55.2:1087
export HTTP_PROXY=http://10.211.55.2:1087
export HTTPS_PROXY=http://10.211.55.2:1087
下载代码之前安装了一些常用软件
sudo apt install curl vim net-tools
下载代码
命令清单
官方文档:https://webrtc.org/native-code/android/
总结一下,执行以下步骤和命令:
# 1.安装必要的软件
sudo apt install git python
# 2.切换到 home
cd /home/webrtc
# 3.安装和设置代码下载工具
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=$PATH:/home/webrtc/depot_tools # 可以写在 .bashrc 里
# 4.创建工作目录并进入
mkdir webrtc_android
cd webrtc_android # 注意接下来执行命令始终在这个目录下
# 5.下载第一步:fetch
fetch --nohooks webrtc_android
# 6.设置 gclient 代理,原因是 gclient 无法使用 $HTTP_PROXY 设置代理,
# 而要使用 .boto 文件来设置。这就是上文提到的坑:)
export NO_AUTH_BOTO_CONFIG=/home/webrtc/.boto # 可以写在 .bashrc 里
echo -e "[Boto]\nproxy = 10.211.55.2\nproxy_port = 1087" > /home/webrtc/.boto
# 7.下载第二步:gclient,官网是一个步骤 "gclient sync",这里可以拆成两个
gclient sync --nohooks # 同步代码用时较短
gclient runhooks # 运行一些 hooks,会下载一些文件,其实这个步骤才需要 .boto 设置代理
下载第一步:fetch
fetch的步骤会下载16G的代码和开发环境,会持续很长时间取决于网速。好在每十秒钟会有一次打印,提醒你仍在下载不是卡死了。
每十秒一次打印
fetch过程中git clone失败会自动重试。但如果整个脚本退出了,那就跪了。直接在原来的位置再次执行fetch是不行的,可以试试下一个命令gclient sync,保险起见可以重来。。。网速不行的总掉线的,可以洗洗睡了。
总之需要稳定的网络环境,还不能太慢,写这篇文章时的下载跪了一次,第二天重来,连的网线,网速稍快且很稳定,大概800k/s左右,6个小时。
fetch完成的画面
设置 gclient 代理
gclient sync 的步骤需要另一种代理设置:
参考这篇文章 WebRTC在iOS端的实现/WebRTC在iOS端的实现
主要是设置一个.boto文件,总结为上面清单里的两条命令:
export NO_AUTH_BOTO_CONFIG=/home/webrtc/.boto
echo -e "[Boto]\nproxy = 10.211.55.2\nproxy_port = 1087" > /home/webrtc/.boto
# 这里就是创建一个 .boto 文件按照固定的语法写上代理配置,文件内容如下:
[Boto]
proxy = 10.211.55.2
proxy_port = 1087
经过实际应用,并不需要unset掉环境变量,反而运行gclient runhooks时仍然需要环境变量,只要设置好NO_AUTH_BOTO_CONFIG就可以了。
下载第二步:gclient
这个步骤相比第一步很快就会完成,主要耗时在一些文件下载上。之后更新代码执行 gclient sync 即可。
编译打包
安装必要的软件和包
参考官网:Prerequisite Software >> Install additional build dependencies
# 进入到src目录中
cd src # 执行完后,当前目录应为 /home/webrtc/webrtc_android/src
# 下载 java相关命令和包,以及其他一些必要的软件和包
build/install-build-deps-android.sh # 执行过程中要输入 sudo 密码
工具
WebRTC项目使用了大量的第三方开源项目,代码庞大复杂,整个构建系统采用了gn gn官方文档 和ninja ninja官方文档。
GN
gn命令处理的是名称为 BUILD.gn 的文件,BUILD.gn 文件中可以定义若干参数,这些参数使 gn 命令执行时可以通过不同的参数值创建不同的编译配置。例如WebRTC的目标系统是在android上还是ios上。
gn使用文件目录层次来组织不同的编译目标,这是非常自然合理的。查看 WebRTC 的目录结构可以发现每个文件夹下面都对应着一个 BUILD.gn 的文件,含有 BUILD.gn 文件表示这个目录下是有编译目标的,这些编译目标可以依赖子目录的编译目标从而组成一套复杂而有序的构建图。
NINJA
gn的输出就是扩展名为 .ninja 的文件,这些文件保存在编译目录中,可以被 ninja 命令直接使用,ninja文件中的指令都是简单和明确的,不需要任何额外的逻辑判断和计算,这使得ninja具有小而快的特点,也是ninja本身的设计初衷。
编译所有目标
官网上的编译打包命令:
cd webrtc_android/src
gn gen out/Debug --args='target_os="android" target_cpu="arm"'
ninja -C out/Debug
总共会有八千多个构建目标,大约会执行一个小时以上。
编译 example app
cd webrtc_android/src
gn gen out/Debug --args='target_os="android" target_cpu="arm"'
ninja -C out/Debug AppRTCMobile
最后生成的apk位于out/Debug/apks/AppRTCMobile.apk
参考官方文档:https://webrtc.googlesource.com/src/+/master/examples/androidapp/README
打包 aar 文件
WebRTC提供了一个脚本工具可以直接构建一个安卓 aar 的文件,我们直接用这个就可以了。
cd webrtc_android/src
tools_webrtc/android/build_aar.py --build-dir out --arch "armeabi-v7a" "arm64-v8a"
–build-dir out指定输出目录,如果不指定会在系统临时目录下创建
–arch “armeabi-v7a” “arm64-v8a” 指定两种cpu架构,相当于gn命令中的target_cpu="arm"和target_cpu=“arm64”。对每一种cpu架构会创建一个编译目录,依次执行gn和ninja命令。
最后将生成的jar和so打包成了aar文件,aar文件位于webrtc_android/src/libwebrtc.aar
编好了 aar 文件后,可以拷贝到 mac 下使用了,在 Android Studio 中可以替换预编译的 dependency
implementation 'org.webrtc:google-webrtc:1.0.+'
如何替换可以参考安卓官方文档:https://developer.android.com/studio/projects/android-library#AddDependency
Android Studio
不推荐使用官网提供的方法
按照这个方法是无法编译成功的,缺少一些步骤,需要手动调整,而且使用generate_gradle.py生成的 gradle 项目比较诡异。
推荐方法
直接将 src/examples/androidapp/ 目录下的代码导入到 Android Studio 中,导入后生成的gradle文件也不太完整,可以参考 src/examples/aarproject 中的 gradle 文件来补全。
注意 src/examples/androidapp/third_part/autobanh/lib/autobanh.jar 文件需要拷贝到 libs 目录下。
以下是 build.gradle 文件内容,供参考
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "org.appspot.apprtc"
minSdkVersion 16
targetSdkVersion 21
versionCode 1
versionName "1.0"
testApplicationId "org.appspot.apprtc.test"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.google.code.findbugs:jsr305:3.0.2'
implementation 'org.webrtc:google-webrtc:1.0.+'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}