namespace Stary.Evo { using System; using System.IO; using YooAsset; public class CopyLocalFileServices : ICopyLocalFileServices { private class AndroidWrapper { public static void CopyAssetFile(string assetPath, string destPath) { // 注意:请实现安卓平台拷贝内置文件的原生接口 } } public void CopyFile(LocalFileInfo sourceFileInfo, string destFilePath) { #if UNITY_ANDROID // 安卓平台包体内文件的拷贝走安卓原生方法 if (IsBuildinSourceFile(sourceFileInfo.SourceFileURL)) { // SourceFileURL示例 jar:file:///apk_path!/assets/yoo/DefaultPackage/xxxxxx.bundle AndroidWrapper.CopyAssetFile(sourceFileInfo.SourceFileURL, destFilePath); } else { string sourceFilePath = ConvertFileUriToPath(sourceFileInfo.SourceFileURL); File.Copy(sourceFilePath, destFilePath); } #elif UNITY_OPENHARMONY // 鸿蒙平台处理方式 ...... #else // 其它平台本地文件拷贝走正常方法 string sourceFilePath = ConvertFileUriToPath(sourceFileInfo.SourceFileURL); File.Copy(sourceFilePath, destFilePath); #endif } // 检测本地文件URL地址是否为安卓内包体文件 private bool IsBuildinSourceFile(string fileURL) { if (string.IsNullOrEmpty(fileURL)) return false; // 判断是否包含APK路径特征 return fileURL.StartsWith("jar:file://", StringComparison.OrdinalIgnoreCase) && fileURL.Contains("!/assets/"); } // 本地文件URL地址转换为标准文件路径 public static string ConvertFileUriToPath(string uri) { if (string.IsNullOrEmpty(uri)) return uri; // 处理标准 file:// URL if (uri.StartsWith("file://", StringComparison.Ordinal)) { // 去除 file:// 前缀 string path = uri.Substring(7); // 处理 Android 特殊格式 (file:/// 后跟绝对路径) if (path.StartsWith("//")) return path.Substring(1); else return path; } return uri; } } }