关于Android平台Total Commander访问根目录(/)及自研应用权限受限的技术问询
关于Android平台Total Commander访问根目录(/)及自研应用权限受限的技术问询
兄弟,我太懂这种明明把能加的存储权限都加上了,结果自己的App还是被死死限制在/storage/emulated/0,但Total Commander却能随便逛根目录的憋屈感了!这事儿本质是Android从API29开始推行的分区存储(Scoped Storage)加上SELinux安全策略的双重限制,而Total Commander之所以能做到,是因为它针对不同Android版本做了极其细致的适配,绝非简单绕开规则。下面我给你拆解明白:
先搞懂你App权限失效的核心原因
你虽然在Manifest里声明了READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE和MANAGE_EXTERNAL_STORAGE这三个权限,但这里有两个容易踩的坑:
MANAGE_EXTERNAL_STORAGE的权限申请流程不对:这个是特殊权限,不能像普通危险权限那样在App内弹窗请求,必须引导用户到系统设置页面手动开启。如果你只是加了权限声明,却没走跳转设置的流程,那这个权限等于没生效。- 即使拿到权限,也碰不到系统保护目录:这个权限只是放开了外部存储所有文件的访问权,但根目录下的
/system、/data、/proc等系统核心目录,受SELinux安全策略严格限制,普通App哪怕权限拉满也访问不了——Total Commander能看到根目录,也只是展示了其中可访问的存储分区,不是真的能随便改系统目录。
Total Commander访问根目录的核心操作逻辑
Total Commander并没有“作弊”,它完全是在Android规则内玩的,核心是这几个操作:
- 针对不同Android版本的差异化适配:
- 在Android 10(API29)之前,它利用当时权限体系的宽松性,结合JNI调用底层文件操作API,枚举根目录下的可访问分区;
- 在API29及之后,它先引导用户授予“所有文件访问权限”(也就是
MANAGE_EXTERNAL_STORAGE),然后通过StorageManager的API获取所有挂载的存储卷,再把这些卷的根路径映射到自己的界面上,让你看起来像是在访问根目录。
- 自定义文件访问引擎:它没有用Android标准的
File类来枚举目录,而是自己实现了一套文件访问逻辑,结合存储访问框架(SAF)的扩展能力,绕过了FileAPI的权限限制,能更灵活地访问系统允许的存储路径。
给你App的适配建议
如果想让你的App也能像TC那样访问根目录下的可访问分区,可以这么做:
- 正确申请
MANAGE_EXTERNAL_STORAGE权限:
用这段代码引导用户到设置页面开启权限:if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (!Environment.isExternalStorageManager()) { val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) intent.data = Uri.parse("package:" + packageName) startActivity(intent) } } - 改用
StorageManagerAPI枚举存储卷:
别直接用File("/").listFiles()这种方式,而是通过系统API获取所有可访问的存储卷,再逐个访问:val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager val storageVolumes = storageManager.storageVolumes for (volume in storageVolumes) { // 获取该存储卷的访问Uri,通过SAF操作文件 val accessUri = volume.createAccessIntent(null) // 后续用DocumentFile等SAF相关API操作内容 } - 降低预期:哪怕做完这些,你还是碰不到
/system、/data这类系统目录,这是Android的底层安全机制,普通App根本绕不开——Total Commander也做不到,它展示的根目录只是可访问分区的集合而已。
内容来源于stack exchange
相关产品推荐
相关产品推荐

