NeetSonic 2024-04-20 09:49 采纳率: 50%
浏览 6
已结题

Android写入文件到内部存储失败

初学andriod,项目 target API :31
在manifest中:

    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

在MainActivity.kt中:

class MainActivity : ComponentActivity() {
    @RequiresApi(Build.VERSION_CODES.R)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ActivityCompat.requestPermissions(this, arrayOf(
                Manifest.permission.MANAGE_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE,
            ), 1)
        var customers = arrayOf(
            Customer("张三", "123", "张三店铺", "cc"),
            Customer("李四","5656","李四店铺","dd")
        )
//        val vals = ContentValues()
//        vals.put(MediaStore.Files.FileColumns.DISPLAY_NAME, "customer.json")
//        vals.put(MediaStore.Files.FileColumns.MIME_TYPE, "text/plain")
//        vals.put(MediaStore.Files.FileColumns.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS)
//        val uri = contentResolver.insert(MediaStore.Files.getContentUri("external"), vals)
//        if (uri != null) {
//            val outStream = contentResolver.openOutputStream(uri)
//            if(outStream != null){
//                outStream.write(Gson().toJson(customers).toByteArray())
//                outStream.close()
//            }
//        }
        FileWriter(Environment.getDataDirectory().name + "\\" + "customer.json").use { w -> w.write(Gson().toJson(customers)) }
        setContent {
            //...
        }
    }

使用FileWriter报错:
java.io.FileNotFoundException: data\customer.json (Read-only file system)

使用OutputStream报错:
java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/file from pid=6532, uid=10063 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-20 09:49
    关注

    引自免费微信小程序:皆我百晓生

    看起来你在尝试将数据保存到Android设备的内部存储中,但遇到了权限问题。在Android 10(API级别29)及更高版本中,访问外部存储需要遵循Scoped Storage规则。这意味着你需要针对每个应用创建一个私有的目录来保存数据,而不是直接写入像Environment.getExternalStorageDirectory()这样的公共路径。

    为了在Android 11及以上版本正确地保存文件,你应该使用getExternalFilesDir()方法获取到应用的私有外部存储目录,然后在这个目录下创建文件。同时,确保在运行时请求必要的权限。以下是修改后的代码示例:

    首先,删除不需要的权限,只保留读写内部存储的权限:

    <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
    

    接下来,在Java代码中,使用以下方式保存文件:

    import android.os.Environment
    import android.content.Context
    import java.io.File
    import java.io.FileWriter
    import java.io.IOException
    import android.util.Log
    import androidx.core.app.ActivityCompat
    import androidx.core.content.ContextCompat
    
    class MainActivity : AppCompatActivity() {
    
        private const val FILE_NAME = "customer.json"
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            if (ContextCompat.checkSelfPermission(
                    this,
                    Manifest.permission.WRITE_INTERNAL_STORAGE
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                ActivityCompat.requestPermissions(
                    this,
                    arrayOf(Manifest.permission.WRITE_INTERNAL_STORAGE),
                    1
                )
            } else {
                saveDataToFile()
            }
        }
    
        override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
            if (requestCode == 1 && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                saveDataToFile()
            } else {
                Log.wtf("MainActivity", "Permission denied for saving data to file.")
            }
        }
    
        private fun saveDataToFile() {
            val customers = arrayOf(
                Customer("张三", "123", "张三店铺", "cc"),
                Customer("李四", "5656", "李四店铺", "dd")
            )
    
            val directory = getExternalFilesDir(null)?.let { it.toAbsolutePath() } ?: return
            val file = File(directory.toString(), FILE_NAME)
    
            try {
                val writer = FileWriter(file)
                writer.append(Gson().toJson(customers))
                writer.flush()
                writer.close()
                Log.d("MainActivity", "Data saved successfully to $file")
            } catch (e: IOException) {
                Log.e("MainActivity", "Error while saving data to file", e)
            }
        }
    }
    

    这个代码片段做了以下几件事:

    1. 使用requestPermissions()请求写入内部存储的权限。
    2. onRequestPermissionsResult()处理权限结果,如果有权限则调用saveDataToFile()方法。
    3. saveDataToFile()方法中,我们从getExternalFilesDir()获取应用的私有外部存储目录,然后在此目录下创建文件并写入数据。

    注意:这里的代码没有包含错误处理和异常处理,实际使用时,可能需要添加更多的错误检查和日志记录。此外,Customer类需要你自己定义。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 4月28日
  • 已采纳回答 4月20日
  • 创建了问题 4月20日

悬赏问题

  • ¥15 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?