Add AndroidApp::vm_as_ptr() and ::activity_as_ptr() APIs

This enables applications to make JNI calls without needing the
`ndk-context` crate - which we would like to deprecate.

Fixes: #60
This commit is contained in:
Robert Bragg
2023-02-13 02:38:49 +00:00
parent 6942637c3c
commit dc9ca832c5
4 changed files with 68 additions and 0 deletions
+3
View File
@@ -3,6 +3,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Added `AndroidApp::vm_as_ptr()` to expose JNI `JavaVM` pointer ([#60](https://github.com/rust-mobile/android-activity/issues/60))
- Added `AndroidApp::activity_as_ptr()` to expose Android `Activity` JNI reference as pointer ([#60](https://github.com/rust-mobile/android-activity/issues/60))
## [0.4] - 2022-11-10
### Changed
+11
View File
@@ -12,6 +12,7 @@ use std::sync::{Arc, RwLock};
use std::time::Duration;
use std::{ptr, thread};
use libc::c_void;
use log::{error, trace, Level};
use jni_sys::*;
@@ -155,6 +156,16 @@ pub struct AndroidAppInner {
}
impl AndroidAppInner {
pub fn vm_as_ptr(&self) -> *mut c_void {
let app_ptr = self.native_app.as_ptr();
unsafe { (*(*app_ptr).activity).vm as _ }
}
pub fn activity_as_ptr(&self) -> *mut c_void {
let app_ptr = self.native_app.as_ptr();
unsafe { (*(*app_ptr).activity).javaGameActivity as _ }
}
pub fn native_window(&self) -> Option<NativeWindow> {
self.native_window.read().unwrap().clone()
}
+44
View File
@@ -62,6 +62,7 @@ use std::sync::Arc;
use std::sync::RwLock;
use std::time::Duration;
use libc::c_void;
use ndk::asset::AssetManager;
use ndk::native_window::NativeWindow;
@@ -472,6 +473,49 @@ impl AndroidApp {
self.inner.read().unwrap().native_window()
}
/// Returns a pointer to the Java Virtual Machine, for making JNI calls
///
/// This returns a pointer to the Java Virtual Machine which can be used
/// with the [`jni`] crate (or similar crates) to make JNI calls that bridge
/// between native Rust code and Java/Kotlin code running within the JVM.
///
/// If you use the [`jni`] crate you can wrap this as a [`JavaVM`] via:
/// ```ignore
/// # use jni::JavaVM;
/// # let app: AndroidApp = todo!();
/// let vm = unsafe { JavaVM::from_raw(app.vm_as_ptr()) };
/// ```
///
/// [`jni`]: https://crates.io/crates/jni
/// [`JavaVM`]: https://docs.rs/jni/latest/jni/struct.JavaVM.html
pub fn vm_as_ptr(&self) -> *mut c_void {
self.inner.read().unwrap().vm_as_ptr()
}
/// Returns a JNI object reference for this application's JVM `Activity` as a pointer
///
/// If you use the [`jni`] crate you can wrap this as an object reference via:
/// ```ignore
/// # use jni::objects::JObject;
/// # let app: AndroidApp = todo!();
/// let activity = unsafe { JObject::from_raw(app.activity_as_ptr()) };
/// ```
///
/// # JNI Safety
///
/// Note that the object reference will be a JNI global reference, not a
/// local reference and it should not be deleted. Don't wrap the reference
/// in an [`AutoLocal`] which would try to explicitly delete the reference
/// when dropped. Similarly, don't wrap the reference as a [`GlobalRef`]
/// which would also try to explicitly delete the reference when dropped.
///
/// [`jni`]: https://crates.io/crates/jni
/// [`AutoLocal`]: https://docs.rs/jni/latest/jni/objects/struct.AutoLocal.html
/// [`GlobalRef`]: https://docs.rs/jni/latest/jni/objects/struct.GlobalRef.html
pub fn activity_as_ptr(&self) -> *mut c_void {
self.inner.read().unwrap().activity_as_ptr()
}
/// Polls for any events associated with this [AndroidApp] and processes those events
/// (such as lifecycle events) via the given `callback`.
///
@@ -5,6 +5,7 @@ use std::ptr::NonNull;
use std::sync::{Arc, RwLock};
use std::time::Duration;
use libc::c_void;
use log::{error, trace};
use ndk_sys::ALooper_wake;
@@ -130,6 +131,15 @@ pub(crate) struct AndroidAppInner {
}
impl AndroidAppInner {
pub(crate) fn vm_as_ptr(&self) -> *mut c_void {
unsafe { (*self.native_activity.activity).vm as _ }
}
pub(crate) fn activity_as_ptr(&self) -> *mut c_void {
// "clazz" is a completely bogus name; this is the _instance_ not class pointer
unsafe { (*self.native_activity.activity).clazz as _ }
}
pub(crate) fn native_activity(&self) -> *const ndk_sys::ANativeActivity {
self.native_activity.activity
}