15

我对android开发很陌生,我需要初学者的帮助...

我正在创建一个应用程序,它应该有 2 个目录,一个数据库目录和一个图像目录,就像 Whatsapp 一样。

当我浏览手机时,我想在文件管理器中查看这些目录,就像您查看其他应用程序文件夹一样。我尝试了在这里找到的所有内容,在内部存储和外部存储中从代码中创建它。文件夹似乎已创建,但是当我浏览手机的文件管理器时,我找不到带有我的应用名称的文件夹以及其中的数据库和图像文件夹......我做错了什么?我需要在 android studio 中创建这些文件夹作为添加文件夹吗?还是我需要从代码中创建它?

你能告诉我完成这项任务需要采取的行动吗?我正在使用安卓工作室 3.1.3。感谢帮助者!:)

4

2 回答 2

23

术语“内部存储”和“外部存储”一开始可能会让人感到困惑,因为 Google 的意图与我们从日常语言使用中所期望和了解的不同:“外部”并不一定意味着“ SD卡”。这家伙写了一篇关于术语混淆的好文章

根据您的意图,您可能希望使用外部存储概念。文档中对这些差异进行了很好的解释,但我将在这里简要介绍一下。

最后,我将为您提供一个示例,但首先让我们了解基础知识:

内部存储器

  • 只有您的应用可以访问文件
  • 卸载您的应用程序时会删除文件
  • 文件始终可用(这意味着它们的文件永远不会保存在可移动存储器上)

外部存储

  • 其他应用程序可以完全读取文件(包括文件管理器应用程序的任何变体,在您的情况下)
  • 卸载您的应用程序时不一定会删除文件 - 稍后解释
  • 无法保证文件的可用性(可以被其他应用程序/可移动内存删除)

所以现在我们知道您需要外部存储,在开始之前需要做几件事:

  • Manifest.xml根据您的需要,在文件中需要权限(读/写) :
    <manifest ...>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
    </manifest>

每个权限都是独立的,这意味着您不需要同时拥有这两个权限,例如,如果您只想读取文件而不是写入文件

  • 验证存储是否可用- 这是在运行时完成的,并且在文档中进行了很好的解释。我们需要确保存储已安装到设备中/它的状态不会以某种方式导致读/写请求失败的问题。

示例时间!

在给定的方法中,我们将在根目录中保存一个文本文件。

这篇文章的学分

public void writeFileExternalStorage() {

    //Text of the Document
    String textToWrite = "bla bla bla";

    //Checking the availability state of the External Storage.
    String state = Environment.getExternalStorageState();
    if (!Environment.MEDIA_MOUNTED.equals(state)) {

        //If it isn't mounted - we can't write into it.
        return;
    }

    //Create a new file that points to the root directory, with the given name:
    File file = new File(getExternalFilesDir(null), filenameExternal);

    //This point and below is responsible for the write operation
    FileOutputStream outputStream = null;
    try {
        file.createNewFile();
        //second argument of FileOutputStream constructor indicates whether
        //to append or create new file if one exists
        outputStream = new FileOutputStream(file, true);

        outputStream.write(textToWrite.getBytes());
        outputStream.flush();
        outputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

我想具体回答你的一些问题:

我需要在 android studio 中创建这些文件夹作为添加文件夹吗?还是我需要从代码中创建它?

绝对不是通过 Android Studio。这些是您的项目文件夹,包含您的代码。上面提到了它的方法。

我找不到包含我的应用程序名称的文件夹以及其中的数据库和图像文件夹......我做错了什么?

正如您之前提到的,可能将您的文件保存为内部存储文件/将它们保存为项目文件夹 - 这些不会(也不应该)出现。


有用的知识

有两种类型的目录:公共的和私有的。

私人的

  • 媒体商店无法访问
  • 卸载应用程序时删除文件
  • getExternalFilesDir(...)通过方法检索

示例:目录(在我的WhatsApp手机中)位于根级别。调用它是:getExternalFilesDir("WhatsApp/...")

公共(下载/电影/图像库)

  • 文件由MediaStore扫描
  • Environment.getExternalStoragePublicDirectory(...)通过方法检索

示例:获取Documents文件夹如下所示:Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)

于 2018-07-28T02:17:46.147 回答
2

主要答案真的帮助了我,如果没有那个很好的答案,我就无法做到这一点。

但是我在获取存储目录时遇到了一些困难(因为随着时间的推移对 API 的更改),而且我使用的是 Kotlin,所以我想我只是分享我使用的最终代码。

我的还返回一条字符串消息(文件的绝对路径为成功,否则为错误消息)。

我还添加了一些日志语句,以便您可以看到正在发生的事情。

fun writeFileExternalStorage() :String {

        var fileData : String = "test this"
        
        Log.i("FirstFrag", "in writeFileExternalStorage")
        //Checking the availability state of the External Storage.
        val state = Environment.getExternalStorageState()
        if (Environment.MEDIA_MOUNTED != state) {

            Log.i("FirstFrag", "Couldn't get file system.")
            return "Couldn't write file."
        }

        var file =File(requireContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "test.txt")

        Log.i("FirstFrag", file.absolutePath)
        //This point and below is responsible for the write operation
        var outputStream: FileOutputStream? = null
        try {
            Log.i("FirstFrag", "creating new file")
            file.createNewFile()
            Log.i("FirstFrag", "file created")
            //second argument of FileOutputStream constructor indicates whether
            //to append or create new file if one exists
            outputStream = FileOutputStream(file, true)
            outputStream?.write(fileData.toByteArray())
            outputStream?.flush()
            outputStream?.close()
            Log.i("FirstFrag", "wrote file!")
            return file.absolutePath
        } catch (e: Exception) {
            Log.i("FirstFrag",e.message.toString())
            return e.message.toString() + "\nPlease check that you have a valid filename."
        }
        finally {
            isRetrievingFile = false;
        }
    }
于 2021-06-03T16:31:36.637 回答