【问题标题】:How do I let a user upload files to internal storage?如何让用户将文件上传到内部存储?
【发布时间】:2017-01-09 09:16:23
【问题描述】:

我正在编写一个小应用程序,该应用程序从设备外部的源(USB、蓝牙、Airdroid 等)读取必须定期写入设备存储的文件。根据我所读到的内容,没有类似的可以写入内部存储。我想管理内部存储中的文件以保护访问隐私。

我的第一个解决方案是让用户将文件写入外部存储,然后点击按钮将它们传输到内部存储的活动。如果这在 n 分钟内没有发生,则外部存储上的文件将被销毁。但是,我后来发现getExternalStorageDirectory 毫无用处,因为设备在内部存储上模拟外部存储,Android 不知道是否以及如何做到这一点。

但我想知道是否没有某种内置活动可以让用户直接从内部存储上传或下载文件,但不能像使用内部存储一样免费访问内部存储的整个文件结构.

作为最后的手段,也许我的应用程序可以通过 TCP 连接接收文件并将它们写入内部存储本身。它很乱,但试图找到一张 SD 卡也是如此。见问题Find an external SD card location

新: 本练习的目的是在 SD 卡上的一个目录中查找所有 .csv 文件,让用户选择一个,处理它,并将输出文件写入 SD 卡.用户将输入一个“权重”值,该值将用于处理文件的计算。

但是,由于 Android 在提供真正的外部存储(即 SD 卡)的位置方面非常不可靠,所以我想尝试将文件存储在内部存储中,Android 似乎更诚实和可靠地知道该位置的位置存储。

【问题讨论】:

  • 您可以将文件直接存储在内部存储中。 developer.android.com/training/basics/data-storage/files.html
  • @Prera​​kSola 但是怎么做?在问这个问题之前,我已经阅读了您链接到的文档,并且它清楚地说明了内部存储,“保存在此处的文件只能由您的应用程序访问”。所以这个问题的重点几乎是用户(不是我的应用程序,也无权访问内部存储)如何将文件放入内部存储。
  • 是你的问题,“如何写入用户可以访问的内部存储而不是data/data/package_name/这样做不会允许其他应用访问它
  • upload to 内部存储模糊。您的意思是,upload from 内部存储可能来自网络 write to 内部存储来自网络或外部资源?
  • @ZekeDran,“上传”对我来说不是那么模糊。我认为它清楚地表明,对于某些母语至少是英语的人来说,“内部存储”是目的地,即我想把文件放在那里,而不是读取它们或从那里取出它们。

标签: android file-transfer android-file


【解决方案1】:

TLDRgetExternalStorageDirectory()getExternalFilesDirs()[0](API 19+)应该返回“primary”存储位置,即内部存储.

编辑:如果您只是想写信给 eMMC 并且不关心它是私有的,只需使用 getFilesDir() 并保证您正在写信给eMMC


解释

为了避免晦涩和方便,我将使用以下术语

  1. PrivateStorage:应用程序在内存中的私有存储 - /data/data/package name
  2. eMMC:手机内部存储
  3. SD:手机的可扩展存储(可移动)

如果我对您的问题的理解正确,您不想写信给 PrivateStorage,这将允许其他应用访问该数据。因此,我们的目标是写信给 eMMC 更具体的,公开访问的 eMMC,而不是在 eMMC 应用的私人空间中

根据 Android Docs (API 1),

Environment.getExternalStorageDirectory() 返回 primary 外部存储目录。如果该目录已被用户安装在他们的计算机上、已从设备中删除或发生了其他问题,则该目录当前可能无法访问。您可以使用 getExternalStorageState() 确定其当前状态。

并且根据 API 19 docs

您现在可以在辅助外部存储介质上读取和写入特定于应用的文件,例如当设备同时提供模拟存储和 SD 卡时。新方法 getExternalFilesDirs() 的工作方式与现有的 getExternalFilesDir() 方法相同,只是它返回一个 File 对象数组。返回的 File 数组中的第一个条目被认为是 设备的“主要”外部存储,与getExternalFilesDir()等现有方法返回的File相同。

总结一下,getExternalStorageDirectory()getExternalFilesDirs()[0] 应该返回“primary”存储位置,即eMMC。但是在实践中你会注意到它返回的不一定eMMC,对于一些手机(KarbonnTitiniumS2、XoloX3000 和许多其他手机)

这里是第二句话的一些快照:这款手机 TitaniumS2 运行的是 4.2,所以我无法使用 getExternalFilesDirs()

您还可以注意到,出于同样的原因,ES Explorer错误地/sdcard0 识别为内部存储 (eMMC) 并且/sdcard1 作为新旧版本的外部存储 (SD),确实继续告诉用户 sdcard0 作为内部存储。

此外,还提出了用于查找 非主 (SD) 存储的 issue

似乎没有用于查找 非主要 外部存储设备的 API 功能,而且 google 无意修复这种情况,让应用程序使用 hacky 变通方法,例如解析所有当前安装的文件系统。对于当前一代的操作系统来说,不能正确支持访问插入的 USB 记忆棒上的文件这样基本的东西是非常糟糕的。

