use blinc_platform::assets::{AssetLoader, AssetPath};
use blinc_platform::{PlatformError, Result};
#[cfg(target_os = "android")]
use android_activity::AndroidApp;
#[cfg(target_os = "android")]
use std::ffi::CString;
#[cfg_attr(not(target_os = "android"), derive(Default))]
pub struct AndroidAssetLoader {
#[cfg(target_os = "android")]
app: AndroidApp,
}
#[cfg(target_os = "android")]
impl AndroidAssetLoader {
pub fn new(app: AndroidApp) -> Self {
Self { app }
}
fn load_from_assets(&self, path: &str) -> Result<Vec<u8>> {
use ndk::asset::{Asset, AssetManager};
use std::io::Read;
let asset_manager = self.app.asset_manager();
let c_path = CString::new(path)
.map_err(|e| PlatformError::AssetLoad(format!("Invalid path: {}", e)))?;
let mut asset = asset_manager
.open(&c_path)
.ok_or_else(|| PlatformError::AssetLoad(format!("Asset not found: {}", path)))?;
let mut buffer = Vec::new();
asset.read_to_end(&mut buffer).map_err(|e| {
PlatformError::AssetLoad(format!("Failed to read asset '{}': {}", path, e))
})?;
Ok(buffer)
}
}
#[cfg(target_os = "android")]
impl AssetLoader for AndroidAssetLoader {
fn load(&self, path: &AssetPath) -> Result<Vec<u8>> {
match path {
AssetPath::Relative(rel) => self.load_from_assets(rel),
AssetPath::Absolute(abs) => {
let asset_path = abs.trim_start_matches('/');
self.load_from_assets(asset_path)
}
AssetPath::Embedded(name) => {
self.load_from_assets(name)
}
}
}
fn exists(&self, path: &AssetPath) -> bool {
use ndk::asset::AssetManager;
let asset_path = match path {
AssetPath::Relative(rel) => rel.as_str(),
AssetPath::Absolute(abs) => abs.trim_start_matches('/'),
AssetPath::Embedded(name) => *name,
};
let Ok(c_path) = CString::new(asset_path) else {
return false;
};
let asset_manager = self.app.asset_manager();
asset_manager.open(&c_path).is_some()
}
fn platform_name(&self) -> &'static str {
"android"
}
}
#[cfg(not(target_os = "android"))]
impl AndroidAssetLoader {
pub fn new() -> Self {
Self::default()
}
}
#[cfg(not(target_os = "android"))]
impl AssetLoader for AndroidAssetLoader {
fn load(&self, _path: &AssetPath) -> Result<Vec<u8>> {
Err(PlatformError::Unsupported(
"Android asset loading only available on Android".to_string(),
))
}
fn exists(&self, _path: &AssetPath) -> bool {
false
}
fn platform_name(&self) -> &'static str {
"android-stub"
}
}