|
|
|
|
/*
|
|
|
|
|
This file is part of Magnum.
|
|
|
|
|
|
|
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
|
|
|
|
|
Vladimír Vondruš <mosra@centrum.cz>
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
to deal in the Software without restriction, including without limitation
|
|
|
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
|
|
|
in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
|
DEALINGS IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
namespace Magnum {
|
|
|
|
|
|
|
|
|
|
/** @page platforms-android Android
|
|
|
|
|
@brief Building and deploying Android projects
|
|
|
|
|
|
|
|
|
|
@tableofcontents
|
|
|
|
|
@m_footernavigation
|
|
|
|
|
@m_keywords{android_create_apk()}
|
|
|
|
|
|
|
|
|
|
@todoc code coverage
|
|
|
|
|
@todoc static plugins
|
|
|
|
|
|
|
|
|
|
The following guide explains how to build Android projects using minimal
|
|
|
|
|
command-line tools, without Android Studio involved.
|
|
|
|
|
|
|
|
|
|
At the very least you need to have Android SDK and Android NDK installed.
|
|
|
|
|
Running console utilities and tests on the device don't need much more, in case
|
|
|
|
|
you want to develop actual applications, you need also the SDK and a platform +
|
|
|
|
|
SDK platform build tools for version of your choice.
|
|
|
|
|
|
|
|
|
|
For APK building it's possible to use either an experimental support in CMake
|
|
|
|
|
or the official way with Gradle. Gradle is able to download all the
|
|
|
|
|
dependencies on its own, however it's also possible to install system packages
|
|
|
|
|
for a cleaner setup.
|
|
|
|
|
|
|
|
|
|
@note On ArchLinux it's the `gradle` package and the following AUR packages,
|
|
|
|
|
adapt the version numbers as necessary:
|
|
|
|
|
@note
|
|
|
|
|
- [android-sdk](https://aur.archlinux.org/packages/android-sdk/)
|
|
|
|
|
- [android-ndk](https://aur.archlinux.org/packages/android-ndk/)
|
|
|
|
|
- [android-sdk-build-tools](https://aur.archlinux.org/packages/android-sdk-build-tools/)
|
|
|
|
|
- [android-sdk-platform-tools](https://aur.archlinux.org/packages/android-sdk-platform-tools/)
|
|
|
|
|
- [android-platform-22](https://aur.archlinux.org/packages/android-platform-22/)
|
|
|
|
|
- [android-sdk-cmake](https://aur.archlinux.org/packages/android-sdk-cmake/)
|
|
|
|
|
|
|
|
|
|
Gradle requires Android SDK version of CMake, which is currently at version
|
|
|
|
|
3.6. See below for an experimental way to @ref platforms-android-system-cmake "use the system CMake"
|
|
|
|
|
instead.
|
|
|
|
|
|
|
|
|
|
@section platforms-android-console Building and running console applications
|
|
|
|
|
|
|
|
|
|
Android allows to run arbitrary console utilities and tests via ADB. Assuming
|
|
|
|
|
you have Magnum installed in the NDK path as described in @ref building-cross-android,
|
|
|
|
|
build your project simply as this (adapt version numbers and ABIs as needed):
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
mkdir build-android-arm64 && cd build-android-arm64
|
|
|
|
|
cmake .. \
|
|
|
|
|
-DCMAKE_SYSTEM_NAME=Android \
|
|
|
|
|
-DCMAKE_SYSTEM_VERSION=22 \
|
|
|
|
|
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
|
|
|
|
|
-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
|
|
|
|
|
-DCMAKE_ANDROID_STL_TYPE=c++_static \
|
|
|
|
|
-DCMAKE_BUILD_TYPE=Release
|
|
|
|
|
cmake --build .
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
After that you can use ADB to upload your executable to the device and run it
|
|
|
|
|
there. The global temporary directory is `/data/local/tmp` and while the parent
|
|
|
|
|
directories often don't have permissions, it's possible to @cb{.sh} cd @ce into
|
|
|
|
|
it and create arbitrary files there. Assuming you built an executable in
|
|
|
|
|
`build-android-arm64/src/my-application`, the workflow would be like this:
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
adb push build-android-arm64/src/my-application /data/local/tmp
|
|
|
|
|
adb shell /data/local/tmp/my-application
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
You can also use @cb{.sh} adb shell @ce to enter the device shell directly and
|
|
|
|
|
continue from there. Besides plain command-line apps it's also possible to
|
|
|
|
|
create an EGL context without any extra setup using
|
|
|
|
|
@ref Platform::WindowlessEglApplication. See also @ref GL::OpenGLTester for
|
|
|
|
|
information about OpenGL testing.
|
|
|
|
|
|
|
|
|
|
@section platforms-android-apps Building and installing graphics apps
|
|
|
|
|
|
|
|
|
|
In case you don't have an OpenGL ES build set up yet, you need to copy
|
|
|
|
|
`FindEGL.cmake` and `FindOpenGLES2.cmake` (or `FindOpenGLES3.cmake`) from the
|
|
|
|
|
[modules/](https://github.com/mosra/magnum/tree/master/modules) directory in
|
|
|
|
|
Magnum source to the `modules/` dir in your project so it is able to find EGL
|
|
|
|
|
and OpenGL ES libraries.
|
|
|
|
|
|
|
|
|
|
Magnum provides Android application wrapper in @ref Platform::AndroidApplication.
|
|
|
|
|
See its documentation for more information about general usage. You can also
|
|
|
|
|
use the Android Native Activity directly or any other way.
|
|
|
|
|
|
|
|
|
|
@note @ref Platform::AndroidApplication also contains a fully configured
|
|
|
|
|
bootstrap project that's ready to build and deploy. Check its documentation
|
|
|
|
|
for details.
|
|
|
|
|
|
|
|
|
|
If you plan to use @ref Platform::AndroidApplication, be sure to request it
|
|
|
|
|
only on Android, for example:
|
|
|
|
|
|
|
|
|
|
@code{.cmake}
|
|
|
|
|
if(CORRADE_TARGET_ANDROID)
|
|
|
|
|
find_package(Magnum REQUIRED AndroidApplication)
|
|
|
|
|
else()
|
|
|
|
|
find_package(Magnum REQUIRED Sdl2Application)
|
|
|
|
|
endif()
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Compared to building an app for other platforms, you need to create a shared
|
|
|
|
|
library instead of an executable:
|
|
|
|
|
|
|
|
|
|
@code{.cmake}
|
|
|
|
|
if(NOT CORRADE_TARGET_ANDROID)
|
|
|
|
|
add_executable(my-application MyApplication.cpp)
|
|
|
|
|
else()
|
|
|
|
|
add_library(my-application SHARED MyApplication.cpp)
|
|
|
|
|
endif()
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-apps-manifest Android manifest file
|
|
|
|
|
|
|
|
|
|
For Android you additionally need an `AndroidManifest.xml` file, which
|
|
|
|
|
describes various properties of the Android package. A minimal stripped-down
|
|
|
|
|
version is:
|
|
|
|
|
|
|
|
|
|
@code{.xml-jinja}
|
|
|
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
|
|
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
|
|
|
package="{{ package }}" android:versionCode="1" android:versionName="1.0">
|
|
|
|
|
<uses-feature android:glEsVersion="0x00020000" />
|
|
|
|
|
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="11" />
|
|
|
|
|
<application android:label="{{ app_name }}" android:hasCode="false">
|
|
|
|
|
<activity
|
|
|
|
|
android:name="android.app.NativeActivity"
|
|
|
|
|
android:label="{{ app_name }}"
|
|
|
|
|
android:configChanges="orientation|screenSize">
|
|
|
|
|
<meta-data android:name="android.app.lib_name" android:value="{{ lib_name }}" />
|
|
|
|
|
<intent-filter>
|
|
|
|
|
<action android:name="android.intent.action.MAIN" />
|
|
|
|
|
<category android:name="android.intent.category.LAUNCHER" />
|
|
|
|
|
</intent-filter>
|
|
|
|
|
</activity>
|
|
|
|
|
</application>
|
|
|
|
|
</manifest>
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Replace @cb{.jinja} {{ package }} @ce with Java-like package name for your app
|
|
|
|
|
(in this case it could be e.g. @cpp "cz.mosra.magnum.my_application" @ce, for
|
|
|
|
|
example), @cb{.jinja} {{ app_name }} @ce with human-readable app name that's
|
|
|
|
|
displayed in the system (so e.g. @cpp "My Application" @ce) and finally the
|
|
|
|
|
@cb{.jinja} {{ lib_name }} @ce is name of the library that you compiled with
|
|
|
|
|
CMake, which in this case would be @cpp "my-application" @ce.
|
|
|
|
|
|
|
|
|
|
The @cb{.xml} <uses-feature android:glEsVersion="0x00020000" /> @ce line says
|
|
|
|
|
that the minimal OpenGL ES version is 2.0, change it in case you require a
|
|
|
|
|
different version.
|
|
|
|
|
|
|
|
|
|
@anchor platforms-android-apps-manifest-screen-compatibility-mode
|
|
|
|
|
|
|
|
|
|
The @cb{.xml} <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="11" /> @ce
|
|
|
|
|
line requests the minimal and target Android SDK version. Setting the version
|
|
|
|
|
lower than this (or accidentally omitting this element) will enable the
|
|
|
|
|
[Screen Compatibility Mode](http://www.androiddocs.com/guide/practices/screen-compat-mode.html),
|
|
|
|
|
which doesn't report events in coordinates that match underlying framebuffer
|
|
|
|
|
pixel size. That is not supported by @ref Platform::AndroidApplication since
|
|
|
|
|
there's [no reliable way](https://stackoverflow.com/q/17481341) to get the
|
|
|
|
|
actual size used for events in that case.
|
|
|
|
|
|
|
|
|
|
@anchor platforms-android-apps-manifest-screen-resize
|
|
|
|
|
|
|
|
|
|
The @cb{.xml} <activity … android:configChanges="orientation|screenSize"> @ce
|
|
|
|
|
attribute is needed in order to make the application properly receive a
|
|
|
|
|
viewport event. By default it's being outright killed and recreated when device
|
|
|
|
|
orientation changes for questionable "performance reasons". If you really want
|
|
|
|
|
to handle orientation changes that way, remove `screenSize` from the set.
|
|
|
|
|
Among other options is restricting the app to only portrait or landscape screen
|
|
|
|
|
orientation.
|
|
|
|
|
|
|
|
|
|
Consult [the Android developer documentation](https://developer.android.com/guide/topics/manifest/manifest-intro.html)
|
|
|
|
|
for further information about the manifest file.
|
|
|
|
|
|
|
|
|
|
With this set up, you have two options how to build the final APK, either using
|
|
|
|
|
plain CMake or using Gradle.
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-apps-cmake Using CMake
|
|
|
|
|
|
|
|
|
|
The `toolchains` repository contains an `UseAndroid.cmake` module that allows
|
|
|
|
|
you to create an APK in a significantly faster and simpler way than when using
|
|
|
|
|
Gradle.
|
|
|
|
|
|
|
|
|
|
@attention This feature is in an experimental stage and at this time it doesn't
|
|
|
|
|
support compilation of any resources (such as icons) or Java sources. It
|
|
|
|
|
also builds only the ABI and configuration that corresponds to the
|
|
|
|
|
particular CMake build directory. It's thus recommended to employ this
|
|
|
|
|
approach for fast iteration during development alongside the classic Gradle
|
|
|
|
|
build @ref platforms-android-apps-gradle "described below" that will get
|
|
|
|
|
used for the final release builds.
|
|
|
|
|
|
|
|
|
|
Download contents of the toolchains repository from https://github.com/mosra/toolchains
|
|
|
|
|
or add it as a Git submodule, add its module path to `CMAKE_MODULE_PATH` and
|
|
|
|
|
include the `UseAndroid` module. Wrapping it in a check for presence of
|
|
|
|
|
`CMAKE_ANDROID_NDK` will make it possible to have the pure CMake and a Gradle
|
|
|
|
|
build coexist --- because Gradle internally uses CMake 3.6 which doesn't know
|
|
|
|
|
about `CMAKE_ANDROID_NDK` yet.
|
|
|
|
|
|
|
|
|
|
@code{.cmake}
|
|
|
|
|
if(CORRADE_TARGET_ANDROID AND CMAKE_ANDROID_NDK)
|
|
|
|
|
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/toolchains/modules/")
|
|
|
|
|
include(UseAndroid)
|
|
|
|
|
endif()
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
On the first run, the macro will attempt to detect SDK location, Android Build
|
|
|
|
|
Tools version and Android Platfrom version and it prints them to the output
|
|
|
|
|
like this:
|
|
|
|
|
|
|
|
|
|
@code{.shell-session}
|
|
|
|
|
$ cmake .
|
|
|
|
|
…
|
|
|
|
|
-- ANDROID_SDK not set, detected /opt/android-sdk
|
|
|
|
|
-- ANDROID_BUILD_TOOLS_VERSION not set, detected 27.0.3
|
|
|
|
|
-- ANDROID_PLATFORM_VERSION not set, detected 27
|
|
|
|
|
…
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
If you don't like what it detected (or the detection failed), edit these values
|
|
|
|
|
in CMake cache. After that, pass your library target name and location of the
|
|
|
|
|
`AndroidManifest.xml` file to @cmake android_create_apk() @ce. Continuing from
|
|
|
|
|
the above:
|
|
|
|
|
|
|
|
|
|
@code{.cmake}
|
|
|
|
|
add_library(my-application SHARED MyApplication.cpp)
|
|
|
|
|
android_create_apk(my-application AndroidManifest.xml)
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Note that even thought it doesn't make any sense, the `aapt` tool *demands* the
|
|
|
|
|
manifest file to be called exactly `AndroidManifest.xml`. It can be, however,
|
|
|
|
|
in any location. This will create an APK named `my-application.apk` and
|
|
|
|
|
additionally also provide a new target, `my-application-deploy`, that will use
|
|
|
|
|
`adb install -r` to install the built APK on the device. Building and uploading
|
|
|
|
|
the application can be then done in a single step:
|
|
|
|
|
|
|
|
|
|
@code{.shell-session}
|
|
|
|
|
$ ninja my-application-deploy
|
|
|
|
|
[5/5] Installing my-application.apk
|
|
|
|
|
Success
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
(Or e.g. `cmake --build . --target my-application-deploy` if you don't use
|
|
|
|
|
Ninja.)
|
|
|
|
|
|
|
|
|
|
For full compatibility with the Gradle build wrap the call again in a check for
|
|
|
|
|
`CMAKE_ANDROID_NDK` and put the manifest in the `src/main` subdirectory, where
|
|
|
|
|
Gradle expects it:
|
|
|
|
|
|
|
|
|
|
@code{.cmake}
|
|
|
|
|
add_library(my-application SHARED MyApplication.cpp)
|
|
|
|
|
if(CMAKE_ANDROID_NDK)
|
|
|
|
|
android_create_apk(my-application src/main/AndroidManifest.xml)
|
|
|
|
|
endif()
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-apps-gradle Using Gradle
|
|
|
|
|
|
|
|
|
|
Besides plain CMake and Gradle it's also possible to use the classic
|
|
|
|
|
`ndk-build`. but that's the least recommended way and it might not be supported
|
|
|
|
|
in newer NDK builds. The following guide assumes you have Gradle installed in a
|
|
|
|
|
system-wide location available in @cb{.sh} $PATH @ce. See the
|
|
|
|
|
[Gradle installation docs](https://docs.gradle.org/current/userguide/installation.html)
|
|
|
|
|
for more information, @ref platforms-android-gradlew "see below" if you want to
|
|
|
|
|
use the `gradlew` wrappers instead.
|
|
|
|
|
|
|
|
|
|
Create a `build.gradle` file that references your root `CMakeLists.txt`.
|
|
|
|
|
Assuming it's saved right next to your root `CMakeLists.txt`, the most minimal
|
|
|
|
|
version might look like this:
|
|
|
|
|
|
|
|
|
|
@code{.gradle}
|
|
|
|
|
buildscript {
|
|
|
|
|
repositories {
|
|
|
|
|
jcenter()
|
|
|
|
|
google()
|
|
|
|
|
}
|
|
|
|
|
dependencies {
|
|
|
|
|
classpath 'com.android.tools.build:gradle:3.0.1'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
apply plugin: 'com.android.application'
|
|
|
|
|
|
|
|
|
|
android {
|
|
|
|
|
compileSdkVersion 25
|
|
|
|
|
|
|
|
|
|
defaultConfig {
|
|
|
|
|
minSdkVersion 22
|
|
|
|
|
|
|
|
|
|
externalNativeBuild {
|
|
|
|
|
cmake {
|
|
|
|
|
arguments '-DANDROID_STL=c++_static'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ndk {
|
|
|
|
|
abiFilters 'arm64-v8a'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
externalNativeBuild {
|
|
|
|
|
cmake {
|
|
|
|
|
path 'CMakeLists.txt'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Important things are @cb{.gradle} compileSdkVersion @ce and
|
|
|
|
|
@cb{.gradle} minSdkVersion @ce, which set SDK version that will be used to
|
|
|
|
|
compile the project and minimal SDK version that the app can run on. You can
|
|
|
|
|
add further CMake parameters in the @cb{.gradle} arguments @ce line (here it's
|
|
|
|
|
just requesting to use static libc++) and the @cb{.gradle} abiFilters @ce allow
|
|
|
|
|
you to restrict which ABIs will the project be built for --- Gradle by default
|
|
|
|
|
builds for both 32 and 64-bit ARM, MIPS and x86, which might be quite annoying
|
|
|
|
|
to wait for (during development at least). The @cb{.gradle} path @ce then
|
|
|
|
|
references your `CMakeLists.txt` file. Gradle by default bundles all shared
|
|
|
|
|
library targets defined in the CMake project, so there's no need to specify a
|
|
|
|
|
particular library name.
|
|
|
|
|
|
|
|
|
|
Gradle by default chooses Android SDK Build Tools version that corresponds to
|
|
|
|
|
the @cb{.gradle} compileSdkVersion @ce. If you want to have control (for
|
|
|
|
|
example to make it use Build Tools that you already have installed), specify
|
|
|
|
|
it using @cb{.gradle} buildToolsVersion @ce:
|
|
|
|
|
|
|
|
|
|
@code{.gradle}
|
|
|
|
|
android {
|
|
|
|
|
compileSdkVersion 27
|
|
|
|
|
buildToolsVersion '27.0.3'
|
|
|
|
|
...
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
The [official documentation](https://developer.android.com/studio/projects/gradle-external-native-builds.html#configure-gradle)
|
|
|
|
|
contains a more complete overview of all possibilities.
|
|
|
|
|
|
|
|
|
|
For the `AndroidManifest.xml` file, Gradle expects it to be placed inside the
|
|
|
|
|
`src/main` subdirectory, *not* straight besides the `build.gradle` file.
|
|
|
|
|
|
|
|
|
|
With everything set up, you are now ready to build the project by simply
|
|
|
|
|
executing the following from the directory with your `build.gradle`. During the
|
|
|
|
|
first run, Gradle will download a huge amount of random stuff when building
|
|
|
|
|
even the simplest thing. Close your eyes and ignore that it happened.
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
gradle build
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
You can also use @cb{.sh} gradle assembleDebug @ce which is slightly faster as
|
|
|
|
|
it doesn't build both Debug and Release and omits some unneeded checks.
|
|
|
|
|
Installing on a connected device or emulator is then a matter of
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
gradle installDebug
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
after which you can launch the app from your home screen. See the
|
|
|
|
|
@ref platforms-android-troubleshooting section below if you ran into problems.
|
|
|
|
|
|
|
|
|
|
@section platforms-android-multiple-abis Building for multiple ABIs and system versions
|
|
|
|
|
|
|
|
|
|
The above guide simplifies things a bit and builds for just a single ARM64 ABI.
|
|
|
|
|
In order to support multiple platforms, you need to separately build and
|
|
|
|
|
install the dependencies for all ABIs of choice --- create separate build
|
|
|
|
|
directories and run CMake with different `CMAKE_ANDROID_ARCH_ABI` and
|
|
|
|
|
corresponding `CMAKE_INSTALL_PREFIX`. Similarly with SDK versions, adapt
|
|
|
|
|
`CMAKE_SYSTEM_VERSION` and `CMAKE_INSTALL_PREFIX` to a desired version. The
|
|
|
|
|
headers are shared and should be always installed into `<ndk>/sysroot/usr`
|
|
|
|
|
regardless of ABI or SDK version. The supported ABI values are:
|
|
|
|
|
|
|
|
|
|
ABI | Corresponding install prefix
|
|
|
|
|
----------- | ----------------------------
|
|
|
|
|
armeabi-v7a | <nk>/platforms/android-<version>/arch-arm/usr
|
|
|
|
|
arm64-v8a | <nk>/platforms/android-<version>/arch-arm64/usr
|
|
|
|
|
x86 | <nk>/platforms/android-<version>/arch-x86/usr
|
|
|
|
|
x86_64 | <nk>/platforms/android-<version>/arch-x86_64/usr
|
|
|
|
|
|
|
|
|
|
After that, you can add the additional ABIs to the `abiFilters` list in your
|
|
|
|
|
`build.gradle`.
|
|
|
|
|
|
|
|
|
|
For example, building Magnum for 32-bit and 64-bit ARM with SDK version 24
|
|
|
|
|
could look like this:
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
mkdir build-android-arm && cd build-android-arm
|
|
|
|
|
cmake .. \
|
|
|
|
|
-DCMAKE_SYSTEM_NAME=Android \
|
|
|
|
|
-DCMAKE_SYSTEM_VERSION=24 \
|
|
|
|
|
-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a \
|
|
|
|
|
-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
|
|
|
|
|
-DCMAKE_ANDROID_STL_TYPE=c++_static \
|
|
|
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
|
|
|
-DCMAKE_INSTALL_PREFIX=<ndk>/platforms/android-24/arch-arm/usr \
|
|
|
|
|
-DMAGNUM_INCLUDE_INSTALL_PREFIX=<ndk>/sysroot/usr
|
|
|
|
|
cmake --build . --target install
|
|
|
|
|
|
|
|
|
|
cd ..
|
|
|
|
|
|
|
|
|
|
mkdir build-android-arm64 && cd build-android-arm64
|
|
|
|
|
cmake .. \
|
|
|
|
|
-DCMAKE_SYSTEM_NAME=Android \
|
|
|
|
|
-DCMAKE_SYSTEM_VERSION=24 \
|
|
|
|
|
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
|
|
|
|
|
-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
|
|
|
|
|
-DCMAKE_ANDROID_STL_TYPE=c++_static \
|
|
|
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
|
|
|
-DCMAKE_INSTALL_PREFIX=<ndk>/platforms/android-24/arch-arm64/usr \
|
|
|
|
|
-DMAGNUM_INCLUDE_INSTALL_PREFIX=<ndk>/sysroot/usr
|
|
|
|
|
cmake --build . --target install
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
The `build.gradle` for your app then looks like below.
|
|
|
|
|
|
|
|
|
|
@attention Building multiple ABIs is currently not supported with the CMake
|
|
|
|
|
@cmake android_create_apk() @ce macro, using Gradle is the only way.
|
|
|
|
|
|
|
|
|
|
@code{.gradle}
|
|
|
|
|
buildscript {
|
|
|
|
|
repositories {
|
|
|
|
|
jcenter()
|
|
|
|
|
google()
|
|
|
|
|
}
|
|
|
|
|
dependencies {
|
|
|
|
|
classpath 'com.android.tools.build:gradle:3.0.1'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
apply plugin: 'com.android.application'
|
|
|
|
|
|
|
|
|
|
android {
|
|
|
|
|
compileSdkVersion 25
|
|
|
|
|
|
|
|
|
|
defaultConfig {
|
|
|
|
|
minSdkVersion 24
|
|
|
|
|
|
|
|
|
|
externalNativeBuild {
|
|
|
|
|
cmake {
|
|
|
|
|
arguments '-DANDROID_STL=c++_static'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ndk {
|
|
|
|
|
abiFilters 'armeabi-v7a', 'arm64-v8a'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
externalNativeBuild {
|
|
|
|
|
cmake {
|
|
|
|
|
path 'CMakeLists.txt'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
See [the official documentation about ABIs](https://developer.android.com/ndk/guides/abis.html)
|
|
|
|
|
for more information.
|
|
|
|
|
|
|
|
|
|
@section platforms-android-output-redirection Redirecting output to Android log buffer
|
|
|
|
|
|
|
|
|
|
While printing to standard output and standard error output "just works" with
|
|
|
|
|
command-line apps, you might want to redirect your @ref Corrade::Utility::Debug "Debug",
|
|
|
|
|
@ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error"
|
|
|
|
|
output to Android log buffer. so it can be accessed through the @cb{.sh} adb logcat @ce
|
|
|
|
|
utility. See @ref Corrade::Utility::AndroidLogStreamBuffer for more
|
|
|
|
|
information.
|
|
|
|
|
|
|
|
|
|
The @ref Platform::AndroidApplication sets this up implicitly with a `magnum`
|
|
|
|
|
tag, you can then filter it out like this, for example:
|
|
|
|
|
|
|
|
|
|
@code{.shell-session}
|
|
|
|
|
$ adb logcat *:S magnum
|
|
|
|
|
...
|
|
|
|
|
03-16 17:35:26.703 17726 17745 I magnum : Renderer: Mali-G71 by ARM
|
|
|
|
|
03-16 17:35:26.703 17726 17745 I magnum : OpenGL version: OpenGL ES 3.2 v1.r2p0
|
|
|
|
|
03-16 17:35:26.703 17726 17745 I magnum : Using optional features:
|
|
|
|
|
03-16 17:35:26.703 17726 17745 I magnum : GL_EXT_robustness
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@section platforms-android-system-cmake Using system-wide CMake installation
|
|
|
|
|
|
|
|
|
|
According to the [official documentation](https://developer.android.com/studio/projects/add-native-code.html#vanilla_cmake),
|
|
|
|
|
it's possible to use system CMake installation without needing to install
|
|
|
|
|
Android SDK version of CMake 3.6. Simply update the
|
|
|
|
|
@cb{.gradle} externalNativeBuild @ce in your `build.gradle` file to specify
|
|
|
|
|
CMake version that you have installed in your system, for example:
|
|
|
|
|
|
|
|
|
|
@code{.gradle}
|
|
|
|
|
android {
|
|
|
|
|
...
|
|
|
|
|
externalNativeBuild {
|
|
|
|
|
cmake {
|
|
|
|
|
path 'CMakeLists.txt'
|
|
|
|
|
...
|
|
|
|
|
version '3.10.2'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
However, be aware that this is an experimental feature and may be broken. At
|
|
|
|
|
the time of writing (March 2018), it didn't work for me with NDK r16b, Android
|
|
|
|
|
buid plugin 3.0.1 and CMake 3.10.
|
|
|
|
|
|
|
|
|
|
@section platforms-android-gradlew Using gradlew wrappers instead of a system installation
|
|
|
|
|
|
|
|
|
|
It's possible to bundle Gradle in the project itself as opposed to requiring a
|
|
|
|
|
pre-existing system installation. It has the downside of having a bit more
|
|
|
|
|
boilerplate files in your project, though.
|
|
|
|
|
|
|
|
|
|
First, add the following to your `build.gradle` file:
|
|
|
|
|
|
|
|
|
|
@code{.gradle}
|
|
|
|
|
task wrapper(type: Wrapper) {
|
|
|
|
|
gradleVersion = '4.0'
|
|
|
|
|
}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Then run this on a system that has Gradle installed:
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
gradle wrapper
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
This will generate the following files that you can then add to version
|
|
|
|
|
control:
|
|
|
|
|
|
|
|
|
|
- `gradlew` shell script for Unix-like systems
|
|
|
|
|
- `gradle.bat` batch script for Windows
|
|
|
|
|
- `gradle/` directory with wrapper binaries
|
|
|
|
|
|
|
|
|
|
With this in place, you can just use @cb{.sh} gradlew @ce instead of
|
|
|
|
|
@cb{.sh} gradle @ce.
|
|
|
|
|
|
|
|
|
|
@section platforms-android-travis Setting up Android build on Travis CI
|
|
|
|
|
|
|
|
|
|
For simple compilation tests, add the following to your `.travis.yml` matrix
|
|
|
|
|
builds. According to the [Travis Android documentation](https://docs.travis-ci.com/user/languages/android/),
|
|
|
|
|
`build-tools-22.0.1` and `android-22` are always present, so your builds
|
|
|
|
|
shouldn't get any extra delay when requesting them. The @cb{.sh} $TARGET @ce
|
|
|
|
|
environment variable is used here only to disambiguate later, you might or
|
|
|
|
|
might not need it.
|
|
|
|
|
|
|
|
|
|
@code{.yml}
|
|
|
|
|
matrix:
|
|
|
|
|
include:
|
|
|
|
|
# ...
|
|
|
|
|
- language: android
|
|
|
|
|
os: linux
|
|
|
|
|
dist: trusty
|
|
|
|
|
env:
|
|
|
|
|
- TARGET=android
|
|
|
|
|
android:
|
|
|
|
|
components:
|
|
|
|
|
- build-tools-22.0.1
|
|
|
|
|
- android-22
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
At the time of writing (March 2018), while the generic Ubuntu 14.04 images
|
|
|
|
|
already have CMake 3.9.2, for some reason the Android Ubuntu 14.04 images have
|
|
|
|
|
just CMake 3.2. Android support is builtin since version 3.7, but
|
|
|
|
|
[an important fix](https://gitlab.kitware.com/cmake/cmake/issues/17253) for the
|
|
|
|
|
LLVM toolchain was merged as late as in 3.9.2, so you may want to grab that
|
|
|
|
|
version. Example `.travis.yml` setup that downloads the binary and extracts it
|
|
|
|
|
to @cb{.sh} $HOME/cmake @ce, with @cb{.sh} $PATH @ce setup and caching:
|
|
|
|
|
|
|
|
|
|
@code{.yml}
|
|
|
|
|
cache:
|
|
|
|
|
directories:
|
|
|
|
|
- $HOME/cmake
|
|
|
|
|
|
|
|
|
|
install:
|
|
|
|
|
- >
|
|
|
|
|
if [ "$TARGET" == "android" ] && [ ! -e "$HOME/cmake/bin" ]; then
|
|
|
|
|
cd $HOME ;
|
|
|
|
|
wget https://cmake.org/files/v3.9/cmake-3.9.2-Linux-x86_64.tar.gz &&
|
|
|
|
|
mkdir -p cmake &&
|
|
|
|
|
cd cmake &&
|
|
|
|
|
tar --strip-components=1 -xzf ../cmake-3.9.2-Linux-x86_64.tar.gz &&
|
|
|
|
|
cd $TRAVIS_BUILD_DIR ;
|
|
|
|
|
fi
|
|
|
|
|
- >
|
|
|
|
|
if [ "$TARGET" == "android" ]; then
|
|
|
|
|
export PATH=$HOME/cmake/bin:$PATH &&
|
|
|
|
|
cmake --version ;
|
|
|
|
|
fi
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
The NDK can be fetched as a simple `*.zip` file. However, version r16b has over
|
|
|
|
|
800 MB, so you might want to explore creation of a
|
|
|
|
|
[Standalone Toolchain](https://developer.android.com/ndk/guides/standalone_toolchain.html)
|
|
|
|
|
with only the things you need to speed up the build. Again, downlading it into
|
|
|
|
|
@cb{.sh} $HOME/android-ndk-r16b @ce is a matter of adding this into your
|
|
|
|
|
@cb{.yml} install: @ce section:
|
|
|
|
|
|
|
|
|
|
@code{.yml}
|
|
|
|
|
- >
|
|
|
|
|
if [ "$TARGET" == "android" ]; then
|
|
|
|
|
cd $HOME ;
|
|
|
|
|
wget https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip &&
|
|
|
|
|
unzip -q android-*.zip &&
|
|
|
|
|
cd $TRAVIS_BUILD_DIR ;
|
|
|
|
|
fi
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Travis CI discourages caching the NDK, as downloading the cache will take
|
|
|
|
|
roughly the same amount of time as downloading it from upstream.
|
|
|
|
|
|
|
|
|
|
Building your actual code is just a matter of setting up a correct NDK path.
|
|
|
|
|
You can install the dependencies to any location as long as you specify the
|
|
|
|
|
same location in `CMAKE_PREFIX_PATH` and `CMAKE_FIND_ROOT_PATH` in depending
|
|
|
|
|
projects. Using `armeabi-v7a` instead of `arm64-v8a` ensures that you can run
|
|
|
|
|
the code in a preinstalled emulator later, see below.
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
mkdir build-android-arm && cd build-android-arm
|
|
|
|
|
cmake .. \
|
|
|
|
|
-DCMAKE_ANDROID_NDK=$HOME/android-ndk-r16b \
|
|
|
|
|
-DCMAKE_SYSTEM_NAME=Android \
|
|
|
|
|
-DCMAKE_SYSTEM_VERSION=22 \
|
|
|
|
|
-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a \
|
|
|
|
|
-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
|
|
|
|
|
-DCMAKE_ANDROID_STL_TYPE=c++_static \
|
|
|
|
|
-DCMAKE_PREFIX_PATH=$HOME/deps \
|
|
|
|
|
-DCMAKE_FIND_ROOT_PATH=$HOME/deps \
|
|
|
|
|
...
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-travis-run Running tests on the emulator
|
|
|
|
|
|
|
|
|
|
In order to run your tests on the emulator, you need to request some system
|
|
|
|
|
image. Again, `sys-img-armeabi-v7a-android-22` is part of the default
|
|
|
|
|
installation, so it shouldn't add any extra time to your build:
|
|
|
|
|
|
|
|
|
|
@code{.yml}
|
|
|
|
|
matrix:
|
|
|
|
|
include:
|
|
|
|
|
- language: android
|
|
|
|
|
# ...
|
|
|
|
|
android:
|
|
|
|
|
components:
|
|
|
|
|
# ...
|
|
|
|
|
- sys-img-armeabi-v7a-android-22
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
As described [in the Travis documentation](https://docs.travis-ci.com/user/languages/android/#How-to-Create-and-Start-an-Emulator),
|
|
|
|
|
create a system image and wait for the emulator to start (be prepared, it can
|
|
|
|
|
easily take up *minutes*). Assuming you use
|
|
|
|
|
the @ref TestSuite-Tester-running-cmake "Corrade::TestSuite Android integration",
|
|
|
|
|
simply run your tests via `ctest` and optionally enable colored output for
|
|
|
|
|
extra clarity:
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
|
|
|
|
|
emulator -avd test -no-audio -no-window &
|
|
|
|
|
android-wait-for-emulator
|
|
|
|
|
CORRADE_TEST_COLOR=ON ctest -V
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-travis-bundle APK bundle creation
|
|
|
|
|
|
|
|
|
|
At the time of writing (March 2018), Travis Ubuntu 14.04 has Gradle 4.0,
|
|
|
|
|
however the Android build plugin 3.0 requires at least Gradle 4.1, so you need
|
|
|
|
|
to backport `gradle.build` to plugin version 2.3.3 compared to the
|
|
|
|
|
@ref platforms-android-apps "template above". In particular, the `classpath`
|
|
|
|
|
needs to be updated, `compileSdkVersion` and `minSdkVersion` adapted to
|
|
|
|
|
versions defined in @cb{.yml} components: @ce in your `travis.yml` file and the
|
|
|
|
|
`buildToolsVersion` explicitly specified, because that's needed in plugin
|
|
|
|
|
versions before 3.0:
|
|
|
|
|
|
|
|
|
|
@code{.gradle}
|
|
|
|
|
buildscript {
|
|
|
|
|
// ...
|
|
|
|
|
dependencies {
|
|
|
|
|
classpath 'com.android.tools.build:gradle:2.3.3'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
|
|
android {
|
|
|
|
|
compileSdkVersion 22
|
|
|
|
|
buildToolsVersion '26.0.2'
|
|
|
|
|
|
|
|
|
|
defaultConfig {
|
|
|
|
|
minSdkVersion 22
|
|
|
|
|
// ...
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Gradle bundles its own CMake 3.6, downloading it on-demand and then failing
|
|
|
|
|
because SDK licenses are not signed. Solution is to install CMake and sign its
|
|
|
|
|
license explicitly beforehand. Add the following to your `.travis.yml`:
|
|
|
|
|
|
|
|
|
|
@code{.yml}
|
|
|
|
|
before_install:
|
|
|
|
|
- if [ "$TARGET" == "android" ]; then yes | sdkmanager "cmake;3.6.4111459"; fi
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Unlike above, and especially if you build for multiple ABIs, it's better to
|
|
|
|
|
install all dependencies where Gradle expects them. In particular, in case of
|
|
|
|
|
Corrade and ARM64 ABI and NDK being in @cb{.sh} $HOME/android-ndk-r16b @ce, the
|
|
|
|
|
install prefixes look like this:
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
cmake .. \
|
|
|
|
|
-DCMAKE_INSTALL_PREFIX=$HOME/android-ndk-r16b/platforms/android-22/arch-arm64/usr \
|
|
|
|
|
-DCORRADE_INCLUDE_INSTALL_PREFIX=$HOME/android-ndk-r16b/sysroot/usr \
|
|
|
|
|
...
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Finally, you need to tell Gradle where the NDK is located and where to look for
|
|
|
|
|
native binaries (for example the `corrade-rc` executable) using environment
|
|
|
|
|
variables. At last, execute `gradle build` in the directory where
|
|
|
|
|
`build.gradle` is:
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
export ANDROID_NDK_HOME=$HOME/android-ndk-r16b
|
|
|
|
|
export CMAKE_PREFIX_PATH=$HOME/deps-native/
|
|
|
|
|
|
|
|
|
|
gradle build
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@section platforms-android-troubleshooting Troubleshooting
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-troubleshooting-multiple-devices ADB fails when more devices are connected
|
|
|
|
|
|
|
|
|
|
If any `adb` command fails with
|
|
|
|
|
|
|
|
|
|
@code{.shell-session}
|
|
|
|
|
error: more than one device/emulator
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@m_class{m-noindent}
|
|
|
|
|
|
|
|
|
|
you can pass the device ID via the `-s` parameter to each command. That is,
|
|
|
|
|
however, verbose and doesn't work for example in case of running
|
|
|
|
|
@ref Corrade::TestSuite tests via `ctest`. Instead, it's possible to supply
|
|
|
|
|
the device ID via an environment variable, for example:
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
export ANDROID_SERIAL="bla"
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-troubleshooting-signing-failed Signing the APK using CMake fails
|
|
|
|
|
|
|
|
|
|
At the moment the location and passphrase for the Android signing keystore is
|
|
|
|
|
implicitly set to @cb{.sh} $HOME/.android/debug.keystore @ce with `android` as
|
|
|
|
|
a password, since that's the location (and password) that Gradle uses. If you
|
|
|
|
|
see output similar to this:
|
|
|
|
|
|
|
|
|
|
@code{.shell-session}
|
|
|
|
|
[1/2] Signing my-application.apk
|
|
|
|
|
FAILED: my-application.apk
|
|
|
|
|
…
|
|
|
|
|
Failed to load signer "signer #1"
|
|
|
|
|
java.io.FileNotFoundException: <home>/.android/debug.keystore
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
then you either don't have the keystore generated yet or it's in some other
|
|
|
|
|
location. Similar error can happen if the password is incrrect, in which case
|
|
|
|
|
it will say the following instead:
|
|
|
|
|
|
|
|
|
|
@code{.shell-session}
|
|
|
|
|
Failed to load signer "signer #1"
|
|
|
|
|
java.io.IOException: Keystore was tampered with, or password was incorrect
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Generating a debug keystore can be done by running through the Gradle build at
|
|
|
|
|
least once. It's also possible to create a keystore
|
|
|
|
|
[using Android Studio](https://developer.android.com/studio/publish/app-signing#generate-key)
|
|
|
|
|
or using the `keytool` utility that's bundled with Java SDK. The following
|
|
|
|
|
creates a key equivalent to the Gradle-generated one, adapt the location as
|
|
|
|
|
necessary:
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
keytool -genkeypair -keystore $HOME/.android/debug.keystore \
|
|
|
|
|
-storepass android -alias androiddebugkey -keypass android \
|
|
|
|
|
-keyalg RSA -validity 10000 -dname CN=,OU=,O=,L=,S=,C=
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
The location and password is controlled via the `ANDROID_APKSIGNER_KEY`
|
|
|
|
|
variable, edit your CMake cache to point it to a different location or
|
|
|
|
|
password. Note that the command parameters have to be delimited by `;` instead
|
|
|
|
|
of a space. For example, setting the location to `/etc/android.keystore` with a
|
|
|
|
|
password `secret` can be done like this:
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
cmake . -DANDROID_APKSIGNER_KEY="--ks;/etc/android.keystore;--ks-pass;pass:secret"
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
You can also add further arguments to `apksigner` here. See the
|
|
|
|
|
[official documentaton for apksigner](https://developer.android.com/studio/command-line/apksigner)
|
|
|
|
|
for details.
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-troubleshooting-cant-find Gradle CMake can't find dependencies
|
|
|
|
|
|
|
|
|
|
Gradle by default searches only in the NDK install path. If you have your
|
|
|
|
|
dependencies installed somewhere else (this goes especially for the *native*
|
|
|
|
|
`corrade-rc` executable), you might want to point the `CMAKE_PREFIX_PATH`
|
|
|
|
|
environment variable to your install location:
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
export CMAKE_PREFIX_PATH=<path-where-your-dependencies-are-installed>
|
|
|
|
|
gradle build
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
If you have the dependencies installed in the NDK path, but it still fails,
|
|
|
|
|
check that you installed for the same SDK version as in `minSdkVersion` and all
|
|
|
|
|
ABIs mentioned in `abiFilters` inside your `build.gradle` file --- Gradle runs
|
|
|
|
|
CMake once for each entry in the list so it might happen that it finds them for
|
|
|
|
|
all but one ABI. See @ref platforms-android-multiple-abis above for more
|
|
|
|
|
information.
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-troubleshooting-cant-launch App can't launch
|
|
|
|
|
|
|
|
|
|
If your application can't launch (or it just blinks and then disappears), you
|
|
|
|
|
can inspect @cb{.sh} adb logcat @ce output to see what went wrong, but be
|
|
|
|
|
quick, the log is spitting out a lot of info all the time. Possible causes:
|
|
|
|
|
|
|
|
|
|
- Mismatch between actual library name and library referenced from
|
|
|
|
|
`AndroidManifest.xml`, causing Java to fail loading it
|
|
|
|
|
- The device has an ABI for which the app was not compiled (check the
|
|
|
|
|
@cb{.gradle} abiFilters @ce option in `build.gradle`) or the app was
|
|
|
|
|
compiled with SDK version that's not supported by the device yet. See the
|
|
|
|
|
[official API level documentation](https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels)
|
|
|
|
|
for more information.
|
|
|
|
|
- The device doesn't support OpenGL ES 3.0 yet. Rebuild Magnum and its
|
|
|
|
|
dependencies with the `TARGET_GLES2` option enabled. See @ref building-features
|
|
|
|
|
for more information.
|
|
|
|
|
- Loading fails with `ANativeActivity_onCreate` symbol not being found. If
|
|
|
|
|
you are using @ref Platform::AndroidApplication, this issue should be
|
|
|
|
|
prevented, otherwise you need to add `-u ANativeActivity_onCreate` to your
|
|
|
|
|
linker flags or reference the symbol some other way. See
|
|
|
|
|
[android-ndk/ndk#381](https://github.com/android-ndk/ndk/issues/381) for
|
|
|
|
|
details.
|
|
|
|
|
- Additional `*.so` libraries are referenced by the main `*.so` but not
|
|
|
|
|
bundled in the `*.apk`. One option is to switch to static libraries,
|
|
|
|
|
another is explicitly specifying them in the `build.gradle` file. See
|
|
|
|
|
[the official documentation](https://developer.android.com/studio/projects/gradle-external-native-builds.html#jniLibs)
|
|
|
|
|
for details.
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-troubleshooting-java8 Gradle aborting due to too new Java
|
|
|
|
|
|
|
|
|
|
If you see one of the following outputs, it might be that you're using Java 9
|
|
|
|
|
or 10, which is not supported by Android build tools yet:
|
|
|
|
|
|
|
|
|
|
@code{.shell-session}
|
|
|
|
|
$ gradle build
|
|
|
|
|
|
|
|
|
|
FAILURE: Build failed with an exception.
|
|
|
|
|
|
|
|
|
|
* What went wrong:
|
|
|
|
|
…
|
|
|
|
|
> Failed to notify project evaluation listener.
|
|
|
|
|
> javax/xml/bind/annotation/XmlSchema
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@code{.shell-session}
|
|
|
|
|
$ gradle build
|
|
|
|
|
|
|
|
|
|
FAILURE: Build failed with an exception.
|
|
|
|
|
|
|
|
|
|
* What went wrong:
|
|
|
|
|
…
|
|
|
|
|
> Failed to notify project evaluation listener.
|
|
|
|
|
> Could not initialize class com.android.sdklib.repository.AndroidSdkHandler
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Solution is to point @cb{.sh} $JAVA_HOME @ce to a Java 8 installation, for
|
|
|
|
|
example. This affects not just `gradle`, but also other tools like `sdkmanager`
|
|
|
|
|
(see @ref platforms-android-troubleshooting-licenses "below"), so you may want
|
|
|
|
|
to export it for the whole session:
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk/
|
|
|
|
|
gradle build
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
On ArchLinux, Java 8 is provided by the [jdk8-openjdk](https://www.archlinux.org/packages/extra/x86_64/jdk8-openjdk/)
|
|
|
|
|
package, which is pulled in as a dependency of the `android-sdk` and `gradle`
|
|
|
|
|
packages.
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-troubleshooting-term Gradle aborting due to termcap
|
|
|
|
|
|
|
|
|
|
If you see the following output, Gradle is crashing because @cb{.sh} $TERM @ce
|
|
|
|
|
is set to `xterm-256color` or `xterm-24`:
|
|
|
|
|
|
|
|
|
|
@code{.shell-session}
|
|
|
|
|
$ gradle build
|
|
|
|
|
|
|
|
|
|
FAILURE: Build failed with an exception.
|
|
|
|
|
|
|
|
|
|
* What went wrong:
|
|
|
|
|
Could not open terminal for stdout: could not get termcap entry
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Solution is to set @cb{.sh} TERM=xterm @ce. See
|
|
|
|
|
[gradle/gradle#4440](https://github.com/gradle/gradle/issues/4440) for more
|
|
|
|
|
information.
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
TERM=xterm gradle build
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-troubleshooting-licenses Accepting SDK licenses for Gradle
|
|
|
|
|
|
|
|
|
|
Gradle might refuse to build a project if SDK licenses are not accepted.
|
|
|
|
|
Depending on where your SDKs are installed, you might need to execute the
|
|
|
|
|
following (assuming you have SDK version 26 at least):
|
|
|
|
|
|
|
|
|
|
@code{.sh}
|
|
|
|
|
sdkmanager --licenses # and then manually accept all of them
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
The tool doesn't provide any diagnostic output if the accepting failed, so be
|
|
|
|
|
sure to verify that everything went well by executing @cb{.sh} sdkmanager --licenses @ce
|
|
|
|
|
again. If it offers the same licenses again, you might want to force it with
|
|
|
|
|
@cb{.sh} sudo @ce.
|
|
|
|
|
|
|
|
|
|
If the tool blows up with the following error, it's again because the Java
|
|
|
|
|
version is too new, see @ref platforms-android-troubleshooting-java8 "above"
|
|
|
|
|
for a solution:
|
|
|
|
|
|
|
|
|
|
@code{.shell-session}
|
|
|
|
|
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
|
|
|
|
|
at com.android.repository.api.SchemaModule$SchemaModuleVersion.<init>(SchemaModule.java:156)
|
|
|
|
|
…
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@subsection platforms-android-troubleshooting-permissions Android SDK directory permissions
|
|
|
|
|
|
|
|
|
|
Gradle is able to work with system-installed Android SDK. If it complains about
|
|
|
|
|
directory permissions such as
|
|
|
|
|
|
|
|
|
|
@code{.shell-session}
|
|
|
|
|
> Failed to install the following SDK components:
|
|
|
|
|
[Android SDK Build-Tools 26.0.2, Android SDK Platform 25]
|
|
|
|
|
The SDK directory (/opt/android-sdk) is not writeable,
|
|
|
|
|
please update the directory permissions.
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
it's often enough to just install such packages. In case of ArchLinux, all
|
|
|
|
|
relevant packages are available in AUR. For the above error in particular, the
|
|
|
|
|
matching packages are [android-sdk-build-tools-26.0.2](https://aur.archlinux.org/packages/android-sdk-build-tools-26.0.2/)
|
|
|
|
|
and [android-platform-25](https://aur.archlinux.org/packages/android-platform-25/).
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
}
|