Android-R/W至可移动SD卡

Android-R/W至可移动SD卡,android,kotlin,Android,Kotlin,我正在创建一个应用程序,它可以将文件从内部存储(我的意思是/storage/emulated/0/*)移动到外部可移动存储(micro-SD卡)。我找到了SD卡根目录的路径,但无法在那里创建文件夹或移动文件。我不知道该怎么做才能让它工作。 我发现了一种叫做存储访问框架的东西,但我不明白如何使用它。 如果您能帮助我获得特定SD卡根路径的读/写权限,我将不胜感激 先谢谢你 自api 19(KitKat)以来,几乎不可能将SD卡内容作为一个简单的文件直接写入SD卡,因为至少对于默认用户,SD卡内容是以

我正在创建一个应用程序,它可以将文件从内部存储(我的意思是/storage/emulated/0/*)移动到外部可移动存储(micro-SD卡)。我找到了SD卡根目录的路径,但无法在那里创建文件夹或移动文件。我不知道该怎么做才能让它工作。 我发现了一种叫做存储访问框架的东西,但我不明白如何使用它。 如果您能帮助我获得特定SD卡根路径的读/写权限,我将不胜感激

先谢谢你

自api 19(KitKat)以来,几乎不可能将SD卡内容作为一个简单的
文件直接写入SD卡,因为至少对于默认用户,SD卡内容是以只读方式装入的(系统仍然可以写入)

API相当复杂(即使是文档中的示例也是很难理解的),这就是为什么添加API来模拟
文件
行为,以便于访问

假设用户已经被授予读/写存储权限,我们需要获取SDcard根目录的文档URI(在
活动中)

我将省略大多数错误检查/文件存在验证,但现在您可以像这样使用获取的
sdCardUri
(将文件“sample.txt”从内部存储根目录复制到SDcard根目录):

以及其他方法(从SD卡到内部存储):


谢谢你的解释。我还是不明白,为什么这么难。很高兴你这么快就帮了我。:)@如果您不知道为什么API中的某些内容被删除和/或混淆,默认答案是“安全性”。如果您觉得我的代码示例有帮助,请将答案标记为已接受。
var sdCardUri : Uri? = null

private fun requestSDCardPermissions(){
    if(Build.VERSION.SDK_INT < 24){
        startActivityForResult(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), REQ_PICK_DIRECTORY)
        return
    }
    // find removable device using getStorageVolumes
    val sm = getSystemService(Context.STORAGE_SERVICE) as StorageManager
    val sdCard = sm.storageVolumes.find { it.isRemovable }
    if(sdCard != null){
        startActivityForResult(sdCard.createAccessIntent(null), REQ_SD_CARD_ACCESS)
    }
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if(requestCode == REQ_SD_CARD_ACCESS || requestCode == REQ_PICK_DIRECTORY){
        if(resultCode == RESULT_OK) {
            if(data == null){
                Log.e(TAG, "Error obtaining access")
            }else{
                sdCardUri = data.data
                Log.d("StorageAccess", "obtained access to $sdCardUri")
                // optionally store uri in preferences as well here { ... }
            }
        }else
            Toast.makeText(this, "access denied", Toast.LENGTH_SHORT).show()
        return
    }
    super.onActivityResult(requestCode, resultCode, data)
}
private fun copyToSDCard(){
    val sdCardRoot = DocumentFile.fromTreeUri(this, sdCardUri)
    val internalFile = File(Environment.getExternalStorageDirectory(), "sample.txt")
    // get or create file
    val sdCardFile = sdCardRoot.findFile("sample.txt") ?: sdCardRoot.createFile(null, "sample.txt")
    val outStream = contentResolver.openOutputStream(sdCardFile.uri)
    outStream.write(internalFile.readBytes())
    outStream.flush()
    outStream.close()
    Toast.makeText(this, "copied to SDCard", Toast.LENGTH_SHORT).show()
}
private fun copyToInternal(){
    val sdCardRoot = DocumentFile.fromTreeUri(this, sdCardUri)
    val internalFile = File(Environment.getExternalStorageDirectory(), "sample.txt")
    val sdCardFile = sdCardRoot.findFile("sample.txt")
    val inStream = contentResolver.openInputStream(sdCardFile.uri)
    internalFile.writeBytes(inStream.readBytes())
    inStream.close()
    Toast.makeText(this, "copied to internal", Toast.LENGTH_SHORT).show()
}