【问题标题】:Is there any way to write wherever I want on a SD card in Android?有什么方法可以在 Android 的 SD 卡上写任何我想写的地方吗?
【发布时间】:2016-10-03 10:55:10
【问题描述】:

自从 KitKat 以来,我读了很多关于 Android 和 SD 卡的东西。但最后,我找不到一个明确的全球答案,所以我会尝试从你们那里得到一个相关的答案。

我想在 SD 卡上的任意位置写入一个文件,一个文本文件。

让我们通过这个简单的示例来关注 Android 6。清单中存在写权限

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

我有这个辅助方法

private void writeFile(File parent)
{
    try
    {
        File f = new File(parent, "test.txt");
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(f));
        outputStreamWriter.write("test");
        outputStreamWriter.close();
        Log.i(TAG, "File created : " + f.getAbsolutePath());
    }
    catch (IOException e)
    {
        Log.e(TAG, "File write failed", e);
    }
}

并在测试活动中:

if (Build.VERSION.SDK_INT >= 23)
{
    if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
        || ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
    {
        ActivityCompat.requestPermissions(MainActivity.this, new String[] {
            android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
            android.Manifest.permission.READ_EXTERNAL_STORAGE }, 1);
    }
    else
    {
        File path = getExternalFilesDirs(Environment.DIRECTORY_PICTURES)[1];
        writeFile(path);

        path = getExternalFilesDirs(null)[1];
        writeFile(path);

        writeFile(new File("/storage/3635-3533/"));
    }
}

/!\ 是的,第三次测试的路径是通过正确检索而硬编码的,SD 卡路径不是这里的主题 /!\

首次启动,permission asked,一切正常(抱歉法国设备)

第二次发布,结果如下

10-03 12:40:10.414: I/TESTSDCARD(26006): File created : /storage/3635-3533/Android/data/com.example.testsdcard/files/Pictures/test.txt
10-03 12:40:10.415: I/TESTSDCARD(26006): File created : /storage/3635-3533/Android/data/com.example.testsdcard/files/test.txt
10-03 12:40:10.426: E/TESTSDCARD(26006): File write failed
10-03 12:40:10.426: E/TESTSDCARD(26006): java.io.FileNotFoundException: /storage/3635-3533/test.txt: open failed: EACCES (Permission denied)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at libcore.io.IoBridge.open(IoBridge.java:459)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at com.example.testsdcard.MainActivity.writeFile(MainActivity.java:61)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at com.example.testsdcard.MainActivity.onCreate(MainActivity.java:50)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at android.app.Activity.performCreate(Activity.java:6367)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2397)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2504)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at android.app.ActivityThread.access$900(ActivityThread.java:165)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1368)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at android.os.Handler.dispatchMessage(Handler.java:102)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at android.os.Looper.loop(Looper.java:150)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at android.app.ActivityThread.main(ActivityThread.java:5546)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at java.lang.reflect.Method.invoke(Native Method)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684)
10-03 12:40:10.426: E/TESTSDCARD(26006): Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at libcore.io.Posix.open(Native Method)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
10-03 12:40:10.426: E/TESTSDCARD(26006):    at libcore.io.IoBridge.open(IoBridge.java:445)
10-03 12:40:10.426: E/TESTSDCARD(26006):    ... 16 more

如您所见,使用getExternalFilesDirs 的两个测试都有效(并不奇怪,应该如此) 但是第三个,试图在 SD 卡的根目录写入,失败了。

我做错了吗?有什么方法可以执行此操作吗?希望不使用存储访问框架,这在我的应用程序环境中对我来说真的很痛苦。

此外,存储访问框架是否允许对文件执行所有基本操作(写入、删除、重命名...)而无需大量代码?

【问题讨论】:

  • 没有root,你没有/storage的写权限
  • 你指的是 SD 卡?
  • 嗯,有些设备没有“SD卡”,所以我只是指文件系统上的路径
  • 我真的不想在/storage上写,只是在SD卡上写文件,比如ES文件资源管理器或Solid Explorer。在我的示例中,/storage/3635-3533/ 是我的 SD 卡的路径。
  • 明白了。我认为3635-3533 是一些虚构的值

标签: android android-permissions android-sdcard


【解决方案1】:

我想在 SD 卡上的任意位置写入一个文件,一个文本文件。

这在搭载 Android 4.4+ 的设备上是不可能的,除非在 root 设备上。

清单中存在写权限

该权限用于外部存储。外部存储不是可移动存储。

我做错了吗?

是的,只要您没有对可移动存储上任意位置的读/写访问权限。

存储访问框架是否允许对文件执行所有基本操作(写入、删除、重命名...)而无需大量代码?

只有您知道您认为“大量代码”是什么。一般来说,如果您获得了用户对某条内容(或其容器)的许可,则可以执行您在DocumentFile 上看到的各种操作。

【讨论】:

  • 那么文件管理器怎么能在没有root权限的情况下执行这样的操作呢?他们都使用了 DocumentFile 方法?
  • @ToYonos:您必须询问这些特定应用程序的开发人员。请注意,设备附带的文件管理器通常被授予对可移动存储的直接访问权限。
  • 我用DocumentFile 做了一些测试,它确实适用于文件创建/修改。我想预计会有一些严重的重构:)
  • 我混淆了 Android 6 中引入的权限系统和存储访问框架。使用 DocumentFile 并授予正确的 uri 权限,解决了我的问题。感谢您的提示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
相关资源
最近更新 更多