Magnum::Platform::AndroidApplication class

Android application.

Application running on Android. Available only on Android, see respective sections in the Corrade and Magnum building documentation.

Bootstrap application

Fully contained base application using Sdl2Application for desktop build and AndroidApplication for Android build along with full Android packaging stuff and CMake setup is available in base-android branch of Magnum Bootstrap repository, download it as tar.gz or zip file. After extracting the downloaded archive, you can do the desktop build in the same way as with Sdl2Application.

In order to build the application, you need Gradle and Android build of Corrade and Magnum. Gradle is usually able to download all SDK dependencies on its own and then you can just build and install the app on a connected device or emulator like this:

gradle build
gradle installDebug

Detailed information about deployment for Android and all needed boilerplate together with a troubleshooting guide is available in Android.

General usage

This application library is built if MAGNUM_WITH_ANDROIDAPPLICATION is enabled when building Magnum. To use this library with CMake, request the AndroidApplication component of the Magnum package and link to the Magnum::AndroidApplication target:

find_package(Magnum REQUIRED)
if(CORRADE_TARGET_ANDROID)
    find_package(Magnum REQUIRED AndroidApplication)
endif()

# ...
if(CORRADE_TARGET_ANDROID)
    target_link_libraries(your-app PRIVATE Magnum::AndroidApplication)
endif()

Additionally, if you're using Magnum as a CMake subproject, do the following before calling find_package() to ensure it's enabled, as the library is not built by default:

set(MAGNUM_WITH_ANDROIDAPPLICATION ON CACHE BOOL "" FORCE)
add_subdirectory(magnum EXCLUDE_FROM_ALL)

If no other application is requested, you can also use the generic Magnum::Application alias to simplify porting. Again, see Downloading and building and Usage with CMake for more information. Note that unlike on other platforms you need to create a shared library instead of an executable:

if(NOT CORRADE_TARGET_ANDROID)
    add_executable(your-app ...)
else()
    add_library(your-app SHARED ...)
endif()

In C++ code you need to implement at least drawEvent() to be able to draw on the screen. The subclass must be then made accessible from JNI using MAGNUM_ANDROIDAPPLICATION_MAIN() macro. See Platform support for more information.

class MyApplication: public Platform::AndroidApplication {
    // implement required methods...
};
MAGNUM_ANDROIDAPPLICATION_MAIN(MyApplication)

If no other application header is included, this class is also aliased to Platform::Application and the macro is aliased to MAGNUM_APPLICATION_MAIN() to simplify porting.

Responding to viewport events

Unlike in desktop application implementations, where this is controlled via Sdl2Application::Configuration::WindowFlag::Resizable, for example, on Android you have to describe this in the AndroidManifest.xml file, as by default the application gets killed and relaunched on screen orientation change. See the manifest file docs for more information.

Redirecting output to Android log buffer

The application by default redirects Debug, Warning and Error output to Android log buffer with tag "magnum", which can be then accessed through logcat utility. See also Corrade::Utility::AndroidLogStreamBuffer for more information.

Touch input on Android

The application recognizes touch and pen input and reports it as Pointer::Finger, Pointer::Pen, Pointer::Eraser with PointerEventSource::Touch and PointerEventSource::Pen.

In case of a multi-touch scenario, PointerEvent::isPrimary() / PointerMoveEvent::isPrimary() can be used to distinguish the primary touch from secondary. For example, if an application doesn't need to recognize gestures like pinch to zoom or rotate, it can ignore all non-primary pointer events. PointerEventSource::Mouse and PointerEventSource::Pen events are always marked as primary, for touch input the first pressed finger is marked as primary and all following pressed fingers are non-primary. Note that there can be up to one primary pointer for each pointer event source, e.g. a finger, pen and a mouse press may all be marked as primary. On the other hand, in a multi-touch scenario, if the first (and thus primary) finger is lifted, no other finger becomes primary until all others are lifted as well. This is consistent with the logic in Sdl2Application and EmscriptenApplication but may not necessarily match what other Android applications do.

If gesture recognition is desirable, PointerEvent::id() / PointerMoveEvent::id() contains a pointer ID that's unique among all pointer event sources, which can be used to track movements of secondary, tertiary and further touch points. The ID allocation isn't defined and you can't rely on it to be contiguous or in any bounded range — for example, each new touch may generate a new ID that's only used until given finger is lifted, and then never again, or the IDs may get heavily reused, being unique only for the period given finger is pressed. For PointerEventSource::Mouse and PointerEventSource::Pen the ID is a constant, as there's always just a single mouse cursor or a pen stylus.

