Unity安卓端无法保存TXT文件至内部存储,求解决方案
嘿,我来帮你搞定Unity安卓上保存TXT文件的问题~
你的代码在电脑上能跑,但到安卓就失效,核心问题出在硬编码路径不可靠和安卓新系统的存储权限限制上,我给你一步步拆解解决方案:
问题根源
- 硬编码路径不通用:
/sdcard/Download/这种路径在不同安卓设备、不同系统版本里可能不一样,而且Android 10+引入了「分区存储(Scoped Storage)」,直接读写公共目录会被系统限制。 - 权限缺失或无效:即使你申请了存储权限,新系统也不允许直接访问公共目录的路径,必须用官方API来操作。
解决方案1:用Unity官方安全路径(推荐)
Unity提供了跨平台的持久化存储路径Application.persistentDataPath,这个路径是每个应用专属的安全目录,安卓上对应Android/data/[你的应用包名]/files/,不需要额外权限,也不会被系统随意清理。
修改后的代码如下:
using UnityEngine; using System.IO; using UnityEngine.UI; public class Click2 : MonoBehaviour { public void OnClick() { // 用Unity官方的跨平台持久化路径,自动适配安卓/Windows/iOS string saveLocation = Application.persistentDataPath; // 确保目录存在(虽然persistentDataPath默认会创建,但好习惯还是加上) if (!Directory.Exists(saveLocation)) { Directory.CreateDirectory(saveLocation); } // 用Path.Combine自动处理路径分隔符,避免跨平台格式错误 string filePath = Path.Combine(saveLocation, "1.txt"); // using语句会自动释放文件资源,不用手动Close(),更安全 using (StreamWriter file = new StreamWriter(filePath, true)) { file.Write("a"); } } }
解决方案2:保存到公共Download目录(Android 10+)
如果你一定要把文件存到系统的Download公共目录,就得用安卓原生的MediaStoreAPI来绕过分区存储限制,下面是Unity调用安卓原生代码的示例:
using UnityEngine; using System.IO; public class SaveToPublicDownload : MonoBehaviour { public void SaveToDownload() { string content = "a"; string fileName = "1.txt"; #if UNITY_ANDROID && !UNITY_EDITOR // 调用安卓原生的MediaStore API AndroidJavaClass mediaStore = new AndroidJavaClass("android.provider.MediaStore"); AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); AndroidJavaObject contentResolver = currentActivity.Call<AndroidJavaObject>("getContentResolver"); AndroidJavaObject contentValues = new AndroidJavaObject("android.content.ContentValues"); // 设置文件名称和类型 contentValues.Call<AndroidJavaObject>("put", mediaStore.GetStatic<string>("MediaColumns.DISPLAY_NAME"), fileName); contentValues.Call<AndroidJavaObject>("put", mediaStore.GetStatic<string>("MediaColumns.MIME_TYPE"), "text/plain"); // 指定保存到Download目录 contentValues.Call<AndroidJavaObject>("put", mediaStore.GetStatic<string>("MediaColumns.RELATIVE_PATH"), "Download"); // 插入文件并获取Uri AndroidJavaObject uri = contentResolver.Call<AndroidJavaObject>("insert", mediaStore.GetStatic<AndroidJavaObject>("Downloads.EXTERNAL_CONTENT_URI"), contentValues); if (uri != null) { AndroidJavaObject outputStream = contentResolver.Call<AndroidJavaObject>("openOutputStream", uri); if (outputStream != null) { // 将字符串转为字节数组写入文件 byte[] bytes = System.Text.Encoding.UTF8.GetBytes(content); outputStream.Call("write", bytes); outputStream.Call("close"); Debug.Log("文件已成功保存到Download目录!"); } } #else // 编辑器或其他平台用持久化路径替代 string savePath = Path.Combine(Application.persistentDataPath, fileName); using (StreamWriter sw = new StreamWriter(savePath, true)) { sw.Write(content); } Debug.Log($"编辑器模式下保存路径:{savePath}"); #endif } }
权限补充说明
- Android 9及以下:需要在Unity的
PlayerSettings > Android > Publishing Settings里启用自定义Manifest,添加权限:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - Android 10+:用上面的
MediaStore方式不需要申请存储权限,系统会自动允许写入公共目录。
内容的提问来源于stack exchange,提问作者Muhammad Hussain




