slint/android.rs
1// Copyright © SixtyFPS GmbH <[email protected]>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4//! Android backend.
5//!
6//! **Note:** This module is only available on Android with the "backend-android-activity-06" feature
7//!
8//! Slint uses the [android-activity crate](https://github.com/rust-mobile/android-activity) as a backend.
9//!
10//! For convenience, Slint re-exports the content of the [`android-activity`](https://docs.rs/android-activity) under `slint::android::android_activity`.
11//!
12//! As with every application using the android-activity crate, the entry point to your app will be the `android_main` function.
13//! From that function, you can call [`slint::android::init`](init()) or [`slint::android::init_with_event_listener`](init_with_event_listener)
14//!
15//! # Example
16//!
17//! This is a basic example of an Android application.
18//! Do not forget the `#[unsafe(no_mangle)]`
19//!
20//! ```rust
21//! # #[cfg(target_os = "android")]
22//! #[unsafe(no_mangle)]
23//! fn android_main(app: slint::android::AndroidApp) {
24//! slint::android::init(app).unwrap();
25//!
26//! // ... rest of your code ...
27//! slint::slint!{
28//! export component MainWindow inherits Window {
29//! Text { text: "Hello World"; }
30//! }
31//! }
32//! MainWindow::new().unwrap().run().unwrap();
33//! }
34//! ```
35//!
36//! That function must be in a `cdylib` library, and you should enable the "backend-android-activity-06"
37//! feature of the slint crate in your Cargo.toml:
38//!
39//! ```toml
40//! [lib]
41//! crate-type = ["cdylib"]
42//!
43//! [dependencies]
44//! slint = { version = "1.6", features = ["backend-android-activity-06"] }
45//! ```
46//!
47//! ## Building and Deploying
48//!
49//! Building a Rust application requires the target toolchain to be installed. You can install it via `rustup`. For example, to target AArch64 Android, use the following command:
50//!
51//! ```sh
52//! rustup target add aarch64-linux-android
53//! ```
54//!
55//! Make sure that you have the Android NDK and SDK installed and set up in your development environment.
56//! For detailed instructions on how to set up the Android NDK and SDK, please refer to the [Android Developer's guide](https://developer.android.com/studio/projects/install-ndk).
57//! The following environment variables need to be set:
58//! * `ANDROID_HOME`: The directory in which your Android SDK is located. Usually `$HOME/Android/Sdk`.
59//! * `ANDROID_NDK_ROOT`: The directory in which your Android NDK is located. Usually `$HOME/Android/Sdk/ndk/${NDK_VERSION}`. ${NDK_VERSION} is the version of the NDK you have installed.
60//! * `JAVA_HOME`: The directory in which your Java compiler (`javac`) is located. This variable is optional if a `javac` is found in your `$PATH`.
61//! Otherwise you can set `JAVA_HOME` to the `javac` installation shipped with Android Studio in `android-studio/jbr`.
62//!
63//! To build and deploy your application, we suggest the usage of [cargo-apk](https://github.com/rust-mobile/cargo-apk),
64//! a cargo subcommand that allows you to build, sign, and deploy Android APKs made in Rust.
65//!
66//! You can install it and use it with the following command:
67//!
68//! ```sh
69//! cargo install cargo-apk
70//! ```
71//!
72//! Build and run your application with the following command:
73//!
74//! ```sh
75//! cargo apk run --target aarch64-linux-android --lib
76//! ```
77//!
78//!
79//! Note Slint does not require a specific build tool and can work with others, such as [xbuild](https://github.com/rust-mobile/xbuild).
80
81/// Re-export of the android-activity crate.
82#[cfg(all(
83 target_os = "android",
84 any(feature = "backend-android-activity-05", feature = "backend-android-activity-06")
85))]
86pub use i_slint_backend_android_activity::android_activity;
87
88#[cfg(not(all(
89 target_os = "android",
90 any(feature = "backend-android-activity-05", feature = "backend-android-activity-06")
91)))]
92/// Re-export of the [android-activity](https://docs.rs/android-activity) crate.
93pub mod android_activity {
94 #[doc(hidden)]
95 pub struct AndroidApp;
96 #[doc(hidden)]
97 pub struct PollEvent<'a>(&'a ());
98}
99
100/// Re-export of AndroidApp from the [android-activity](https://docs.rs/android-activity) crate.
101#[doc(no_inline)]
102pub use android_activity::AndroidApp;
103
104use crate::platform::SetPlatformError;
105
106/// Initializes the Android backend.
107///
108/// **Note:** This function is only available on Android with the "backend-android-activity-06" feature
109///
110/// This function must be called from the `android_main` function before any call to Slint that needs a backend.
111///
112/// See the [module documentation](self) for an example on how to create Android application.
113///
114/// See also [`init_with_event_listener`]
115pub fn init(app: android_activity::AndroidApp) -> Result<(), SetPlatformError> {
116 #[cfg(not(target_os = "android"))]
117 unreachable!();
118 #[cfg(target_os = "android")]
119 {
120 crate::platform::set_platform(Box::new(
121 i_slint_backend_android_activity::AndroidPlatform::new(app),
122 ))
123 }
124}
125
126/// Similar to [`init()`], which allow to listen to android-activity's event
127///
128/// **Note:** This function is only available on Android with the "backend-android-activity-06" feature
129///
130/// The listener argument is a function that takes a [`android_activity::PollEvent`](https://docs.rs/android-activity/latest/android_activity/enum.PollEvent.html)
131///
132/// # Example
133///
134/// ```rust
135/// # #[cfg(target_os = "android")]
136/// #[unsafe(no_mangle)]
137/// fn android_main(app: slint::android_activity::AndroidApp) {
138/// slint::android_init_with_event_listener(
139/// app,
140/// |event| { eprintln!("got event {event:?}") }
141/// ).unwrap();
142///
143/// // ... rest of your application ...
144///
145/// }
146/// ```
147///
148/// Check out the [module documentation](self) for a more complete example on how to write an android application
149pub fn init_with_event_listener(
150 app: android_activity::AndroidApp,
151 listener: impl Fn(&android_activity::PollEvent<'_>) + 'static,
152) -> Result<(), SetPlatformError> {
153 #[cfg(not(target_os = "android"))]
154 unreachable!();
155 #[cfg(target_os = "android")]
156 {
157 crate::platform::set_platform(Box::new(
158 i_slint_backend_android_activity::AndroidPlatform::new_with_event_listener(
159 app, listener,
160 ),
161 ))
162 }
163}