rom reading on android (#937)

This commit is contained in:
Logan McNaughton
2026-05-22 16:42:08 +02:00
committed by GitHub
parent 18fbd8e56c
commit 3f9d62248a
2 changed files with 69 additions and 7 deletions
+15 -5
View File
@@ -16,7 +16,7 @@ const N64_EXTENSIONS_UNCOMPRESSED: [&str; 8] =
use rand::{Rng, SeedableRng};
use crate::{cheats, netplay, retroachievements, ui};
use std::{collections::HashMap, fs, io::Read};
use std::{collections::HashMap, io::Read};
pub mod ai;
pub mod cache;
@@ -156,7 +156,10 @@ pub fn get_rom_contents(file_path: &std::path::PathBuf) -> Option<Vec<u8>> {
.unwrap_or_default()
.eq_ignore_ascii_case("zip")
{
let zip_file = fs::File::open(file_path).unwrap();
#[cfg(target_os = "android")]
let zip_file = ui::android::get_file_from_uri(file_path).unwrap();
#[cfg(not(target_os = "android"))]
let zip_file = std::fs::File::open(file_path).unwrap();
let mut archive = zip::ZipArchive::new(zip_file).unwrap();
for i in 0..archive.len() {
let mut file = archive.by_index(i).unwrap();
@@ -173,8 +176,12 @@ pub fn get_rom_contents(file_path: &std::path::PathBuf) -> Option<Vec<u8>> {
.unwrap_or_default()
.eq_ignore_ascii_case("7z")
{
#[cfg(target_os = "android")]
let sevenz_file = ui::android::get_file_from_uri(file_path).unwrap();
#[cfg(not(target_os = "android"))]
let sevenz_file = std::fs::File::open(file_path).unwrap();
let mut archive =
sevenz_rust2::ArchiveReader::open(file_path, sevenz_rust2::Password::empty()).unwrap();
sevenz_rust2::ArchiveReader::new(sevenz_file, sevenz_rust2::Password::empty()).unwrap();
let mut found = false;
archive
@@ -197,8 +204,11 @@ pub fn get_rom_contents(file_path: &std::path::PathBuf) -> Option<Vec<u8>> {
)
.expect("ok");
} else {
contents = fs::read(file_path)
.unwrap_or_else(|_| panic!("Could not read ROM file: {}", file_path.display()));
#[cfg(target_os = "android")]
let mut file = ui::android::get_file_from_uri(file_path).unwrap();
#[cfg(not(target_os = "android"))]
let mut file = std::fs::File::open(file_path).unwrap();
file.read_to_end(&mut contents).unwrap();
}
if contents.is_empty() {
+54 -2
View File
@@ -1,9 +1,9 @@
use crate::ui;
use jni::objects::{JClass, JObject, JString};
use jni::refs::Global;
use jni::sys::jint;
use jni::{Env, EnvUnowned, JavaVM, bind_java_type};
use crate::ui;
use std::os::fd::FromRawFd;
pub const REQUEST_SELECT_ROM: jint = 1;
@@ -72,6 +72,7 @@ bind_java_type! {
ParcelFileDescriptor => "android.os.ParcelFileDescriptor",
methods {
fn close() -> (),
fn detach_fd() -> jint,
},
}
@@ -371,6 +372,57 @@ fn rom_exists_on_jvm(env: &mut Env<'_>, path: String) -> jni::errors::Result<()>
}
}
pub fn get_file_from_uri(path: &std::path::PathBuf) -> Option<std::fs::File> {
let path = path.to_str().unwrap().into();
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 None;
};
match vm.attach_current_thread(|env| get_file_from_uri_on_jvm(env, path)) {
Ok(file) => file,
Err(err) => {
eprintln!("JNI error while opening URI: {err:?}");
return None;
}
}
}
fn get_file_from_uri_on_jvm(
env: &mut Env<'_>,
path: String,
) -> jni::errors::Result<Option<std::fs::File>> {
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::<Global<AndroidActivity>>(&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()
{
let owned_fd = unsafe { std::os::fd::OwnedFd::from_raw_fd(descriptor.detach_fd(env)?) };
let file = std::fs::File::from(owned_fd);
descriptor.close(env)?;
return Ok(Some(file));
} else {
return Ok(None);
}
} 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,