正确写法只能在真机Android App运行,H5和模拟器无效;iOS不支持,须用原生插件或uni.getFileSystemManager()间接估算:先调用plus.android.invoke(file, "getPath")获取路径字符串再初始化StatFs,避免直接传File对象报错,且必须用plus.android.invoke()调用getAvailableBlocks()和getBlockSize()方法。

uni-app 中 plus.android 获取 Android 可用存储空间的正确写法
只能在真机 Android App 环境下运行,H5 和模拟器完全无效;iOS 不支持该方式,必须走原生插件或 uni.getFileSystemManager() 间接估算。
核心是绕过 Java 对象调用陷阱:不能直接把 File 对象传给 StatFs 构造函数(旧写法会报错),必须先用 plus.android.invoke(file, "getPath") 拿到路径字符串再初始化。
-
Environment.getDataDirectory()返回的是内部存储(/data/data/xxx),不是用户可见的“手机内存”——但它是唯一无需权限即可访问的路径 - 若想查外部 SD 卡或公共目录(如
Environment.getExternalStorageDirectory()),需先申请android.permission.READ_EXTERNAL_STORAGE,且 Android 10+ 强制启用 Scoped Storage,路径行为已变更 -
getAvailableBlocks()和getBlockSize()必须用plus.android.invoke()调用,不能直接点语法(否则返回 undefined 或报错) - 计算结果单位易错:
1024 * 1024 * 1024是 GiB(二进制 GB),不是十进制 GB;显示时建议保留两位小数并标注单位,如"${gb} GB (GiB)"
const environment = plus.android.importClass("android.os.Environment");
const statFs = plus.android.importClass("android.os.StatFs");
const file = environment.getDataDirectory();
const path = plus.android.invoke(file, "getPath"); // ⚠️ 关键一步
const fs = new statFs(path);
const blockSize = plus.android.invoke(fs, "getBlockSize");
const availBlocks = plus.android.invoke(fs, "getAvailableBlocks");
const bytes = blockSize * availBlocks;
iOS 平台为什么不能用 plus.ios 类似方式?
iOS 系统不开放磁盘总容量和剩余空间的公开 API 给第三方 App,这是系统级限制,不是 uni-app 能绕过的。
你看到的“设置 → 通用 → iPhone 存储空间”界面,是系统私有框架渲染的,App 进程无权读取。任何声称“纯 JS 获取 iOS 总存储”的方案,要么是伪造数据,要么依赖越狱环境。
- 部分插件市场所谓“iOS 获取内存”的插件,实际只是返回 App 沙盒内
tmp或Documents目录的可用空间(用NSFileManager查询),和整机存储无关 - 如果你需要在 iOS 上做空间预警,只能靠业务逻辑预估:比如下载前检查当前沙盒剩余是否 > 500MB,用
plus.ios.invoke(manager, "URLForDirectory:inDomain:appropriateForURL:create:error:", ...)定位目录再查空间 - 别信“用
cordova-plugin-device扩展就能拿到 iOS 总空间”的说法——它在 iOS 上对 storage 字段始终返回 null 或占位值
用 uni.getFileSystemManager() 做轻量级空间探测(跨平台 fallback)
它不能告诉你“手机还剩多少 GB”,但能帮你判断“当前是否快写不进文件了”,适合做上传/缓存前的安全检查。
原理是尝试写入一个临时小文件,捕获失败时的错误码,反推空间状态。虽然粗糙,但不依赖原生权限、兼容 H5/App/小程序,且 iOS 也能跑。
- 错误码
fail no space或fail system error(具体看平台)可能暗示空间不足,但不是 100% 可靠——也可能是权限/路径问题 - 建议只用于“临界预警”:比如连续 3 次写入 1MB 临时文件失败,就提示用户清理空间,而不是用来展示精确数字
- 不要在主线程反复调用,避免卡顿;可设防抖,或仅在关键操作(如拍照后保存)前执行一次
const fs = uni.getFileSystemManager();
fs.writeFile({
filePath: `${uni.env.USER_DATA_PATH}/test.tmp`,
data: new Array(1024 * 1024).fill(0),
encoding: 'binary',
success: () => console.log('空间足够'),
fail: (e) => {
if (e.errMsg.includes('no space') || e.errMsg.includes('system error')) {
uni.showToast({ title: '存储空间不足', icon: 'none' });
}
}
});
插件市场那些“内存检测”插件,哪些能信?
搜 “存储空间”“内存检测”“disk space”,结果里 80% 是 Android 专用、iOS 返回假数据、或者根本没处理 Android 10+ Scoped Storage 的老插件。
真正可用的插件极少,且必须满足两个条件:Android 部分用 StatFs 查 /data,iOS 部分明确声明“仅返回沙盒空间”,并提供清晰的平台差异文档。
- 推荐优先自查插件源码:Android 的
Plugin.java是否调用了StatFs+getDataDirectory().getPath();iOS 的.m文件是否用了[[NSFileManager defaultManager] attributesOfFileSystemForPath:error:] - 避开名字带“一键获取全部内存”“全自动检测”的插件——这种大概率是把
Runtime.getRuntime().maxMemory()(Java 堆内存)误当成磁盘空间返回 - 如果项目要上架 App Store,慎用任何调用私有 API(如
NSProcessInfo.processInfo().physicalMemory)的插件,可能被拒审
实际开发中,最常被忽略的是:Android 10+ 上 Environment.getExternalStorageDirectory() 已被废弃,且返回路径不可写;而 getDataDirectory() 虽安全,但数值远小于用户认知中的“手机剩余空间”——它只反映 App 自身沙盒容量。你要的到底是“系统级剩余”,还是“我这个 App 还能存多少”?目标没分清,代码就永远对不上预期。










