Android Kotlin开发:无法读取外部存储目录及文件问题求助
解决Android API26下无法读取外部存储目录的问题
针对你遇到的目录存在但无法读取、listFiles()返回null的问题,核心原因是权限请求未处理回调逻辑,加上可能的权限请求不完整,以下是具体解决步骤:
1. 补全权限请求的回调处理
你当前只发起了权限请求,但未处理用户授权后的操作。当用户点击允许权限后,需要在回调中重新执行文件读取逻辑。
2. 同时请求读写存储权限
虽然API23+中同一权限组的权限会被同时授予,但为了兼容性,建议同时请求READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE。
3. 抽离文件读取逻辑,避免重复代码
将读取文件的代码封装成独立方法,方便在权限校验通过和回调成功时复用。
修改后的完整代码示例
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) if (checkPermission()) { loadFiles() } else { requestPermission() } if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .replace(R.id.container, MainFragment.newInstance()) .commitNow() } } // 检查读写权限是否都已授予 private fun checkPermission(): Boolean { val readGranted = ContextCompat.checkSelfPermission( this, Manifest.permission.READ_EXTERNAL_STORAGE ) == PackageManager.PERMISSION_GRANTED val writeGranted = ContextCompat.checkSelfPermission( this, Manifest.permission.WRITE_EXTERNAL_STORAGE ) == PackageManager.PERMISSION_GRANTED return readGranted && writeGranted } // 请求读写存储权限 private fun requestPermission(){ val shouldShowRationale = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) if(shouldShowRationale){ Toast.makeText(this, "需要存储权限来访问文件", Toast.LENGTH_SHORT).show() } else { ActivityCompat.requestPermissions( this, arrayOf( Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE ), 111 ) } } // 处理权限请求结果 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if(requestCode == 111){ if(grantResults.isNotEmpty() && grantResults.all { it == PackageManager.PERMISSION_GRANTED }){ loadFiles() } else { Toast.makeText(this, "存储权限被拒绝,无法访问文件", Toast.LENGTH_SHORT).show() } } } // 封装文件读取逻辑 private fun loadFiles(){ val rootDir = Environment.getExternalStorageDirectory() Log.d("FILETAG", "路径: ${rootDir.path}") Log.d("FILETAG", "是否存在: ${rootDir.exists()}") Log.d("FILETAG", "是否可读: ${rootDir.canRead()}") val filesAndFolders = rootDir.listFiles() if(filesAndFolders != null){ Log.d("FILETAG", "文件/文件夹数量: ${filesAndFolders.size}") // 将数据传递给Fragment,可通过ViewModel或接口回调 // 示例(假设使用ViewModel): // yourViewModel.updateFiles(filesAndFolders.toList()) } else { Log.e("FILETAG", "无法列出文件,目录不可读") } }
针对Fragment的补充说明
如果需要在Fragment中实现读取逻辑,可以直接在Fragment内处理权限请求和文件读取:
- 在Fragment中使用
requestPermissions()方法发起请求 - 重写Fragment的
onRequestPermissionsResult()处理回调 - 确保Fragment和Activity的权限请求逻辑保持一致,避免冲突
内容的提问来源于stack exchange,提问作者Phoenonical
相关产品推荐
相关产品推荐