See also Handling mouse, touch and pen events for general information about handling pointer input in a portable way. There's also a Platform::TwoFingerGesture helper for recognition of common two-finger gestures for zoom, rotation and pan.

Public types

class Configuration
Configuration.
class GLConfiguration
OpenGL context configuration.
class InputEvent
Base for input events.
class MouseEvent deprecated in Git master
Mouse event.
class MouseMoveEvent deprecated in Git master
Mouse move event.
class PointerEvent new in Git master
Pointer event.
class PointerMoveEvent new in Git master
Pointer move event.
class ViewportEvent
Viewport event.
enum class PointerEventSource: UnsignedByte { Unknown, Mouse, Touch, Pen } new in Git master
Pointer event source.
enum class Pointer: UnsignedByte { Unknown = 1 << 0, MouseLeft = 1 << 1, MouseMiddle = 1 << 2, MouseRight = 1 << 3, Finger = 1 << 4, Pen = 1 << 5, Eraser = 1 << 6 } new in Git master
Pointer type.
using Arguments = android_app*
Application arguments.
using Pointers = Containers::EnumSet<Pointer> new in Git master
Set of pointer types.

Public static functions

static void exec(android_app* state, Containers::Pointer<AndroidApplication>(*)(const Arguments&) instancer)
Execute the application.

Constructors, destructors, conversion operators

AndroidApplication(const Arguments& arguments, const Configuration& configuration, const GLConfiguration& glConfiguration) explicit
Construct with an OpenGL context.
AndroidApplication(const Arguments& arguments, const Configuration& configuration = Configuration{}) explicit
Construct without explicit GPU context configuration.
AndroidApplication(const Arguments& arguments, NoCreateT) explicit
Construct without creating a window.
AndroidApplication(const AndroidApplication&) deleted
Copying is not allowed.
AndroidApplication(AndroidApplication&&) deleted
Moving is not allowed.

Public functions

auto operator=(const AndroidApplication&) -> AndroidApplication& deleted
Copying is not allowed.
auto operator=(AndroidApplication&&) -> AndroidApplication& deleted
Moving is not allowed.
auto nativeActivity() -> ANativeActivity*
Underlying native activity handle.

Protected functions

void create(const Configuration& configuration, const GLConfiguration& glConfiguration)
Create a window with given configuration for OpenGL context.
void create(const Configuration& configuration)
Create a window with given configuration and OpenGL context.
void create()
Create a window with default configuration and OpenGL context.
auto tryCreate(const Configuration& configuration, const GLConfiguration& glConfiguration) -> bool
Try to create context with given configuration for OpenGL context.
auto tryCreate(const Configuration& configuration) -> bool
Try to create context with given configuration and OpenGL context.

Screen handling

auto windowSize() const -> Vector2i
Window size.
auto framebufferSize() const -> Vector2i
Framebuffer size.
auto dpiScaling() const -> Vector2
DPI scaling.
auto dpiScaling(const Configuration& configuration) const -> Vector2
DPI scaling for given configuration.
void swapBuffers()
Swap buffers.
void redraw()
Redraw immediately.
void viewportEvent(ViewportEvent& event) private virtual
Viewport event.
void drawEvent() private pure virtual
Draw event.

Pointer handling

void pointerPressEvent(PointerEvent& event) private virtual new in Git master
Pointer press event.
void mousePressEvent(MouseEvent& event) deprecated in Git master private virtual
Mouse press event.
void pointerReleaseEvent(PointerEvent& event) private virtual new in Git master
Pointer release event.
void mouseReleaseEvent(MouseEvent& event) deprecated in Git master private virtual
Mouse release event.
void pointerMoveEvent(PointerMoveEvent& event) private virtual new in Git master
Pointer move event.
void mouseMoveEvent(MouseMoveEvent& event) deprecated in Git master private virtual
Mouse move event.

Enum documentation

enum class Magnum::Platform::AndroidApplication::PointerEventSource: UnsignedByte new in Git master

Pointer event source.

Enumerators
Unknown

The event source is unknown. Corresponds to AMOTION_EVENT_TOOL_TYPE_UNKNOWN and other types not listed below.

