【问题标题】:Kotlin - Create directory in Environment.getExternalStorageDirectory().getAbsolutePath() on Android 10+Kotlin - 在 Android 10+ 上的 Environment.getExternalStorageDirectory().getAbsolutePath() 中创建目录
【发布时间】:2021-09-10 18:02:02
【问题描述】:

以前有人问过这个问题,但我找不到适合我的答案。

我有一个应用程序,在第一次运行时,我需要在这些目录中创建一些目录和文件。

到目前为止,我所做的工作在 Android 5 到 9 上运行良好。 令我惊讶的是,它在 Android 10+ 上不起作用,因为 getExternalStorageDirectory() 已被弃用。

这就是我目前正在做的事情:

if(isFirstRun)
{
    Log.i("MyApp","ServerWizardActivity > createNecesaryFoldersFiles > isFirstRun")

    val absoluteExternalStorageDirectory = Environment.getExternalStorageDirectory().getAbsolutePath()
    val appDirectory = File("${absoluteExternalStorageDirectory}/MyApp/")
    val picturesDirectory = File("${absoluteExternalStorageDirectory}/Pictures/")

    val fullPath: String? = "${absoluteExternalStorageDirectory}/MyApp/${jsonFileName}"
    var dataFile = File(fullPath)

    if (!appDirectory .exists())
    {
        Log.i("MyApp","ServerWizardActivity > createNecesaryFoldersFiles > appDirectory")

        appDirectory .mkdir()
    }

    if (!picturesDirectory.exists())
    {
        Log.i("MyApp","ServerWizardActivity > createNecesaryFoldersFiles > picturesDirectory")

        picturesDirectory.mkdir()
    }

    if(!dataFile.exists())
    {
        Log.i("MyApp","ServerWizardActivity > createNecesaryFoldersFiles > dataFile")

        dataFile.createNewFile()
    }
}
else
{
    Log.i("MyApp","ServerWizardActivity > createNecesaryFoldersFiles > isNotFirstRun")
}

到目前为止一切顺利。 但是,我需要直接在Device Storage上创建一个目录,与DCIM、Pictures、Documents和Downloads处于同一级别,这样我才能使其与Android 5-9版本和iOS版本的应用程序保持一致。

我为 Android 10+ 尝试了下面的代码,它可以工作,但我只能在 Environment 中的一个目录(在本例中为 Pictures 目录)中创建一个目录。 有没有办法绕过?我不想因此而改变整个应用程序结构。

if(isFirstRun)
    {
        val resolver = contentResolver
        val contentValues = ContentValues()
        contentValues.put(
            MediaStore.MediaColumns.RELATIVE_PATH,
            Environment.DIRECTORY_PICTURES + "/MyApp"
        )
        val path = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).toString()
        val folder = File(path)
        val isCreated = folder.exists()

        if (!isCreated)
        {
            folder.mkdirs()
        }
    }

哦,到目前为止,我的 Android 清单文件中有这些:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

<application
    android:requestLegacyExternalStorage="true"
</application>

【问题讨论】:

  • 也许您可以使用ACTION_OPEN_DOCUMENT_TREE 并让用户决定用户的设备(或用户的 选择的云存储提供商)您的应用应存储用户的内容。
  • @CommonsWare - 这不取决于我。而且由于该应用程序必须像 iOS 版本一样工作,我也必须更改该应用程序,这不是一个选择。
  • 用户,在您的应用程序之外,可以从外部存储根目录创建一个目录,但是用户没有办法(除了通过ACTION_OPEN_DOCUMENT_TREE)授予您对该目录的访问权限。如果您的应用将通过 Play 商店分发,那么您的 android:requestLegacyExternalStorage="true" 方法将在今年晚些时候开始失效,而且 Google 不太可能授予您使用 MANAGE_EXTERNAL_STORAGE 的豁免权。
  • @CommonsWare 感谢您的信息。不确定该应用程序是否会通过 PlayStore(iOS 版本在内部托管)。我会尝试看看如何在不过多影响功能的情况下更改结构。

标签: android kotlin directory storage mkdir


【解决方案1】:

尝试使用以下代码,它将帮助您在文档目录中创建一个测试目录。

//Make sure don't forget to ask runtime permission of read/write file
private fun writeFile(fileData: String, fileName: String) {
val dir = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    File(
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
            .toString() + "/" + "test"
    )
} else {
    File(
        Environment.getExternalStorageDirectory()
            .toString() + "/${Environment.DIRECTORY_DOCUMENTS}/" + "test"
    )
}
dir.apply {
    if (!this.exists()) this.mkdir()
    File(this, "$fileName.txt").apply {
        if (!this.exists()) this.createNewFile()
        FileOutputStream(this).apply {
            write(fileData.toByteArray())
            close()
        }
    }
}
}

【讨论】:

  • 谢谢。会试一试。问题是我需要在级别上创建的目录,与 DIRECTORY_DOCUMENTS 处于同一级别,而不是在其中。整个应用一开始就是这样设计的。
  • 不幸的是,在我的手机上运行应用程序时,我不断收到此错误:“java.io.IOException:没有这样的文件或目录”。由于某种原因,我无法创建 A10 AVD 来对其进行测试,因为我一直在运行 BSOD...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-29
  • 2012-12-04
  • 2016-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多