mirror of
https://github.com/gopher64/gopher64.git
synced 2026-07-11 01:25:20 +02:00
rom reading on android (#937)
This commit is contained in:
+15
-5
@@ -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
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user