diff --git a/android-project/app/src/main/AndroidManifest.xml b/android-project/app/src/main/AndroidManifest.xml
index 4b84b02..e3061a1 100644
--- a/android-project/app/src/main/AndroidManifest.xml
+++ b/android-project/app/src/main/AndroidManifest.xml
@@ -5,6 +5,8 @@
+
+
diff --git a/src/device/controller/gbcart.rs b/src/device/controller/gbcart.rs
index 8ee0cc5..318b460 100644
--- a/src/device/controller/gbcart.rs
+++ b/src/device/controller/gbcart.rs
@@ -80,6 +80,9 @@ pub fn save(
elapsed_time: i64,
ram_path: &std::string::String,
) {
+ if cfg!(target_os = "android") {
+ return;
+ }
update_rtc_regs(gb_cart, elapsed_time);
if let Ok(file) = std::fs::File::create(ram_path) {
diff --git a/src/ui/android.rs b/src/ui/android.rs
index 2cbdae7..129864f 100644
--- a/src/ui/android.rs
+++ b/src/ui/android.rs
@@ -68,13 +68,22 @@ bind_java_type! {
},
}
+bind_java_type! {
+ ParcelFileDescriptor => "android.os.ParcelFileDescriptor",
+ methods {
+ fn close() -> (),
+ },
+}
+
bind_java_type! {
AndroidContentResolver => "android.content.ContentResolver",
type_map = {
AndroidUri => "android.net.Uri",
+ ParcelFileDescriptor => "android.os.ParcelFileDescriptor",
},
methods {
fn take_persistable_uri_permission(uri: AndroidUri, flags: jint) -> (),
+ fn open_file_descriptor(uri: AndroidUri, mode: JString) -> ParcelFileDescriptor,
},
}
@@ -160,11 +169,9 @@ fn list_controllers_on_jvm(env: &mut Env<'_>) -> jni::errors::Result, path: &str) -> jni::errors::Result<()> {
let raw_activity_global = app.activity_as_ptr() as jni::sys::jobject;
let activity = unsafe { env.as_cast_raw::>(&raw_activity_global)? };
- let uri_string = JString::from_str(env, path.to_string())?;
+ let uri_string = JString::from_str(env, path)?;
let uri = AndroidUri::parse(env, &uri_string)?;
let action_view = AndroidIntent::ACTION_VIEW(env)?;
@@ -305,6 +312,50 @@ pub fn get_dirs() -> ui::Dirs {
}
}
+pub fn rom_exists(path: &str) -> bool {
+ let path = path.to_string();
+
+ let vm = if let Ok(app) = ANDROID_APP.lock()
+ && let Some(app) = app.as_ref()
+ {
+ unsafe { JavaVM::from_raw(app.vm_as_ptr().cast()) }
+ } else {
+ eprintln!("Android app not initialized");
+ return false;
+ };
+ if let Err(err) = vm.attach_current_thread(|env| rom_exists_on_jvm(env, path)) {
+ eprintln!("JNI error while opening URI: {err:?}");
+ return false;
+ }
+ true
+}
+
+fn rom_exists_on_jvm(env: &mut Env<'_>, path: String) -> jni::errors::Result<()> {
+ if let Ok(app) = ANDROID_APP.lock()
+ && let Some(app) = app.as_ref()
+ {
+ let raw_activity_global = app.activity_as_ptr() as jni::sys::jobject;
+ let activity = unsafe { env.as_cast_raw::>(&raw_activity_global)? };
+ let path = JString::from_str(env, path)?;
+ let mode = JString::from_str(env, "r")?;
+ let uri = AndroidUri::parse(env, &path)?;
+
+ let content_resolver = activity.as_ref().get_content_resolver(env)?;
+ let parcel_file_descriptor = content_resolver.open_file_descriptor(env, &uri, &mode);
+ if let Ok(descriptor) = parcel_file_descriptor
+ && !descriptor.is_null()
+ {
+ descriptor.close(env)?;
+ return Ok(());
+ } else {
+ return Err(jni::errors::Error::ObjectFreed);
+ }
+ } else {
+ eprintln!("Android app not initialized");
+ return Err(jni::errors::Error::UninitializedJavaVM);
+ }
+}
+
#[unsafe(no_mangle)]
pub extern "system" fn Java_io_github_gopher64_gopher64_SlintActivity_nativeOnActivityResult<
'caller,
diff --git a/src/ui/gui.rs b/src/ui/gui.rs
index da541d5..8bb9ed9 100644
--- a/src/ui/gui.rs
+++ b/src/ui/gui.rs
@@ -1,4 +1,6 @@
use crate::ui;
+#[cfg(target_os = "android")]
+use crate::ui::android;
use slint::Model;
#[cfg(not(target_os = "android"))]
use slint::winit_030::WinitWindowAccessor;
@@ -93,13 +95,20 @@ fn file_dropped(app: &AppWindow) {
});
}
+fn rom_exists(path: &str) -> bool {
+ #[cfg(not(target_os = "android"))]
+ return std::fs::exists(path).unwrap_or(false);
+ #[cfg(target_os = "android")]
+ return android::rom_exists(path);
+}
+
fn local_game_window(app: &AppWindow, config: &ui::config::Config) {
app.set_recent_roms(slint::ModelRc::from(std::rc::Rc::new(
slint::VecModel::from(
config
.recent_roms
.iter()
- .filter(|x| std::fs::exists(x).unwrap_or(false))
+ .filter(|x| rom_exists(x))
.map(|x| {
(
x.into(),
@@ -585,7 +594,7 @@ pub fn run_rom(
for rom in handle.get_recent_roms().iter() {
if rom.0 != file_path.to_str().unwrap()
&& recent_roms.row_count() < 5
- && std::fs::exists(&rom.0).unwrap_or(false)
+ && rom_exists(&rom.0)
{
recent_roms.push(rom);
}