Mouse

The event is coming from a mouse. Corresponds to AMOTION_EVENT_TOOL_TYPE_MOUSE.

Touch

The event is coming from a touch contact, Corresponds to AMOTION_EVENT_TOOL_TYPE_FINGER.

Pen

The event is coming from a pen stylus. Corresponds to AMOTION_EVENT_TOOL_TYPE_STYLUS and AMOTION_EVENT_TOOL_TYPE_ERASER.

enum class Magnum::Platform::AndroidApplication::Pointer: UnsignedByte new in Git master

Pointer type.

Enumerators
Unknown

Unknown. Corresponds to AMOTION_EVENT_TOOL_TYPE_UNKNOWN and other types not listed below.

MouseLeft

Left mouse button. Corresponds to AMOTION_EVENT_TOOL_TYPE_MOUSE and AMOTION_EVENT_BUTTON_PRIMARY.

MouseMiddle

Middle mouse button. Corresponds to AMOTION_EVENT_TOOL_TYPE_MOUSE and AMOTION_EVENT_BUTTON_SECONDARY.

MouseRight

Right mouse button. Corresponds to AMOTION_EVENT_TOOL_TYPE_MOUSE and AMOTION_EVENT_BUTTON_TERTIARY.

Finger

Finger. Corresponds to AMOTION_EVENT_TOOL_TYPE_FINGER.

Pen

Pen. Corresponds to AMOTION_EVENT_TOOL_TYPE_STYLUS.

Eraser

Eraser. Corresponds to AMOTION_EVENT_TOOL_TYPE_ERASER.

Typedef documentation

typedef Containers::EnumSet<Pointer> Magnum::Platform::AndroidApplication::Pointers new in Git master

Set of pointer types.

Function documentation

static void Magnum::Platform::AndroidApplication::exec(android_app* state, Containers::Pointer<AndroidApplication>(*)(const Arguments&) instancer)

Execute the application.

See MAGNUM_ANDROIDAPPLICATION_MAIN() for usage information.

Magnum::Platform::AndroidApplication::AndroidApplication(const Arguments& arguments, const Configuration& configuration, const GLConfiguration& glConfiguration) explicit

Construct with an OpenGL context.

Parameters
arguments Application arguments
configuration Application configuration
glConfiguration OpenGL context configuration

Creates application with default or user-specified configuration. See Configuration for more information. The program exits if the context cannot be created, see tryCreate() for an alternative.

Magnum::Platform::AndroidApplication::AndroidApplication(const Arguments& arguments, const Configuration& configuration = Configuration{}) explicit

Construct without explicit GPU context configuration.

Equivalent to calling AndroidApplication(const Arguments&, const Configuration&, const GLConfiguration&) with default-constructed GLConfiguration.

Magnum::Platform::AndroidApplication::AndroidApplication(const Arguments& arguments, NoCreateT) explicit

Construct without creating a window.

Parameters
arguments Application arguments

Unlike above, the window is not created and must be created later with create() or tryCreate().

ANativeActivity* Magnum::Platform::AndroidApplication::nativeActivity()

Underlying native activity handle.

Use in case you need to call NDK functionality directly.

void Magnum::Platform::AndroidApplication::create(const Configuration& configuration, const GLConfiguration& glConfiguration) protected

Create a window with given configuration for OpenGL context.

Parameters
configuration Application configuration
glConfiguration OpenGL context configuration

Must be called only if the context wasn't created by the constructor itself, i.e. when passing NoCreate to it. Error message is printed and the program exits if the context cannot be created, see tryCreate() for an alternative.

void Magnum::Platform::AndroidApplication::create(const Configuration& configuration) protected

Create a window with given configuration and OpenGL context.

Equivalent to calling create(const Configuration&, const GLConfiguration&) with default-constructed GLConfiguration.

void Magnum::Platform::AndroidApplication::create() protected

Create a window with default configuration and OpenGL context.

Equivalent to calling create(const Configuration&) with default-constructed Configuration.

bool Magnum::Platform::AndroidApplication::tryCreate(const Configuration& configuration, const GLConfiguration& glConfiguration) protected

Try to create context with given configuration for OpenGL context.

Unlike create(const Configuration&, const GLConfiguration&) returns false if the context cannot be created, true otherwise.

