summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-07-18 14:46:17 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-07-18 14:46:17 -0300
commit227fc1d94d84ec3665965f5e94abcae1537f7462 (patch)
tree16b938a024f1aba6523baa1dd8df2088c32205f0
parenteab8d714e048bd93b34c768044e2b7282151d703 (diff)
parentd1632fd044054542cbb4b65928f9a14f3a51dcd2 (diff)
downloadmullvadvpn-227fc1d94d84ec3665965f5e94abcae1537f7462.tar.xz
mullvadvpn-227fc1d94d84ec3665965f5e94abcae1537f7462.zip
Merge branch 'multiple-android-architectures'
-rw-r--r--.gitignore2
-rw-r--r--README.md70
-rw-r--r--android/build.gradle44
-rw-r--r--android/proguard-rules.pro4
-rwxr-xr-xbuild-apk.sh76
5 files changed, 163 insertions, 33 deletions
diff --git a/.gitignore b/.gitignore
index f96460a318..85e2308d15 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,5 +17,7 @@
/dist-assets/openvpn
/dist-assets/openvpn.exe
/windows/**/bin/
+/android/keystore.properties
+/android/local.properties
**/.vs/
*.bak
diff --git a/README.md b/README.md
index 3b792ce77e..42f9134ed7 100644
--- a/README.md
+++ b/README.md
@@ -96,12 +96,30 @@ unzip android-ndk-r20-linux-x86_64.zip
--platform=android-21 \
--arch=arm64 \
--install-dir=$PWD/toolchains/android21-aarch64
+./android-ndk-r20/build/tools/make-standalone-toolchain.sh \
+ --platform=android-21 \
+ --arch=arm \
+ --install-dir=$PWD/toolchains/android21-armv7
+./android-ndk-r20/build/tools/make-standalone-toolchain.sh \
+ --platform=android-21 \
+ --arch=x86_64 \
+ --install-dir=$PWD/toolchains/android21-x86_64
+./android-ndk-r20/build/tools/make-standalone-toolchain.sh \
+ --platform=android-21 \
+ --arch=x86 \
+ --install-dir=$PWD/toolchains/android21-i686
```
Set up the required environment variables:
```
export AR_aarch64_linux_android="$PWD/toolchains/android21-aarch64/bin/aarch64-linux-android-ar"
+export AR_armv7_linux_androideabi="$PWD/toolchains/android21-armv7/bin/arm-linux-androideabi-ar"
+export AR_x86_64_linux_android="$PWD/toolchains/android21-x86_64/bin/x86_64-linux-android-ar"
+export AR_i686_linux_android="$PWD/toolchains/android21-i686/bin/i686-linux-android-ar"
export CC_aarch64_linux_android="$PWD/toolchains/android21-aarch64/bin/aarch64-linux-android21-clang"
+export CC_armv7_linux_androideabi="$PWD/toolchains/android21-armv7/bin/armv7a-linux-androideabi21-clang"
+export CC_x86_64_linux_android="$PWD/toolchains/android21-x86_64/bin/x86_64-linux-android21-clang"
+export CC_i686_linux_android="$PWD/toolchains/android21-i686/bin/i686-linux-android21-clang"
export ANDROID_HOME="$PWD"
```
@@ -111,7 +129,7 @@ These steps has to be done **after** you have installed Rust in the section belo
##### Install the Rust Android target
```bash
-rustup target add aarch64-linux-android
+rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
```
##### Set up cargo to use the correct linker and archiver
@@ -123,7 +141,40 @@ Add to `~/.cargo/config`:
```
[target.aarch64-linux-android]
ar = "/opt/android/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar"
-linker = "/opt/android/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android28-clang"
+linker = "/opt/android/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang"
+
+[target.armv7-linux-androideabi]
+ar = "/opt/android/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar"
+linker = "/opt/android/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang"
+
+[target.x86_64-linux-android]
+ar = "/opt/android/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android-ar"
+linker = "/opt/android/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang"
+
+[target.i686-linux-android]
+ar = "/opt/android/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android-ar"
+linker = "/opt/android/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android21-clang"
+```
+
+#### Signing the release APK
+
+In order to build release APKs, they need to be signed. First, a signing key must be generated and
+stored in a keystore file. In the example below, the keystore file will be
+`/home/user/app-keys.jks` and will contain a key called `release`.
+
+```
+keytool -genkey -v -keystore /home/user/app-keys.jks -alias release -keyalg RSA -keysize 4096 -validity 10000
+```
+
+Fill in the requested information to generate the key and the keystore file. Suppose the file was
+protected by a password `keystore-password` and the key with a password `key-password`. This
+information should then be added to the `android/keystore.properties` file:
+
+```
+keyAlias = release
+keyPassword = key-password
+storeFile = /home/user/app-keys.jks
+storePassword = keystore-password
```
### All platforms
@@ -250,22 +301,17 @@ to do that before starting the GUI.
## Building the Android app
-Build the Rust daemon with:
-```bash
-. env.sh "aarch64-linux-android"
-cargo build --target aarch64-linux-android --release
-```
-
-Packaging the APK:
+Running the `build-apk.sh` script will build the necessary Rust daemon for all supported ABIs and
+build the final APK. You may pass a `--dev-build` to build the Rust daemon and the UI in debug mode
+and sign the APK with automatically generated debug keys.
```bash
-cd android/
-./gradlew assembleRelease
+./build-apk.sh
```
If the above fails with an error related to compression, try allowing more memory to the JVM:
```bash
echo "org.gradle.jvmargs=-Xmx4608M" >> ~/.gradle/gradle.properties
-./gradlew --stop
+./android/gradlew --stop
```
diff --git a/android/build.gradle b/android/build.gradle
index e6b15979fb..4ee2ce7bd3 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -8,6 +8,13 @@ def repoRootPath = projectDir.absoluteFile.parentFile.absolutePath
def extraAssetsDirectory = "$project.buildDir/extraAssets"
def extraJniDirectory = "$project.buildDir/extraJni"
+def keystorePropertiesFile = file('keystore.properties')
+def keystoreProperties = new Properties()
+
+if (keystorePropertiesFile.exists()) {
+ keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
+}
+
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
@@ -20,10 +27,22 @@ android {
versionName "2019.1"
}
- buildTypes {
- release {
- minifyEnabled true
- proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
+ if (keystorePropertiesFile.exists()) {
+ signingConfigs {
+ release {
+ keyAlias keystoreProperties['keyAlias']
+ keyPassword keystoreProperties['keyPassword']
+ storeFile file(keystoreProperties['storeFile'])
+ storePassword keystoreProperties['storePassword']
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
+ signingConfig signingConfigs.release
+ }
}
}
@@ -43,11 +62,6 @@ android {
variant.mergeAssetsProvider.configure {
dependsOn copyApiRootCertificate
}
-
- variant.ndkCompileProvider.configure {
- dependsOn copyMullvadJni
- dependsOn copyWireguardGo
- }
}
}
@@ -95,18 +109,6 @@ task format(type: FormatTask, group: 'formatting') {
lint.dependsOn lintKotlin
-task copyMullvadJni(type: Copy) {
- from "$repoRootPath/target/aarch64-linux-android/debug"
- include 'libmullvad_jni.so'
- into "$extraJniDirectory/arm64-v8a"
-}
-
-task copyWireguardGo(type: Copy) {
- from "$repoRootPath/dist-assets/binaries/aarch64-linux-android"
- include 'libwg.so'
- into "$extraJniDirectory/arm64-v8a"
-}
-
task copyApiRootCertificate(type: Copy) {
from "$repoRootPath/dist-assets"
include "api_root_ca.pem"
diff --git a/android/proguard-rules.pro b/android/proguard-rules.pro
index f6a2ef15e0..a50d295303 100644
--- a/android/proguard-rules.pro
+++ b/android/proguard-rules.pro
@@ -1 +1,5 @@
-dontwarn org.joda.convert.**
+
+-keep class net.mullvad.mullvadvpn.model.** { *; }
+-keep class net.mullvad.mullvadvpn.MullvadDaemon { *; }
+-keep class net.mullvad.mullvadvpn.MullvadVpnService { *; }
diff --git a/build-apk.sh b/build-apk.sh
new file mode 100755
index 0000000000..e69c57c563
--- /dev/null
+++ b/build-apk.sh
@@ -0,0 +1,76 @@
+#!/usr/bin/env bash
+
+set -e
+
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd "$SCRIPT_DIR"
+
+PRODUCT_VERSION="$(node -p "require('$SCRIPT_DIR/gui/package.json').version" | sed -Ee 's/\.0//g')"
+
+if [[ "${1:-""}" == "--dev-build" ]]; then
+ BUILD_TYPE="debug"
+ GRADLE_TASK="assembleDebug"
+ APK_SUFFIX="-debug"
+ CARGO_FLAGS=""
+else
+ BUILD_TYPE="release"
+ GRADLE_TASK="assembleRelease"
+ APK_SUFFIX=""
+ CARGO_FLAGS="--release"
+
+ if [ ! -f "$SCRIPT_DIR/android/keystore.properties" ]; then
+ echo "ERROR: No keystore.properties file found" >&2
+ echo " Please configure the signing keys as described in the README" >&2
+ exit 1
+ fi
+fi
+
+if [[ "$BUILD_TYPE" == "debug" || "$(git describe)" != "$PRODUCT_VERSION" ]]; then
+ GIT_COMMIT="$(git rev-parse --short HEAD)"
+ APK_VERSION="${PRODUCT_VERSION}-dev-${GIT_COMMIT}"
+else
+ APK_VERSION="$PRODUCT_VERSION"
+fi
+
+ARCHITECTURES="aarch64 armv7 x86_64 i686"
+
+cd "$SCRIPT_DIR/android"
+./gradlew --console plain clean
+mkdir -p "${SCRIPT_DIR}/android/build/extraJni"
+
+cd "$SCRIPT_DIR"
+
+for ARCHITECTURE in $ARCHITECTURES; do
+ case "$ARCHITECTURE" in
+ "x86_64")
+ TARGET="x86_64-linux-android"
+ ABI="x86_64"
+ ;;
+ "i686")
+ TARGET="i686-linux-android"
+ ABI="x86"
+ ;;
+ "aarch64")
+ TARGET="aarch64-linux-android"
+ ABI="arm64-v8a"
+ ;;
+ "armv7")
+ TARGET="armv7-linux-androideabi"
+ ABI="armeabi-v7a"
+ ;;
+ esac
+
+ . env.sh "$TARGET"
+ cargo build $CARGO_FLAGS --target "$TARGET" --package mullvad-jni
+
+ cp -a "$SCRIPT_DIR/dist-assets/binaries/$TARGET" "$SCRIPT_DIR/android/build/extraJni/$ABI"
+ cp "$SCRIPT_DIR/target/$TARGET/$BUILD_TYPE/libmullvad_jni.so" "$SCRIPT_DIR/android/build/extraJni/$ABI/"
+done
+
+cd "$SCRIPT_DIR/android"
+./gradlew --console plain "$GRADLE_TASK"
+
+GENERATED_APK="$SCRIPT_DIR/android/build/outputs/apk/$BUILD_TYPE/android-$BUILD_TYPE.apk"
+
+mkdir -p ../dist
+cp "$GENERATED_APK" "$SCRIPT_DIR/dist/MullvadVPN-${APK_VERSION}${APK_SUFFIX}.apk"