android_ndk/
native_activity.rs

1//! Bindings for `ANativeActivity`
2//!
3//! See also [the NDK
4//! docs](https://developer.android.com/ndk/reference/struct/a-native-activity.html)
5
6//use num_enum::{IntoPrimitive, TryFromPrimitive};
7use std::ffi::CStr;
8use std::os::raw::c_void;
9use std::ptr::NonNull;
10
11/// An `ANativeActivity *`
12///
13/// This is either provided in `ANativeActivity_onCreate`, or accessible in
14/// `android_native_app_glue`'s android_app.
15#[derive(Debug)]
16pub struct NativeActivity {
17    ptr: NonNull<ffi::ANativeActivity>,
18}
19
20// It gets shared between threads in android_native_app_glue
21unsafe impl Send for NativeActivity {}
22unsafe impl Sync for NativeActivity {}
23
24impl NativeActivity {
25    /// Create a `NativeActivity` from a pointer
26    ///
27    /// By calling this function, you assert that it is a valid pointer to a native
28    /// `ANativeActivity`.
29    pub unsafe fn from_ptr(ptr: NonNull<ffi::ANativeActivity>) -> Self {
30        Self { ptr }
31    }
32
33    /// The pointer to the native `ANativeActivity`
34    pub fn ptr(&self) -> NonNull<ffi::ANativeActivity> {
35        self.ptr
36    }
37}
38
39/// Methods that relate to fields of the struct itself
40///
41/// The relevant NDK docs can be found
42/// [here.](https://developer.android.com/ndk/reference/struct/a-native-activity)
43impl NativeActivity {
44    /// The platform's SDK version code
45    pub fn sdk_version(&self) -> i32 {
46        unsafe { self.ptr.as_ref().sdkVersion }
47    }
48
49    /// Path to this application's internal data directory
50    pub fn internal_data_path(&self) -> &CStr {
51        unsafe { CStr::from_ptr(self.ptr.as_ref().internalDataPath) }
52    }
53
54    /// Path to this application's external (removable, mountable) data directory
55    pub fn external_data_path(&self) -> &CStr {
56        unsafe { CStr::from_ptr(self.ptr.as_ref().externalDataPath) }
57    }
58
59    /// This app's asset manager, which can be used to access assets from the `.apk` file.
60    pub fn asset_manager(&self) -> crate::asset::AssetManager {
61        unsafe {
62            crate::asset::AssetManager::from_ptr(
63                NonNull::new(self.ptr.as_ref().assetManager).unwrap(),
64            )
65        }
66    }
67
68    /// Instance data associated with the activity
69    pub fn instance(&self) -> *mut c_void {
70        unsafe { self.ptr.as_ref().instance }
71    }
72
73    /// Set the instance data associated with the activity
74    ///
75    /// This can invalidate assumptions held by `android_native_app_glue`, as well as cause data
76    /// races with concurrent access to the instance data.
77    pub unsafe fn set_instance(&mut self, data: *mut c_void) {
78        // FIXME Does this create undefined behavior by creating a mutable reference to what could
79        // also be accessed immutably at the same time?
80        //
81        // I think that as long as we warn the users to avoid concurrent access, and we pass along
82        // the `unsafe` burden, it's OK.
83        self.ptr.as_mut().instance = data;
84    }
85
86    /// This process's `JavaVM` object.
87    ///
88    /// ```no_run
89    /// # use android_ndk::native_activity::NativeActivity;
90    /// # let native_activity: NativeActivity = unimplemented!();
91    /// let vm = native_activity.vm();
92    /// let env = vm.attach_current_thread();
93    /// // Do JNI with env ...
94    /// ```
95    pub fn vm(&self) -> jni::JavaVM {
96        unsafe { jni::JavaVM::from_raw(self.ptr.as_ref().vm as *mut _).unwrap() }
97    }
98
99    /// The `android.app.NativeActivity` instance
100    ///
101    /// In the JNI, this is named `clazz`; however, as the docs say, "it should really be named
102    /// 'activity' instead of 'clazz', since it's a reference to the NativeActivity instance.
103    pub fn activity(&self) -> jni::objects::JObject<'_> {
104        unsafe {
105            jni::objects::JObject::from(&self.ptr.as_ref().clazz as *const _ as jni::sys::jobject)
106        }
107    }
108
109    /// Path to the directory with the application's OBB files.
110    ///
111    /// Only available as of Honeycomb (Android 3.0+, API level 11+)
112    pub unsafe fn obb_path(&self) -> &CStr {
113        CStr::from_ptr(self.ptr.as_ref().obbPath)
114    }
115}
116
117/// Methods that relate to `ANativeActivity_*` functions.
118///
119/// The relevant NDK docs can be found
120/// [here.](https://developer.android.com/ndk/reference/group/native-activity)
121impl NativeActivity {
122    /// Sends a destroy event to the activity and stops it.
123    pub fn finish(&self) {
124        unsafe { ffi::ANativeActivity_finish(self.ptr.as_ptr()) }
125    }
126
127    /// Shows the IME (the on-screen keyboard).
128    ///
129    /// If `force` is true, the `SHOW_FORCED` flag is used; otherwise, the `SHOW_IMPLICIT` flag is
130    /// used.  Depending on the value of this flag, the `hide_soft_input` method with behave
131    /// differently.  See [the relevant
132    /// javadoc](https://developer.android.com/reference/android/view/inputmethod/InputMethodManager#constants_2)
133    /// for more information.
134    pub fn show_soft_input(&self, force: bool) {
135        let flag = if force {
136            ffi::ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED
137        } else {
138            ffi::ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT
139        };
140        unsafe { ffi::ANativeActivity_showSoftInput(self.ptr.as_ptr(), flag) }
141    }
142
143    /// Hides the IME (the on-screen keyboard).
144    ///
145    /// If `not_always` is true, the `HIDE_NOT_ALWAYS` flag is used; otherwise, the
146    /// `HIDE_IMPLICIT_ONLY` flag is used.  Depending on the value of this flag and the way the IME
147    /// was shown, it may or may not be hidden.  See [the relevant
148    /// javadoc](https://developer.android.com/reference/android/view/inputmethod/InputMethodManager#constants_2)
149    /// for more information.
150    pub fn hide_soft_input(&self, not_always: bool) {
151        let flag = if not_always {
152            ffi::ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS
153        } else {
154            ffi::ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY
155        };
156        unsafe { ffi::ANativeActivity_hideSoftInput(self.ptr.as_ptr(), flag) }
157    }
158
159    /*/// Set the window format. Performs the Java `.getWindow().setFormat()`.
160    ///
161    /// See also [the relevant
162    /// javadoc](https://developer.android.com/reference/android/view/Window#setFormat(int))
163    pub unsafe fn set_window_format(&self, format: WindowFormat) {
164        unsafe { ffi::ANativeActivity_setWindowFormat(self.ptr.as_ptr(), format.into()) }
165    }*/
166}
167
168/*#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
169#[repr(u32)]
170pub enum WindowFormat {
171    Rgb565 = ffi::ANativeWindow_LegacyFormat_WINDOW_FORMAT_RGB_565,
172    Rgba8888 = ffi::ANativeWindow_LegacyFormat_WINDOW_FORMAT_RGBA_8888,
173    Rgbx8888 = ffi::ANativeWindow_LegacyFormat_WINDOW_FORMAT_RGBX_8888,
174}*/