use std::hash::Hash;
use std::sync::Arc;
use std::sync::RwLock;
use std::time::Duration;
use ndk::asset::AssetManager;
use ndk::native_window::NativeWindow;
#[cfg(not(target_os = "android"))]
compile_error!("android-activity only supports compiling for Android");
#[cfg(all(feature = "game-activity", feature = "native-activity"))]
compile_error!(
"The \"game-activity\" and \"native-activity\" features cannot be enabled at the same time"
);
#[cfg(all(
not(any(feature = "game-activity", feature = "native-activity")),
not(doc)
))]
compile_error!("Either \"game-activity\" or \"native-activity\" must be enabled as features");
#[cfg(any(feature = "native-activity", doc))]
mod native_activity;
#[cfg(any(feature = "native-activity", doc))]
use native_activity as activity_impl;
#[cfg(feature = "game-activity")]
mod game_activity;
#[cfg(feature = "game-activity")]
use game_activity as activity_impl;
pub use activity_impl::input;
mod config;
pub use config::ConfigurationRef;
mod util;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Rect {
pub left: i32,
pub top: i32,
pub right: i32,
pub bottom: i32,
}
pub type StateSaver<'a> = activity_impl::StateSaver<'a>;
pub type StateLoader<'a> = activity_impl::StateLoader<'a>;
#[non_exhaustive]
#[derive(Debug)]
pub enum MainEvent<'a> {
InputAvailable,
#[non_exhaustive]
InitWindow {},
#[non_exhaustive]
TerminateWindow {},
#[non_exhaustive]
WindowResized {},
#[non_exhaustive]
RedrawNeeded {},
#[non_exhaustive]
ContentRectChanged {},
GainedFocus,
LostFocus,
#[non_exhaustive]
ConfigChanged {},
LowMemory,
Start,
#[non_exhaustive]
Resume { loader: StateLoader<'a> },
#[non_exhaustive]
SaveState { saver: StateSaver<'a> },
Pause,
Stop,
Destroy,
#[non_exhaustive]
InsetsChanged {},
}
#[derive(Debug)]
#[non_exhaustive]
pub enum PollEvent<'a> {
Wake,
Timeout,
Main(MainEvent<'a>),
}
use activity_impl::AndroidAppInner;
pub use activity_impl::AndroidAppWaker;
#[derive(Debug, Clone)]
pub struct AndroidApp {
pub(crate) inner: Arc<RwLock<AndroidAppInner>>,
}
impl PartialEq for AndroidApp {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}
impl Eq for AndroidApp {}
impl Hash for AndroidApp {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.inner).hash(state);
}
}
impl AndroidApp {
#[cfg_attr(docsrs, doc(cfg(feature = "native-activity")))]
#[cfg(feature = "native-activity")]
pub(crate) fn native_activity(&self) -> *const ndk_sys::ANativeActivity {
self.inner.read().unwrap().native_activity()
}
pub fn native_window<'a>(&self) -> Option<NativeWindow> {
self.inner.read().unwrap().native_window()
}
pub fn poll_events<F>(&self, timeout: Option<Duration>, callback: F)
where
F: FnMut(PollEvent),
{
self.inner.read().unwrap().poll_events(timeout, callback);
}
pub fn create_waker(&self) -> activity_impl::AndroidAppWaker {
self.inner.read().unwrap().create_waker()
}
pub fn config(&self) -> ConfigurationRef {
self.inner.read().unwrap().config()
}
pub fn content_rect(&self) -> Rect {
self.inner.read().unwrap().content_rect()
}
pub fn asset_manager(&self) -> AssetManager {
self.inner.read().unwrap().asset_manager()
}
pub fn enable_motion_axis(&self, axis: input::Axis) {
self.inner.write().unwrap().enable_motion_axis(axis);
}
pub fn disable_motion_axis(&self, axis: input::Axis) {
self.inner.write().unwrap().disable_motion_axis(axis);
}
pub fn input_events<'b, F>(&self, callback: F)
where
F: FnMut(&input::InputEvent),
{
self.inner.read().unwrap().input_events(callback);
}
pub fn sdk_version() -> i32 {
let mut prop = android_properties::getprop("ro.build.version.sdk");
if let Some(val) = prop.value() {
i32::from_str_radix(&val, 10).expect("Failed to parse ro.build.version.sdk property")
} else {
panic!("Couldn't read ro.build.version.sdk system property");
}
}
pub fn internal_data_path(&self) -> Option<std::path::PathBuf> {
self.inner.read().unwrap().internal_data_path()
}
pub fn external_data_path(&self) -> Option<std::path::PathBuf> {
self.inner.read().unwrap().external_data_path()
}
pub fn obb_path(&self) -> Option<std::path::PathBuf> {
self.inner.read().unwrap().obb_path()
}
}
#[test]
fn test_app_is_send_sync() {
fn needs_send_sync<T: Send + Sync>() {}
needs_send_sync::<AndroidApp>();
}