使用Kotlin在Android中无法创建.txt文件的问题求助
解决Android中创建.txt文件权限被拒的问题
核心问题分析
你遇到的Permission denied主要源于三个问题:
- 直接操作系统根目录
/,普通APP无权限访问该系统分区 - 仅在清单文件声明权限,未完成动态权限申请(危险权限需运行时用户授权)
- Android 10(API 29)及以上版本对外部存储实施了更严格的分区存储限制
具体解决步骤
1. 选择合法的文件存储目录
不要直接操作根目录,根据需求选择以下合规目录:
- APP内部存储:仅当前APP可访问,无需额外权限,卸载APP时文件会被自动删除
- APP专属外部存储目录:仅当前APP可访问,Android 10+无需权限,卸载时文件被删除
- 外部存储公共目录:如Downloads,需动态申请权限,Android 10+需适配分区存储规则
2. 动态申请危险权限
WRITE_EXTERNAL_STORAGE属于危险权限,API 23及以上版本必须在运行时请求用户授权:
private val REQUEST_STORAGE_PERMISSION = 100 fun checkStoragePermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_STORAGE_PERMISSION) } else { // 权限已授予,执行文件创建逻辑 createTxtFile() } } // 处理权限申请结果 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == REQUEST_STORAGE_PERMISSION) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { createTxtFile() } else { Toast.makeText(this, "需要存储权限才能创建文件", Toast.LENGTH_SHORT).show() } } }
3. 不同场景的文件创建代码示例
示例1:使用APP内部存储创建文件
fun createTxtFile() { val fileName = "documento.txt" // 获取内部存储的文件目录 val file = File(filesDir, fileName) if (!file.exists()) { try { file.createNewFile() Toast.makeText(this, "文件创建成功", Toast.LENGTH_SHORT).show() } catch (e: IOException) { e.printStackTrace() Toast.makeText(this, "创建失败:${e.message}", Toast.LENGTH_SHORT).show() } } else { Toast.makeText(this, "文件已存在", Toast.LENGTH_SHORT).show() } }
示例2:使用APP专属外部存储目录(Android 10+推荐)
fun createTxtFile() { val fileName = "documento.txt" // 获取APP专属外部存储目录,无需权限 val externalDir = getExternalFilesDir(null) externalDir?.let { val file = File(it, fileName) if (!file.exists()) { try { file.createNewFile() Toast.makeText(this, "文件创建成功", Toast.LENGTH_SHORT).show() } catch (e: IOException) { e.printStackTrace() Toast.makeText(this, "创建失败:${e.message}", Toast.LENGTH_SHORT).show() } } else { Toast.makeText(this, "文件已存在", Toast.LENGTH_SHORT).show() } } }
示例3:使用外部公共目录(如Downloads,需动态权限)
fun createTxtFile() { val fileName = "documento.txt" // 获取Downloads公共目录 val downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) val file = File(downloadsDir, fileName) if (!file.exists()) { try { file.createNewFile() Toast.makeText(this, "文件创建成功", Toast.LENGTH_SHORT).show() } catch (e: IOException) { e.printStackTrace() Toast.makeText(this, "创建失败:${e.message}", Toast.LENGTH_SHORT).show() } } else { Toast.makeText(this, "文件已存在", Toast.LENGTH_SHORT).show() } }
4. Android 10+额外适配
如果目标SDK版本为29及以上,需在清单文件的application标签中添加临时兼容配置:
<application ... android:requestLegacyExternalStorage="true">
若要完全适配分区存储规则,建议使用MediaStore API操作公共目录文件。
内容的提问来源于stack exchange,提问作者Looking for a answer ...
相关产品推荐
相关产品推荐

