From f2cd05e07c800dd110d9796f82fdbcb7a81dbb08 Mon Sep 17 00:00:00 2001 From: Christian Hoffmann Date: Sun, 13 Mar 2022 22:53:28 +0100 Subject: [PATCH 1/5] Autobuild: Combine and simplify Android build scripts Related: #2503 - Move all autobuild/android/* scripts to a single .github/autobuild/android.sh script which is called for the different stages (setup/build/get-artifacts). - Create functions with proper names for larger steps - Inline Github artifact output definition as it's shorter that way - Make shellcheck-clean - Drop wget dependency and use curl for all downloads - Keep variables as local as possible; only export what's necessary - Move further hardcoded versions to variables - Move build output to build/ - Drop dependencies libxkbcommon-x11-0 (unused) and openjdk-8-jre-headless (covered via jdk) --- .github/autobuild/android.sh | 112 ++++++++++++++++++ .github/workflows/autobuild.yml | 8 +- autobuild/android/autobuild_apk_1_prepare.sh | 90 -------------- autobuild/android/autobuild_apk_2_build.sh | 33 ------ .../android/autobuild_apk_3_copy_files.sh | 43 ------- 5 files changed, 116 insertions(+), 170 deletions(-) create mode 100755 .github/autobuild/android.sh delete mode 100755 autobuild/android/autobuild_apk_1_prepare.sh delete mode 100755 autobuild/android/autobuild_apk_2_build.sh delete mode 100755 autobuild/android/autobuild_apk_3_copy_files.sh diff --git a/.github/autobuild/android.sh b/.github/autobuild/android.sh new file mode 100755 index 0000000000..7aeb4ce82f --- /dev/null +++ b/.github/autobuild/android.sh @@ -0,0 +1,112 @@ +#!/bin/bash +set -eu + +COMMANDLINETOOLS_VERSION=6858069 +ANDROID_NDK_VERSION=r21d +ANDROID_PLATFORM=android-30 +ANDROID_BUILD_TOOLS=30.0.2 +AQTINSTALL_VERSION=2.0.6 +QT_VERSION=5.15.2 + +# Only variables which are really needed by sub-commands are exported. +# Definitions have to stay in a specific order due to dependencies. +QT_BASEDIR="/opt/Qt" +ANDROID_BASEDIR="/opt/android" +BUILD_DIR=build +export ANDROID_SDK_ROOT="${ANDROID_BASEDIR}/android-sdk" +COMMANDLINETOOLS_DIR="${ANDROID_SDK_ROOT}"/cmdline-tools/latest/ +ANDROID_NDK_ROOT="${ANDROID_BASEDIR}/android-ndk" +ANDROID_NDK_HOST="linux-x86_64" +ANDROID_SDKMANAGER="${COMMANDLINETOOLS_DIR}/bin/sdkmanager" +export JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/" +export PATH="${PATH}:${ANDROID_SDK_ROOT}/tools" +export PATH="${PATH}:${ANDROID_SDK_ROOT}/platform-tools" + +if [[ ! ${jamulus_buildversionstring:-} =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then + echo "Environment variable jamulus_buildversionstring has to be set to a valid version string" + exit 1 +fi + +setup_ubuntu_dependencies() { + export DEBIAN_FRONTEND="noninteractive" + + sudo apt-get -qq update + sudo apt-get -qq --no-install-recommends -y install build-essential zip unzip bzip2 p7zip-full curl chrpath openjdk-8-jdk-headless +} + +setup_android_sdk() { + mkdir -p "${ANDROID_BASEDIR}" + + if [[ -d "${COMMANDLINETOOLS_DIR}" ]]; then + echo "Using commandlinetools installation from previous run (actions/cache)" + else + mkdir -p "${COMMANDLINETOOLS_DIR}" + curl -s -o downloadfile "https://dl.google.com/android/repository/commandlinetools-linux-${COMMANDLINETOOLS_VERSION}_latest.zip" + unzip -q downloadfile + mv cmdline-tools/* "${COMMANDLINETOOLS_DIR}" + fi + + yes | "${ANDROID_SDKMANAGER}" --licenses + "${ANDROID_SDKMANAGER}" --update + "${ANDROID_SDKMANAGER}" "platforms;${ANDROID_PLATFORM}" + "${ANDROID_SDKMANAGER}" "build-tools;${ANDROID_BUILD_TOOLS}" +} + +setup_android_ndk() { + mkdir -p "${ANDROID_BASEDIR}" + if [[ -d "${ANDROID_NDK_ROOT}" ]]; then + echo "Using NDK installation from previous run (actions/cache)" + else + curl -s -o downloadfile "https://dl.google.com/android/repository/android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip" + unzip -q downloadfile + mv "android-ndk-${ANDROID_NDK_VERSION}" "${ANDROID_NDK_ROOT}" + fi +} + +setup_qt() { + if [[ -d "${QT_BASEDIR}" ]]; then + echo "Using Qt installation from previous run (actions/cache)" + else + echo "Installing Qt..." + python3 -m pip install "aqtinstall==${AQTINSTALL_VERSION}" + python3 -m aqt install-qt --outputdir "${QT_BASEDIR}" linux android "${QT_VERSION}" \ + --archives qtbase qttools qttranslations qtandroidextras + fi +} + +build_app_as_apk() { + QT_DIR="${QT_BASEDIR}/${QT_VERSION}/android" + MAKE="${ANDROID_NDK_ROOT}/prebuilt/${ANDROID_NDK_HOST}/bin/make" + + "${QT_DIR}/bin/qmake" -spec android-clang + "${MAKE}" -j "$(nproc)" + "${MAKE}" INSTALL_ROOT="${BUILD_DIR}" -f Makefile install + "${QT_DIR}"/bin/androiddeployqt --input android-Jamulus-deployment-settings.json --output "${BUILD_DIR}" \ + --android-platform "${ANDROID_PLATFORM}" --jdk "${JAVA_HOME}" --gradle +} + +pass_artifact_to_job() { + mkdir deploy + artifact_deploy_filename="jamulus_${jamulus_buildversionstring}_android.apk" + echo "Moving ${BUILD_DIR}/build/outputs/apk/debug/build-debug.apk to deploy/${artifact_deploy_filename}" + mv "./${BUILD_DIR}/build/outputs/apk/debug/build-debug.apk" "./deploy/${artifact_deploy_filename}" + echo "::set-output name=artifact_1::${artifact_deploy_filename}" +} + +case "${1:-}" in + setup) + setup_ubuntu_dependencies + setup_android_ndk + setup_android_sdk + setup_qt + ;; + build) + build_app_as_apk + ;; + get-artifacts) + pass_artifact_to_job + ;; + *) + echo "Unknown stage '${1:-}'" + exit 1 +esac diff --git a/.github/workflows/autobuild.yml b/.github/workflows/autobuild.yml index ebac4d1e9e..d783578bfc 100644 --- a/.github/workflows/autobuild.yml +++ b/.github/workflows/autobuild.yml @@ -87,9 +87,9 @@ jobs: - config_name: Android .apk (artifact+codeQL) target_os: android building_on_os: ubuntu-20.04 - cmd1_prebuild: "./autobuild/android/autobuild_apk_1_prepare.sh" - cmd2_build: "./autobuild/android/autobuild_apk_2_build.sh" - cmd3_postbuild: "./autobuild/android/autobuild_apk_3_copy_files.sh" + cmd1_prebuild: "./.github/autobuild/android.sh setup" + cmd2_build: "./.github/autobuild/android.sh build" + cmd3_postbuild: "./.github/autobuild/android.sh get-artifacts" run_codeql: true # Jamulus.pro needs to count git history length for android versioning: checkout_fetch_depth: '0' @@ -196,7 +196,7 @@ jobs: /opt/Qt /opt/android/android-sdk /opt/android/android-ndk - key: ${{ matrix.config.target_os }}-${{ hashFiles('.github/workflows/autobuild.yml', 'autobuild/android/autobuild_apk_1_prepare.sh', 'autobuild/android/install-qt.sh') }}-${{ matrix.config.cmd1_prebuild }} + key: ${{ matrix.config.target_os }}-${{ hashFiles('.github/workflows/autobuild.yml', '.github/autobuild/android.sh') }}-${{ matrix.config.cmd1_prebuild }} - name: Set up build dependencies for ${{ matrix.config.config_name }} if: matrix.config.cmd1_prebuild diff --git a/autobuild/android/autobuild_apk_1_prepare.sh b/autobuild/android/autobuild_apk_1_prepare.sh deleted file mode 100755 index d90e2d6295..0000000000 --- a/autobuild/android/autobuild_apk_1_prepare.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/bash -e - -# autobuild_1_prepare: set up environment, install Qt & dependencies - - -################### -### PROCEDURE ### -################### - -COMMANDLINETOOLS_VERSION=6858069 -ANDROID_NDK_VERSION=r21d -AQTINSTALL_VERSION=2.0.6 - -export DEBIAN_FRONTEND="noninteractive" -echo "::set-env name=DEBIAN_FRONTEND::${DEBIAN_FRONTEND}" - -sudo apt-get -qq update -# Dependencies to create Android pkg -sudo apt-get -qq --no-install-recommends -y install build-essential zip unzip bzip2 p7zip-full wget curl chrpath libxkbcommon-x11-0 \ - openjdk-8-jre-headless openjdk-8-jdk-headless - -# Add Android tools and platform tools to PATH -export ANDROID_HOME="/opt/android/android-sdk" -export ANDROID_SDK_ROOT="${ANDROID_HOME}" -export ANDROID_NDK_ROOT="/opt/android/android-ndk" -COMMANDLINETOOLS_DIR="${ANDROID_SDK_ROOT}"/cmdline-tools/latest/ - -export PATH="${PATH}:${ANDROID_HOME}/tools" -export PATH="${PATH}:${ANDROID_HOME}/platform-tools" -export JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/" - -# other variables -export MY_QT_VERSION="5.15.2" -export ANDROID_NDK_HOST="linux-x86_64" -export ANDROID_SDKMANAGER="${COMMANDLINETOOLS_DIR}/bin/sdkmanager" - -# paths for Android SDK -mkdir -p "${ANDROID_SDK_ROOT}"/build-tools/latest/ - -# Install Android sdk -if [[ -d "${COMMANDLINETOOLS_DIR}" ]]; then - echo "Using commandlinetools installation from previous run (actions/cache)" -else - mkdir -p "${COMMANDLINETOOLS_DIR}" - wget -q -O downloadfile https://dl.google.com/android/repository/commandlinetools-linux-${COMMANDLINETOOLS_VERSION}_latest.zip - unzip -q downloadfile - mv cmdline-tools/* "${COMMANDLINETOOLS_DIR}" -fi - -# Install Android ndk -if [[ -d "${ANDROID_NDK_ROOT}" ]]; then - echo "Using NDK installation from previous run (actions/cache)" -else - wget -q -O downloadfile https://dl.google.com/android/repository/android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip - unzip -q downloadfile - mv android-ndk-${ANDROID_NDK_VERSION} "${ANDROID_NDK_ROOT}" -fi - -# Install Android SDK -yes | "${ANDROID_SDKMANAGER}" --licenses -"${ANDROID_SDKMANAGER}" --update -"${ANDROID_SDKMANAGER}" "platforms;android-30" -"${ANDROID_SDKMANAGER}" "build-tools;30.0.2" - - -# Download / install Qt -QT_BASEDIR="/opt/Qt" -if [[ -d "${QT_BASEDIR}" ]]; then - echo "Using Qt installation from previous run (actions/cache)" -else - echo "Install dependencies..." - python3 -m pip install "aqtinstall==${AQTINSTALL_VERSION}" - python3 -m aqt install-qt --outputdir "${QT_BASEDIR}" linux android "${MY_QT_VERSION}" --archives qtbase qttools qttranslations qtandroidextras -fi - -# Set the QTDIR environment variable -export QTDIR="${QT_BASEDIR}/${MY_QT_VERSION}/android" - -#necessary -echo "::set-env name=QTDIR::${QTDIR}" -echo "::set-env name=ANDROID_NDK_ROOT::${ANDROID_NDK_ROOT}" -echo "::set-env name=ANDROID_NDK_HOST::${ANDROID_NDK_HOST}" -echo "::set-env name=JAVA_HOME::${JAVA_HOME}" - -#nice to have -echo "::set-env name=ANDROID_HOME::${ANDROID_HOME}" -echo "::set-env name=ANDROID_SDK_ROOT::${ANDROID_SDK_ROOT}" -echo "::set-env name=PATH::${PATH}" -echo "::set-env name=MY_QT_VERSION::${MY_QT_VERSION}" -echo "::set-env name=ANDROID_SDKMANAGER::${ANDROID_SDKMANAGER}" diff --git a/autobuild/android/autobuild_apk_2_build.sh b/autobuild/android/autobuild_apk_2_build.sh deleted file mode 100755 index 556348665d..0000000000 --- a/autobuild/android/autobuild_apk_2_build.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -e - -# autobuild_2_build: actual build process - - -#################### -### PARAMETERS ### -#################### - -source $(dirname $(readlink -f "${BASH_SOURCE[0]}"))/../ensure_THIS_JAMULUS_PROJECT_PATH.sh - -################### -### PROCEDURE ### -################### - -cd "${THIS_JAMULUS_PROJECT_PATH}" - -"${QTDIR}"/bin/qmake -spec android-clang CONFIG+=release -echo . -echo . -echo . -echo . -/opt/android/android-ndk/prebuilt/linux-x86_64/bin/make -j "$(nproc)" -echo . -echo . -echo . -echo . -"${ANDROID_NDK_ROOT}"/prebuilt/"${ANDROID_NDK_HOST}"/bin/make INSTALL_ROOT=android-build -f Makefile install -echo . -echo . -echo . -echo . -"${QTDIR}"/bin/androiddeployqt --input $(ls *.json) --output android-build --android-platform android-30 --jdk "${JAVA_HOME}" --gradle diff --git a/autobuild/android/autobuild_apk_3_copy_files.sh b/autobuild/android/autobuild_apk_3_copy_files.sh deleted file mode 100755 index 43539dd4ea..0000000000 --- a/autobuild/android/autobuild_apk_3_copy_files.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -# autobuild_3_copy_files: copy the built files to deploy folder - - -#################### -### PARAMETERS ### -#################### - -source $(dirname $(readlink -f "${BASH_SOURCE[0]}"))/../ensure_THIS_JAMULUS_PROJECT_PATH.sh - -################### -### PROCEDURE ### -################### - -mkdir "${THIS_JAMULUS_PROJECT_PATH}"/deploy - -echo "" -echo "" -echo "ls GITROOT/android-build/build/outputs/apk/debug/" -ls "${THIS_JAMULUS_PROJECT_PATH}"/android-build/build/outputs/apk/debug/ -echo "" - - -artifact_deploy_filename=jamulus_${jamulus_buildversionstring}_android.apk -echo "" -echo "" -echo "move to ${artifact_deploy_filename}" -mv "${THIS_JAMULUS_PROJECT_PATH}"/android-build/build/outputs/apk/debug/android-build-debug.apk "${THIS_JAMULUS_PROJECT_PATH}"/deploy/"${artifact_deploy_filename}" - -echo "" -echo "" -echo "ls GITROOT/deploy/" -ls "${THIS_JAMULUS_PROJECT_PATH}"/deploy/ -echo "" - -github_output_value() -{ - echo "github_output_value() ${1} = ${2}" - echo "::set-output name=${1}::${2}" -} - -github_output_value artifact_1 ${artifact_deploy_filename} From 7803eb5921c9af3c56a571b4faa0c8870909e066 Mon Sep 17 00:00:00 2001 From: Christian Hoffmann Date: Sat, 19 Mar 2022 17:10:56 +0100 Subject: [PATCH 2/5] Autobuild: Remove unused autobuild/ensure_THIS_JAMULUS_PROJECT_PATH.sh Now that all platforms have been converted to the new scheme (.github/autobuild/*), the autobuild directory only contains the ensure_THIS_JAMULUS_PROJECT_PATH.sh script which is no longer used. Related: #2521 --- autobuild/ensure_THIS_JAMULUS_PROJECT_PATH.sh | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100755 autobuild/ensure_THIS_JAMULUS_PROJECT_PATH.sh diff --git a/autobuild/ensure_THIS_JAMULUS_PROJECT_PATH.sh b/autobuild/ensure_THIS_JAMULUS_PROJECT_PATH.sh deleted file mode 100755 index a1366340de..0000000000 --- a/autobuild/ensure_THIS_JAMULUS_PROJECT_PATH.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -echo "ensuring env-variable THIS_JAMULUS_PROJECT_PATH" - -#################### -### PARAMETERS ### -#################### - -if [ ! -z "${1}" ]; then - echo "THIS_JAMULUS_PROJECT_PATH from parameter" - THIS_JAMULUS_PROJECT_PATH="${1}" -elif [ ! -z "${jamulus_project_path}" ]; then - echo "THIS_JAMULUS_PROJECT_PATH from env-variable jamulus_project_path" - THIS_JAMULUS_PROJECT_PATH="${jamulus_project_path}" -elif [ ! -z "${GITHUB_WORKSPACE}" ]; then - echo "THIS_JAMULUS_PROJECT_PATH from env-variable GITHUB_WORKSPACE" - THIS_JAMULUS_PROJECT_PATH="${GITHUB_WORKSPACE}" -else - echo "Please give the path to the repository root as environment variable 'jamulus_project_path' or parameter to this script!" - exit 1 -fi - -if [ -d "$THIS_JAMULUS_PROJECT_PATH" ]; then - echo "THIS_JAMULUS_PROJECT_PATH exists (relative): ${THIS_JAMULUS_PROJECT_PATH}" - ## THIS_JAMULUS_PROJECT_PATH=$(readlink -e "${THIS_JAMULUS_PROJECT_PATH}") # works for linux, but not mac - THIS_JAMULUS_PROJECT_PATH=$(python -c "import os; print(os.path.abspath(\"${THIS_JAMULUS_PROJECT_PATH}\"));") - #python -c "import os; print(os.path.abspath(\"${THIS_JAMULUS_PROJECT_PATH}\"));" - echo "THIS_JAMULUS_PROJECT_PATH exists (absolute): ${THIS_JAMULUS_PROJECT_PATH}" -else - echo "ERROR: THIS_JAMULUS_PROJECT_PATH must reference an existing directory: \"${THIS_JAMULUS_PROJECT_PATH}\"" - exit 1 -fi From 8cec00b5d18f8c2daf7e3a167a9be185bd1f58df Mon Sep 17 00:00:00 2001 From: Christian Hoffmann Date: Sat, 19 Mar 2022 20:50:46 +0100 Subject: [PATCH 3/5] Android: Add Qt6 workaround for QtAndroid Qt6 no longer ships qtandroidextras. As of 6.2, there is no replacement either. The official workaround is to use the private headers which still contain the APIs we need: https://bugreports.qt.io/browse/QTBUG-84382?focusedCommentId=566019&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-566019 Fixes #2528 --- .github/autobuild/android.sh | 5 +++++ Jamulus.pro | 8 +++++++- src/main.cpp | 9 ++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/autobuild/android.sh b/.github/autobuild/android.sh index 7aeb4ce82f..42f9cd4869 100755 --- a/.github/autobuild/android.sh +++ b/.github/autobuild/android.sh @@ -71,6 +71,11 @@ setup_qt() { python3 -m pip install "aqtinstall==${AQTINSTALL_VERSION}" python3 -m aqt install-qt --outputdir "${QT_BASEDIR}" linux android "${QT_VERSION}" \ --archives qtbase qttools qttranslations qtandroidextras + QT_ARCHIVES=(qtbase qttools qttranslations) + if [[ "${QT_VERSION}" =~ 5\..* ]]; then + QT_ARCHIVES+=(qtandroidextras) + fi + python3 -m aqt install-qt --outputdir "${QT_BASEDIR}" linux android "${QT_VERSION}" --archives "${QT_ARCHIVES[@]}" fi } diff --git a/Jamulus.pro b/Jamulus.pro index 7c10220099..b9b77813a1 100644 --- a/Jamulus.pro +++ b/Jamulus.pro @@ -211,7 +211,13 @@ win32 { # liboboe requires C++17 for std::timed_mutex CONFIG += c++17 - QT += androidextras + lessThan(QT_MAJOR_VERSION, 6) { + QT += androidextras + } else { + # Qt >=6 does not have an androidextras module anymore. + # The current workaround as of Qt 6.2 is to use private headers from qtbase. + CONFIG += core-private + } # enabled only for debugging on android devices DEFINES += ANDROIDDEBUG diff --git a/src/main.cpp b/src/main.cpp index 888be6778d..f6abcaaca8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,7 +36,14 @@ #include "testbench.h" #include "util.h" #ifdef ANDROID -# include +# if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) +/* Qt6 doesn't have qtandroidextras anymore, but there is no replacement either. + * Therefore, the official workaround is using the private header here: + */ +# include +# else +# include +# endif #endif #if defined( Q_OS_MACX ) # include "mac/activity.h" From 0d332f63271605cfaca77d853eed54626df0c22a Mon Sep 17 00:00:00 2001 From: Christian Hoffmann Date: Thu, 27 Jan 2022 01:31:49 +0100 Subject: [PATCH 4/5] Autobuild: Android: Build with Qt 6.2.3 --- .github/autobuild/android.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/autobuild/android.sh b/.github/autobuild/android.sh index 42f9cd4869..dd5afce0d3 100755 --- a/.github/autobuild/android.sh +++ b/.github/autobuild/android.sh @@ -6,7 +6,7 @@ ANDROID_NDK_VERSION=r21d ANDROID_PLATFORM=android-30 ANDROID_BUILD_TOOLS=30.0.2 AQTINSTALL_VERSION=2.0.6 -QT_VERSION=5.15.2 +QT_VERSION=6.2.3 # Only variables which are really needed by sub-commands are exported. # Definitions have to stay in a specific order due to dependencies. From 22a949c1ad7cb6556e128272fb25fa0fcba314e5 Mon Sep 17 00:00:00 2001 From: Christian Hoffmann Date: Mon, 21 Mar 2022 21:08:38 +0100 Subject: [PATCH 5/5] Android: Add Qt6 compatibility (80%) This is still broken. The main reason is that Qt6 no longer supports building multiple ANDROID_ABIS in one go. This commit includes some attempts to work around this, but they don't work. Individual builds do work though. --- .github/autobuild/android.sh | 71 +++++++++++++++++++++++++++++++----- Jamulus.pro | 11 +----- android/AndroidManifest.xml | 50 +------------------------ src/main.cpp | 25 ------------- 4 files changed, 65 insertions(+), 92 deletions(-) diff --git a/.github/autobuild/android.sh b/.github/autobuild/android.sh index dd5afce0d3..af7f395e55 100755 --- a/.github/autobuild/android.sh +++ b/.github/autobuild/android.sh @@ -8,17 +8,26 @@ ANDROID_BUILD_TOOLS=30.0.2 AQTINSTALL_VERSION=2.0.6 QT_VERSION=6.2.3 +# This list has to match Jamulus.pro's ANDROID_ABIS, but we can't extract it automatically as names differ slightly: +ABIS=(x86 x86_64 armv7 arm64_v8a) + +if [[ "${QT_VERSION}" =~ 5\..* ]]; then + JAVA_VERSION=8 +else + JAVA_VERSION=11 +fi + # Only variables which are really needed by sub-commands are exported. # Definitions have to stay in a specific order due to dependencies. QT_BASEDIR="/opt/Qt" ANDROID_BASEDIR="/opt/android" BUILD_DIR=build export ANDROID_SDK_ROOT="${ANDROID_BASEDIR}/android-sdk" +export ANDROID_NDK_ROOT="${ANDROID_BASEDIR}/android-ndk" COMMANDLINETOOLS_DIR="${ANDROID_SDK_ROOT}"/cmdline-tools/latest/ -ANDROID_NDK_ROOT="${ANDROID_BASEDIR}/android-ndk" ANDROID_NDK_HOST="linux-x86_64" ANDROID_SDKMANAGER="${COMMANDLINETOOLS_DIR}/bin/sdkmanager" -export JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/" +export JAVA_HOME="/usr/lib/jvm/java-${JAVA_VERSION}-openjdk-amd64/" export PATH="${PATH}:${ANDROID_SDK_ROOT}/tools" export PATH="${PATH}:${ANDROID_SDK_ROOT}/platform-tools" @@ -29,9 +38,14 @@ fi setup_ubuntu_dependencies() { export DEBIAN_FRONTEND="noninteractive" + EXTRA_PKGS=("") + if [[ ! "${QT_VERSION}" =~ 5\..* ]]; then + # Qt6 depends on this: + EXTRA_PKGS=("libglib2.0-0") + fi sudo apt-get -qq update - sudo apt-get -qq --no-install-recommends -y install build-essential zip unzip bzip2 p7zip-full curl chrpath openjdk-8-jdk-headless + sudo apt-get -qq --no-install-recommends -y install build-essential zip unzip bzip2 p7zip-full curl chrpath "openjdk-${JAVA_VERSION}-jdk-headless" "${EXTRA_PKGS[@]}" } setup_android_sdk() { @@ -74,19 +88,56 @@ setup_qt() { QT_ARCHIVES=(qtbase qttools qttranslations) if [[ "${QT_VERSION}" =~ 5\..* ]]; then QT_ARCHIVES+=(qtandroidextras) + python3 -m aqt install-qt --outputdir "${QT_BASEDIR}" linux android "${QT_VERSION}" --archives "${QT_ARCHIVES[@]}" + else + # From Qt6 onwards, each android ABI has to be installed individually. + local abi + for abi in "${ABIS[@]}"; do + python3 -m aqt install-qt --outputdir "${QT_BASEDIR}" linux android "${QT_VERSION}" "android_${abi}" --archives "${QT_ARCHIVES[@]}" + done + + # In addition, android no longer provides a full qmake binary. Instead, it's just a script. + # We need to install the regular Linux desktop qmake instead. + # Qt6 is also linked to rather exotic versions of libicu, therefore, we need to install those prebuilt libs as well: + python3 -m aqt install-qt --outputdir "${QT_BASEDIR}" linux desktop "${QT_VERSION}" --archives qtbase icu fi - python3 -m aqt install-qt --outputdir "${QT_BASEDIR}" linux android "${QT_VERSION}" --archives "${QT_ARCHIVES[@]}" fi } build_app_as_apk() { - QT_DIR="${QT_BASEDIR}/${QT_VERSION}/android" - MAKE="${ANDROID_NDK_ROOT}/prebuilt/${ANDROID_NDK_HOST}/bin/make" + local MAKE="${ANDROID_NDK_ROOT}/prebuilt/${ANDROID_NDK_HOST}/bin/make" + local DEPLOYMENT_SETTINGS="android-Jamulus-deployment-settings.json" + local ARCHITECTURES="" + local abi + for abi in "${ABIS[@]}"; do + if [[ "${QT_VERSION}" =~ 5\..* ]]; then + QMAKE="${QT_BASEDIR}/${QT_VERSION}/android/bin/qmake" + ANDROIDDEPLOYQT="${QT_BASEDIR}/${QT_VERSION}/android/bin/androiddeployqt" + else + # From Qt6 onwards, there is no single android directory anymore. + # Instead, there's one per ABI. As qmake handles ABIs itself, we just pick + # one here: + QMAKE="${QT_BASEDIR}/${QT_VERSION}/android_${abi}/bin/qmake" + # In Qt6, androiddeployqt is part of the desktop qtbase, not the android* qtbase: + ANDROIDDEPLOYQT="${QT_BASEDIR}/${QT_VERSION}/gcc_64/bin/androiddeployqt" + fi + + "${QMAKE}" -spec android-clang + "${MAKE}" -j "$(nproc)" + "${MAKE}" INSTALL_ROOT="${BUILD_DIR}" -f Makefile install + if [[ "${QT_VERSION}" =~ 5\..* ]]; then + # Qt5 performs all ABI builds in one go + break + fi + [[ -z "${ARCHITECTURES}" ]] || ARCHITECTURES="${ARCHITECTURES}, " + ARCHITECTURES="${ARCHITECTURES}$(grep -oP '"architectures":\s*\{\K[^}]+(?=\})' "${DEPLOYMENT_SETTINGS}")" + "${MAKE}" clean + done + if [[ ! "${QT_VERSION}" =~ 5\..* ]]; then + sed -re 's/("architectures":\s*\{).*(\}.*)/\1'"${ARCHITECTURES}\2/" -i "${DEPLOYMENT_SETTINGS}" + fi - "${QT_DIR}/bin/qmake" -spec android-clang - "${MAKE}" -j "$(nproc)" - "${MAKE}" INSTALL_ROOT="${BUILD_DIR}" -f Makefile install - "${QT_DIR}"/bin/androiddeployqt --input android-Jamulus-deployment-settings.json --output "${BUILD_DIR}" \ + "${ANDROIDDEPLOYQT}" --input "${DEPLOYMENT_SETTINGS}" --output "${BUILD_DIR}" \ --android-platform "${ANDROID_PLATFORM}" --jdk "${JAVA_HOME}" --gradle } diff --git a/Jamulus.pro b/Jamulus.pro index b9b77813a1..d8ec27f690 100644 --- a/Jamulus.pro +++ b/Jamulus.pro @@ -203,22 +203,15 @@ win32 { LIBS += -framework AVFoundation \ -framework AudioToolbox } else:android { - ANDROID_ABIS = armeabi-v7a arm64-v8a x86 x86_64 + #ANDROID_ABIS = armeabi-v7a arm64-v8a x86 x86_64 ANDROID_VERSION_NAME = $$VERSION ANDROID_VERSION_CODE = $$system(git log --oneline | wc -l) + ANDROID_PERMISSIONS += android.permission.MODIFY_AUDIO_SETTINGS android.permission.RECORD_AUDIO message("Setting ANDROID_VERSION_NAME=$${ANDROID_VERSION_NAME} ANDROID_VERSION_CODE=$${ANDROID_VERSION_CODE}") # liboboe requires C++17 for std::timed_mutex CONFIG += c++17 - lessThan(QT_MAJOR_VERSION, 6) { - QT += androidextras - } else { - # Qt >=6 does not have an androidextras module anymore. - # The current workaround as of Qt 6.2 is to use private headers from qtbase. - CONFIG += core-private - } - # enabled only for debugging on android devices DEFINES += ANDROIDDEBUG diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 5bf53539ae..d7bd757f3c 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,14 +1,10 @@ - + - - - - @@ -18,57 +14,16 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main.cpp b/src/main.cpp index f6abcaaca8..fc81d9de92 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,16 +35,6 @@ #include "settings.h" #include "testbench.h" #include "util.h" -#ifdef ANDROID -# if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) -/* Qt6 doesn't have qtandroidextras anymore, but there is no replacement either. - * Therefore, the official workaround is using the private header here: - */ -# include -# else -# include -# endif -#endif #if defined( Q_OS_MACX ) # include "mac/activity.h" extern void qt_set_sequence_auto_mnemonic ( bool bEnable ); @@ -774,21 +764,6 @@ int main ( int argc, char** argv ) # endif #endif -#ifdef ANDROID - // special Android coded needed for record audio permission handling - auto result = QtAndroid::checkPermission ( QString ( "android.permission.RECORD_AUDIO" ) ); - - if ( result == QtAndroid::PermissionResult::Denied ) - { - QtAndroid::PermissionResultMap resultHash = QtAndroid::requestPermissionsSync ( QStringList ( { "android.permission.RECORD_AUDIO" } ) ); - - if ( resultHash["android.permission.RECORD_AUDIO"] == QtAndroid::PermissionResult::Denied ) - { - return 0; - } - } -#endif - #ifdef _WIN32 // set application priority class -> high priority SetPriorityClass ( GetCurrentProcess(), HIGH_PRIORITY_CLASS );