Вопрос или проблема
В настоящее время я пытаюсь написать приложение для Android, используя Tauri, которое должно получить доступ к файлам ресурсов шрифтов.
- Я добавил эти файлы в свою папку
fonts
в директорииsrc-tauri
. - В моем
tauri.conf.json
я указал спецификатор"bundle": {"resources": ["fonts/*"]}
- Я проверил директории
targe > debug
, и папка шрифтов + файлы шрифтов были созданы
Однако, когда я пытаюсь получить доступ к файлу, используя следующий фрагмент кода, я получаю ошибку NotFound.
let resource_path = app_handle
.path()
.resolve(format!("fonts/{}", name), BaseDirectory::Resource)
.expect("не удалось разрешить ресурс");
let mut file = File::open(&resource_path).expect(&format!("Не удалось открыть файл шрифта {}", resource_path.as_path().to_str().unwrap()));
10-19 16:22:58.189 19486 19600 I RustStdoutStderr: thread '<unnamed>' panicked at src\lib.rs:85:47:
10-19 16:22:58.189 19486 19600 I RustStdoutStderr: Не удалось открыть файл шрифта asset://localhost/fonts/Calibri-Regular.ttf: Os { code: 2, kind: NotFound, message: "Нет такого файла или директории" }
Я попробовал тот же код на Windows, и все работало нормально, кажется, что Android обрабатывает ресурсы по-другому, но я обычно не разрабатываю приложения для Android, так что не знаю, как с этим справиться. Буду признателен за любую помощь 🙂
Эта проблема, похоже, связана с тем, как Android обрабатывает файлы ресурсов в приложениях Tauri, что отличается от Windows. Основные моменты, которые следует учитывать:
Похоже, что разрешение пути ресурса работает, так как он генерирует путь.
Операция File::open() завершается с ошибкой NotFound.
Сгенерированный путь использует схему “asset://localhost/”, которая специфична для Android.
Проблема, вероятно, возникает из-за попытки использовать стандартные операции ввода-вывода файлов Rust в системе активов Android. Android упаковывает ресурсы особым образом, и они не могут быть доступны как обычные файлы в файловой системе.
Вместо использования File::open() используйте API активов Tauri, чтобы читать содержимое файла. Вот пример того, как это сделать:
use tauri::Assets;
fn read_font_file(assets: &Assets, name: &str) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let font_path = format!("fonts/{}", name);
let font_data = assets.get(&font_path).ok_or("Шрифт не найден")?;
Ok(font_data.into_owned())
}
// Использование в вашем коде:
let app_handle = // ... получите обработчик приложения
let assets = app_handle.assets_handle();
match read_font_file(&assets, "Calibri-Regular.ttf") {
Ok(font_data) => {
// Используйте font_data (Vec<u8>) по мере необходимости
println!("Данные шрифта загружены, размер: {} байт", font_data.len());
},
Err(e) => eprintln!("Не удалось загрузить шрифт: {}", e),
}
Этот подход использует систему активов Tauri, которая работает последовательно на всех платформах, включая Android. Она возвращает содержимое файла в виде Vec, который вы можете использовать по мере необходимости в вашем приложении.
Если вам нужно работать с данными шрифта как с файлом (например, если вы используете библиотеку, которая ожидает путь к файлу), вам, возможно, придется сначала записать данные во временный файл. Вот пример того, как вы могли бы это сделать:
use std::io::Write;
use tempfile::NamedTempFile;
fn create_temp_font_file(font_data: Vec<u8>) -> Result<NamedTempFile, std::io::Error> {
let mut temp_file = NamedTempFile::new()?;
temp_file.write_all(&font_data)?;
Ok(temp_file)
}
// Использование:
let font_data = read_font_file(&assets, "Calibri-Regular.ttf")?;
let temp_file = create_temp_font_file(font_data)?;
let temp_path = temp_file.path();
// Используйте temp_path по мере необходимости
Это создает временный файл, который будет автоматически удален, когда выйдет из области видимости.
Ответ или решение
Использование файлов ресурсов Tauri на Android может быть не таким простым, как на других платформах, таких как Windows. В этом ответе мы детально рассмотрим, как правильно работать с ресурсами шрифтов, добавленными в проект Tauri для Android, чтобы избежать ошибок, связанных с отсутствием файлов.
Шаги по правильному использованию файлов ресурсов в Tauri на Android
-
Добавление файлов шрифтов:
Вы уже правильно создали папкуfonts
в директорииsrc-tauri
и добавили в нее необходимые шрифты. Это первый и важный шаг. -
Настройка конфигурации Tauri:
В вашем файлеtauri.conf.json
вы указали:"bundle": { "resources": ["fonts/*"] }
Это правильно, так как позволяет Tauri упаковывать ваши файлы ресурсов.
-
Проблема с доступом к файлам ресурсов на Android:
Как вы заметили, использованиеFile::open()
вызывает ошибкуNotFound
. Это связано с тем, что Android обрабатывает ресурсы иначе, чем Windows. Android хранит ресурсы в пакете приложения, и их нельзя открывать с помощью стандартных операций ввода-вывода Rust.
Использование Tauri Assets API
Вместо использования стандартного ввода-вывода Rust, рекомендуется использовать API ресурсов Tauri для доступа к содержимому файлов. Вот как вы можете это сделать:
use tauri::Assets;
fn read_font_file(assets: &Assets, name: &str) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let font_path = format!("fonts/{}", name);
let font_data = assets.get(&font_path).ok_or("Font not found")?;
Ok(font_data.into_owned())
}
// Применение в вашем коде:
let app_handle = // ... получить вашу ссылку на приложение
let assets = app_handle.assets_handle();
match read_font_file(&assets, "Calibri-Regular.ttf") {
Ok(font_data) => {
// Используйте font_data (Vec<u8>) по мере необходимости
println!("Font data loaded, size: {} bytes", font_data.len());
},
Err(e) => eprintln!("Failed to load font: {}", e),
}
Создание временного файла
Если вам необходимо работать с данными шрифта в виде файла (например, если вы используете библиотеку, которая требует путь к файлу), вы можете записать данные во временный файл. Вот пример:
use std::io::Write;
use tempfile::NamedTempFile;
fn create_temp_font_file(font_data: Vec<u8>) -> Result<NamedTempFile, std::io::Error> {
let mut temp_file = NamedTempFile::new()?;
temp_file.write_all(&font_data)?;
Ok(temp_file)
}
// Применение:
let font_data = read_font_file(&assets, "Calibri-Regular.ttf")?;
let temp_file = create_temp_font_file(font_data)?;
let temp_path = temp_file.path();
// Используйте temp_path по мере необходимости
Этот код создает временный файл, который будет автоматически удален, когда выйдет из области видимости.
Заключение
Используя вышеуказанные шаги, вы сможете правильно получить доступ к шрифтам и другим ресурсам в Tauri на платформе Android. Избегайте использования стандартных операций ввода-вывода для работы с ресурсами, упакованными в приложение. Вместо этого используйте API ресурсов для чтения данных и создавайте временные файлы, если это необходимо. Это гарантирует, что ваше приложение будет работать корректно на всех поддерживаемых платформах.