【讨论】:

  • @ProfK,如果你能确切地告诉你你想在你的应用程序中做什么,人们可以建议解决方法和可能的黑客攻击;你已经提到了它,但没有足够的细节(比如你想要最终实现的目标)来找到我认为的 hack :)
  • 我写信的目的不是阻止其他应用访问数据,而是因为 Android 知道数据在哪里,找到真正的外部存储在哪里是一项艰巨的任务。
  • 这个应用有什么用?它有什么作用?为什么要专门访问eMMC?这只是出于性能原因吗?
【解决方案2】:

希望对您有所帮助...

您可以获取用户想要上传的文件,并且可以读取数据...然后您想将它们写入您的应用程序路径...

如果我错了,请纠正我......

这里是您如何尝试将文件写入应用程序的路径...我的一个是/data/data/com.test.internalstorage/files

try {
    File filesDir = getApplicationContext().getFilesDir();
    Log.d(TAG, "  Files -> 1 context.getFilesDir()-=> " + filesDir);
    Log.d(TAG, "  Files -> 1 context.getFilesDir().getName-=> " + filesDir.get-name());
    Log.d(TAG, "  Files -> 1 context.getFilesDir().getAbsolutePath-=> " + filesDir.getAbsolutePath());
    Log.d(TAG, "  Files -> 1 context.getFilesDir().getCanonicalPath-=> " + filesDir.getCanonicalPath());
    Log.d(TAG, "  Files -> 1 context.getFilesDir().getPath-=> " + filesDir.getPath());
    String[] lst = getApplicationContext().getFilesDir().list();
    for (int i=0; i< lst.length; i++){
        Log.d(TAG, "  Files -> 1 context.getFilesDir()list("+i+")-=> " + lst[i]);
    }
    String FILENAME = "hello_file5";
    String string = "hello world!";

    FileOutputStream fos = null;

    fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
    fos.write(string.getBytes());
    fos.close();


    Log.d(TAG, "  Files ");"
    File nw_filesDir = getApplicationContext().getFilesDir();
    Log.d(TAG, "  Files -> 2 context.getFilesDir()-=> " + nw_filesDir);
    String[] nw_lst = getApplicationContext().getFilesDir().list();
    for (int i=0; i< nw_lst.length; i++){
        Log.d(TAG, "  Files -> 2 context.getFilesDir()list("+i+")-=>  " + nw_lst[i] +
                " -> " + new File(nw_filesDir,nw_lst[i]).getParentFile());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

输出是

D/_TAG_:   Files -> 1 context.getFilesDir()-=> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 1 context.getFilesDir().getName-=> files
D/_TAG_:   Files -> 1 context.getFilesDir().getAbsolutePath-=> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 1 context.getFilesDir().getCanonicalPath-=> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 1 context.getFilesDir().getPath-=> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 1 context.getFilesDir()list(0)-=> hello_file
D/_TAG_:   Files -> 1 context.getFilesDir()list(1)-=> hello_file2
D/_TAG_:   Files -> 1 context.getFilesDir()list(2)-=> hello_file3
D/_TAG_:   Files -> 1 context.getFilesDir()list(3)-=> hello_file4
D/_TAG_:   Files 
D/_TAG_:   Files -> 2 context.getFilesDir()-=> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 2 context.getFilesDir()list(0)-=>  hello_file -> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 2 context.getFilesDir()list(1)-=>  hello_file2 -> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 2 context.getFilesDir()list(2)-=>  hello_file3 -> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 2 context.getFilesDir()list(3)-=>  hello_file4 -> /data/data/com.test.internalstorage/files
D/_TAG_:   Files -> 2 context.getFilesDir()list(4)-=>  hello_file5 -> /data/data/com.test.internalstorage/files

欢迎指正和建议!!!

【讨论】:

  • 谢谢,但不是这样。我想从用户通过 USB 将文件保存在设备的 SD 汽车上的位置获取文件并处理它们,但我无法可靠地找到它们所在的路径,所以我想让用户直接将它们保存到内部存储器。 USB 连接将无法访问它,因此我要求设备/应用程序可以将文件从设备外部保存到内部存储。
  • 在这种情况下,我猜对文件的权限将不允许您(我的意思是 USB 接口),因为根据 Linux File Permissions,它将属于 Others group ... 其中作为应用程序作为系统的一部分运行,实际上您可以访问!
  • 如果以某种方式,务实地,我们可以在您的应用程序文件夹下的内部存储中创建一个具有 755 或 777 权限的目录,在我的例子中是 /data/data/com.test.internalstorage/files,然后是 adb,那么一件事可能会对我们有所帮助或abd shell 命令将帮助您将文件传输到此位置,....
猜你喜欢
  • 2015-03-11
  • 1970-01-01
  • 2021-03-06
  • 2020-02-08
  • 2020-04-08
  • 2012-09-18
  • 2019-08-13
  • 2023-03-25
  • 2014-05-14
相关资源
最近更新 更多