bool Magnum::Platform::AndroidApplication::tryCreate(const Configuration& configuration) protected

Try to create context with given configuration and OpenGL context.

Unlike create(const Configuration&) returns false if the context cannot be created, true otherwise.

Vector2i Magnum::Platform::AndroidApplication::windowSize() const

Window size.

Window size to which all input event coordinates can be related. Expects that a window is already created, equivalent to framebufferSize().

Vector2i Magnum::Platform::AndroidApplication::framebufferSize() const

Framebuffer size.

Size of the default framebuffer, equivalent to windowSize(). Expects that a window is already created.

Vector2 Magnum::Platform::AndroidApplication::dpiScaling() const

DPI scaling.

Provided only for compatibility with other toolkits. Returns always {1.0f, 1.0f}.

Vector2 Magnum::Platform::AndroidApplication::dpiScaling(const Configuration& configuration) const

DPI scaling for given configuration.

Provided only for compatibility with other toolkits. Returns always {1.0f, 1.0f}.

void Magnum::Platform::AndroidApplication::swapBuffers()

Swap buffers.

Paints currently rendered framebuffer on screen.

void Magnum::Platform::AndroidApplication::redraw()

Redraw immediately.

Marks the window for redrawing, resulting in call to drawEvent() in the next iteration. You can call it from drawEvent() itself to redraw immediately without waiting for user input.

void Magnum::Platform::AndroidApplication::viewportEvent(ViewportEvent& event) virtual private

Viewport event.

Called when window size changes, for example after device orientation change. The default implementation does nothing. If you want to respond to size changes, you should pass the new size to GL::DefaultFramebuffer::setViewport() (if using OpenGL) and possibly elsewhere (to SceneGraph::Camera::setViewport(), other framebuffers...).

Note that this function might not get called at all if the window size doesn't change. You should configure the initial state of your cameras, framebuffers etc. in application constructor rather than relying on this function to be called. Size of the window can be retrieved using windowSize(), size of the backing framebuffer via framebufferSize() and DPI scaling using dpiScaling(). See DPI awareness for detailed info about these values.

void Magnum::Platform::AndroidApplication::drawEvent() pure virtual private

Draw event.

Called when the screen is redrawn. You should clean the framebuffer using GL::DefaultFramebuffer::clear() (if using OpenGL) and then add your own drawing functions. After drawing is finished, call swapBuffers(). If you want to draw immediately again, call also redraw().

void Magnum::Platform::AndroidApplication::pointerPressEvent(PointerEvent& event) virtual private new in Git master

Pointer press event.

Called when a mouse is pressed. Note that if at least one mouse button is already pressed and another button gets pressed in addition, pointerMoveEvent() with the new combination is called, not this function.

On builds with MAGNUM_BUILD_DEPRECATED enabled, default implementation delegates to mousePressEvent(). On builds with deprecated functionality disabled, default implementation does nothing.

void Magnum::Platform::AndroidApplication::mousePressEvent(MouseEvent& event) virtual private

Mouse press event.

Default implementation does nothing.

void Magnum::Platform::AndroidApplication::pointerReleaseEvent(PointerEvent& event) virtual private new in Git master

Pointer release event.

Called when a mouse is released. Note that if multiple mouse buttons are pressed and one of these is released, pointerMoveEvent() with the new combination is called, not this function.

On builds with MAGNUM_BUILD_DEPRECATED enabled, default implementation delegates to mouseReleaseEvent(). On builds with deprecated functionality disabled, default implementation does nothing.

void Magnum::Platform::AndroidApplication::mouseReleaseEvent(MouseEvent& event) virtual private

Mouse release event.

Default implementation does nothing.

void Magnum::Platform::AndroidApplication::pointerMoveEvent(PointerMoveEvent& event) virtual private new in Git master

Pointer move event.

Called when any of the currently pressed pointers is moved or changes its properties. Gets called also if the set of pressed mouse buttons changes.

On builds with MAGNUM_BUILD_DEPRECATED enabled, default implementation delegates to mouseMoveEvent(), or if PointerMoveEvent::pointer() is not Containers::NullOpt, to either mousePressEvent() or mouseReleaseEvent(). On builds with deprecated functionality disabled, default implementation does nothing.

void Magnum::Platform::AndroidApplication::mouseMoveEvent(MouseMoveEvent& event) virtual private

Mouse move event.

Default implementation does nothing.