mirror of https://github.com/tauri-apps/tauri
feat(core): resources on mobile apps (#10696)
* feat(core): resources on mobile apps * resources dir on android
This commit is contained in:
parent
086271b73e
commit
da381e07f3
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
"tauri-cli": patch:feat
|
||||
"@tauri-apps/cli": patch:feat
|
||||
---
|
||||
|
||||
Inject configured resources on mobile apps.
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"tauri-utils": patch:bug
|
||||
---
|
||||
|
||||
Implemented `resource_dir` on Android, which returns a URI that needs to be resolved using [AssetManager::open](https://developer.android.com/reference/android/content/res/AssetManager#open(java.lang.String,%20int)). This will be handled by the file system plugin.
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"tauri-utils": patch:bug
|
||||
---
|
||||
|
||||
Fix `resource_dir` on iOS.
|
|
@ -15,6 +15,9 @@ use crate::{Env, PackageInfo};
|
|||
|
||||
mod starting_binary;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub const ANDROID_ASSET_PROTOCOL_URI_PREFIX: &str = "asset://localhost/";
|
||||
|
||||
/// Platform target.
|
||||
#[derive(PartialEq, Eq, Copy, Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
|
@ -256,7 +259,13 @@ fn is_cargo_output_directory(path: &Path) -> bool {
|
|||
/// `${exe_dir}/../lib/${exe_name}`.
|
||||
///
|
||||
/// On MacOS, it's `${exe_dir}../Resources` (inside .app).
|
||||
///
|
||||
/// On iOS, it's `${exe_dir}/assets`.
|
||||
///
|
||||
/// Android uses a special URI prefix that is resolved by the Tauri file system plugin `asset://localhost/`
|
||||
pub fn resource_dir(package_info: &PackageInfo, env: &Env) -> crate::Result<PathBuf> {
|
||||
#[cfg(target_os = "android")]
|
||||
return Ok(PathBuf::from(ANDROID_ASSET_PROTOCOL_URI_PREFIX));
|
||||
let exe = current_exe()?;
|
||||
resource_dir_from(exe, package_info, env)
|
||||
}
|
||||
|
@ -320,6 +329,11 @@ fn resource_dir_from<P: AsRef<Path>>(
|
|||
.map_err(Into::into);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
{
|
||||
res = exe_dir.join("assets").canonicalize().map_err(Into::into);
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ import app.tauri.plugin.Plugin
|
|||
import app.tauri.plugin.Invoke
|
||||
import app.tauri.plugin.JSObject
|
||||
|
||||
const val TAURI_ASSETS_DIRECTORY_URI = "asset://localhost/"
|
||||
|
||||
@TauriPlugin
|
||||
class PathPlugin(private val activity: Activity): Plugin(activity) {
|
||||
private fun resolvePath(invoke: Invoke, path: String?) {
|
||||
|
@ -67,8 +69,7 @@ class PathPlugin(private val activity: Activity): Plugin(activity) {
|
|||
|
||||
@Command
|
||||
fun getResourcesDir(invoke: Invoke) {
|
||||
// TODO
|
||||
resolvePath(invoke, activity.cacheDir.absolutePath)
|
||||
resolvePath(invoke, TAURI_ASSETS_DIRECTORY_URI)
|
||||
}
|
||||
|
||||
@Command
|
||||
|
|
|
@ -3221,7 +3221,7 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
|
|||
|
||||
[[package]]
|
||||
name = "tauri"
|
||||
version = "2.0.0-rc.3"
|
||||
version = "2.0.0-rc.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
@ -3271,7 +3271,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-build"
|
||||
version = "2.0.0-rc.3"
|
||||
version = "2.0.0-rc.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo_toml",
|
||||
|
@ -3293,7 +3293,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-codegen"
|
||||
version = "2.0.0-rc.3"
|
||||
version = "2.0.0-rc.4"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"brotli",
|
||||
|
@ -3318,7 +3318,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-macros"
|
||||
version = "2.0.0-rc.3"
|
||||
version = "2.0.0-rc.4"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
|
@ -3330,7 +3330,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-plugin"
|
||||
version = "2.0.0-rc.3"
|
||||
version = "2.0.0-rc.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"glob",
|
||||
|
@ -3356,7 +3356,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-runtime"
|
||||
version = "2.0.0-rc.3"
|
||||
version = "2.0.0-rc.4"
|
||||
dependencies = [
|
||||
"dpi",
|
||||
"gtk",
|
||||
|
@ -3373,7 +3373,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-runtime-wry"
|
||||
version = "2.0.0-rc.3"
|
||||
version = "2.0.0-rc.4"
|
||||
dependencies = [
|
||||
"cocoa 0.26.0",
|
||||
"gtk",
|
||||
|
@ -3395,7 +3395,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-utils"
|
||||
version = "2.0.0-rc.3"
|
||||
version = "2.0.0-rc.4"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"brotli",
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use anyhow::Result;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn copy_file(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<()> {
|
||||
let from = from.as_ref();
|
||||
let to = to.as_ref();
|
||||
if !from.exists() {
|
||||
return Err(anyhow::anyhow!("{:?} does not exist", from));
|
||||
}
|
||||
if !from.is_file() {
|
||||
return Err(anyhow::anyhow!("{:?} is not a file", from));
|
||||
}
|
||||
let dest_dir = to.parent().expect("No data in parent");
|
||||
std::fs::create_dir_all(dest_dir)?;
|
||||
std::fs::copy(from, to)?;
|
||||
Ok(())
|
||||
}
|
|
@ -8,6 +8,7 @@ pub mod cargo_manifest;
|
|||
pub mod config;
|
||||
pub mod flock;
|
||||
pub mod framework;
|
||||
pub mod fs;
|
||||
pub mod npm;
|
||||
pub mod plugins;
|
||||
pub mod prompts;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use super::{
|
||||
configure_cargo, delete_codegen_vars, ensure_init, env, get_app, get_config, inject_assets,
|
||||
configure_cargo, delete_codegen_vars, ensure_init, env, get_app, get_config, inject_resources,
|
||||
log_finished, open_and_wait, MobileTarget, OptionsHandle,
|
||||
};
|
||||
use crate::{
|
||||
|
@ -209,7 +209,7 @@ fn run_build(
|
|||
cli_options,
|
||||
)?;
|
||||
|
||||
inject_assets(config, tauri_config.lock().unwrap().as_ref().unwrap())?;
|
||||
inject_resources(config, tauri_config.lock().unwrap().as_ref().unwrap())?;
|
||||
|
||||
let apk_outputs = if options.apk {
|
||||
apk::build(
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use super::{
|
||||
configure_cargo, delete_codegen_vars, device_prompt, ensure_init, env, get_app, get_config,
|
||||
inject_assets, open_and_wait, MobileTarget,
|
||||
inject_resources, open_and_wait, MobileTarget,
|
||||
};
|
||||
use crate::{
|
||||
dev::Options as DevOptions,
|
||||
|
@ -244,7 +244,7 @@ fn run_dev(
|
|||
cli_options,
|
||||
)?;
|
||||
|
||||
inject_assets(config, tauri_config.lock().unwrap().as_ref().unwrap())?;
|
||||
inject_resources(config, tauri_config.lock().unwrap().as_ref().unwrap())?;
|
||||
|
||||
if open {
|
||||
open_and_wait(config, &env)
|
||||
|
|
|
@ -25,6 +25,7 @@ use std::{
|
|||
time::Duration,
|
||||
};
|
||||
use sublime_fuzzy::best_match;
|
||||
use tauri_utils::resources::ResourcePaths;
|
||||
|
||||
use super::{
|
||||
ensure_init, get_app,
|
||||
|
@ -32,7 +33,10 @@ use super::{
|
|||
log_finished, read_options, CliOptions, OptionsHandle, Target as MobileTarget,
|
||||
MIN_DEVICE_MATCH_SCORE,
|
||||
};
|
||||
use crate::{helpers::config::Config as TauriConfig, Result};
|
||||
use crate::{
|
||||
helpers::config::{BundleResources, Config as TauriConfig},
|
||||
Result,
|
||||
};
|
||||
|
||||
mod android_studio_script;
|
||||
mod build;
|
||||
|
@ -296,7 +300,7 @@ fn open_and_wait(config: &AndroidConfig, env: &Env) -> ! {
|
|||
}
|
||||
}
|
||||
|
||||
fn inject_assets(config: &AndroidConfig, tauri_config: &TauriConfig) -> Result<()> {
|
||||
fn inject_resources(config: &AndroidConfig, tauri_config: &TauriConfig) -> Result<()> {
|
||||
let asset_dir = config
|
||||
.project_dir()
|
||||
.join("app/src/main")
|
||||
|
@ -308,5 +312,18 @@ fn inject_assets(config: &AndroidConfig, tauri_config: &TauriConfig) -> Result<(
|
|||
serde_json::to_string(&tauri_config)?,
|
||||
)?;
|
||||
|
||||
let resources = match &tauri_config.bundle.resources {
|
||||
Some(BundleResources::List(paths)) => Some(ResourcePaths::new(paths.as_slice(), true)),
|
||||
Some(BundleResources::Map(map)) => Some(ResourcePaths::from_map(map, true)),
|
||||
None => None,
|
||||
};
|
||||
if let Some(resources) = resources {
|
||||
for resource in resources.iter() {
|
||||
let resource = resource?;
|
||||
let dest = asset_dir.join(resource.target());
|
||||
crate::helpers::fs::copy_file(resource.path(), dest)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use super::{
|
||||
configure_cargo, detect_target_ok, ensure_init, env, get_app, get_config, inject_assets,
|
||||
configure_cargo, detect_target_ok, ensure_init, env, get_app, get_config, inject_resources,
|
||||
log_finished, merge_plist, open_and_wait, MobileTarget, OptionsHandle,
|
||||
};
|
||||
use crate::{
|
||||
|
@ -164,7 +164,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
|
|||
config.project_dir(),
|
||||
MobileTarget::Ios,
|
||||
)?;
|
||||
inject_assets(&config)?;
|
||||
inject_resources(&config, tauri_config.lock().unwrap().as_ref().unwrap())?;
|
||||
|
||||
let info_plist_path = config
|
||||
.project_dir()
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use super::{
|
||||
configure_cargo, device_prompt, ensure_init, env, get_app, get_config, inject_assets,
|
||||
configure_cargo, device_prompt, ensure_init, env, get_app, get_config, inject_resources,
|
||||
merge_plist, open_and_wait, MobileTarget,
|
||||
};
|
||||
use crate::{
|
||||
|
@ -179,7 +179,7 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> {
|
|||
config.project_dir(),
|
||||
MobileTarget::Ios,
|
||||
)?;
|
||||
inject_assets(&config)?;
|
||||
inject_resources(&config, tauri_config.lock().unwrap().as_ref().unwrap())?;
|
||||
|
||||
let info_plist_path = config
|
||||
.project_dir()
|
||||
|
|
|
@ -20,6 +20,7 @@ use cargo_mobile2::{
|
|||
};
|
||||
use clap::{Parser, Subcommand};
|
||||
use sublime_fuzzy::best_match;
|
||||
use tauri_utils::resources::ResourcePaths;
|
||||
|
||||
use super::{
|
||||
ensure_init, env, get_app,
|
||||
|
@ -28,7 +29,10 @@ use super::{
|
|||
MIN_DEVICE_MATCH_SCORE,
|
||||
};
|
||||
use crate::{
|
||||
helpers::{app_paths::tauri_dir, config::Config as TauriConfig},
|
||||
helpers::{
|
||||
app_paths::tauri_dir,
|
||||
config::{BundleResources, Config as TauriConfig},
|
||||
},
|
||||
Result,
|
||||
};
|
||||
|
||||
|
@ -304,9 +308,23 @@ fn open_and_wait(config: &AppleConfig, env: &Env) -> ! {
|
|||
}
|
||||
}
|
||||
|
||||
fn inject_assets(config: &AppleConfig) -> Result<()> {
|
||||
fn inject_resources(config: &AppleConfig, tauri_config: &TauriConfig) -> Result<()> {
|
||||
let asset_dir = config.project_dir().join(DEFAULT_ASSET_DIR);
|
||||
create_dir_all(asset_dir)?;
|
||||
create_dir_all(&asset_dir)?;
|
||||
|
||||
let resources = match &tauri_config.bundle.resources {
|
||||
Some(BundleResources::List(paths)) => Some(ResourcePaths::new(paths.as_slice(), true)),
|
||||
Some(BundleResources::Map(map)) => Some(ResourcePaths::from_map(map, true)),
|
||||
None => None,
|
||||
};
|
||||
if let Some(resources) = resources {
|
||||
for resource in resources.iter() {
|
||||
let resource = resource?;
|
||||
let dest = asset_dir.join(resource.target());
|
||||
crate::helpers::fs::copy_file(resource.path(), dest)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue