【问题标题】:Why are some ContextCompat.getExternalFilesDirs not accessible?为什么某些 ContextCompat.getExternalFilesDirs 无法访问?
【发布时间】:2017-05-03 18:44:07
【问题描述】:

ContextCompat.getExternalFilesDirs(context, null) 说:

返回所有外部存储设备上应用程序特定目录的绝对路径,应用程序可以在其中放置其拥有的持久文件。

例如,运行 Android 5.1.1 的 Huawei Honor 从该方法返回以下内容:

/storage/emulated/0/Android/data/my.package.name/files
/storage/sdcard1/Android/data/my.package.name/files

第二个目录是可移动的 sd 卡。但是,如果我尝试读取或写入该目录,则会收到异常:android.system.ErrnoException: open failed: EACCES (Permission denied)

该应用确实有WRITE_EXTERNAL_STORAGE。这在运行 Android 4.4.4 的三星 Galaxy Note 4 上运行良好。这与 Android 6.0 的可选权限无关,因为这是在 5.1.1 上显示的问题。

API 显示the application can place persistent files it owns,但似乎并非如此。

我也听到了来自其他设备的报告,包括更现代的三星设备。这只是 OEM 没有正确实现这一点,还是我在 Android 复杂的存储框架中遗漏了什么?

这里有一些代码将在此设备和某些设备上演示这一点。

File removable = ContextCompat.getExternalFilesDirs(context, null)[1];
if (removable.exists() && removable.canRead() && removable.canWrite()) {
    File test = new File(removable, "test");
    test.createNewFile(); // Throws the exception mentioned above
}

在该目录中创建、移动、mkdir 文件的任何尝试都会失败。

【问题讨论】:

  • "如果我尝试读取或写入该目录" -- 哪个目录?你列出其中两个。 “该应用确实有 WRITE_EXTERNAL_STORAGE”——这与 Android 4.4+ 上的那些位置无关。
  • 糟糕。以上更新。第二个,是可移动的 sd 卡。
  • 嗯,你应该有读/写权限。您可能会考虑发布失败的代码以及完整的堆栈跟踪。恕我直言,制造商更有可能搞砸可移动存储而不是外部存储。
  • 添加了一些代码

标签: android storage android-sdcard


【解决方案1】:

好吧,我将你的代码封装在这个活动中:

package com.commonsware.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    File removable = ContextCompat.getExternalFilesDirs(this, null)[1];
    if (removable.exists() && removable.canRead() && removable.canWrite()) {
      File test = new File(removable, "test");
      try {
        test.createNewFile(); // Throws the exception mentioned above
      }
      catch (IOException e) {
        Log.e(getClass().getSimpleName(), "Exception creating file", e);
        Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
      }
    }
  }
}

在运行 Android 6.0.1 的华为荣耀 5X 上运行良好:

$ adb shell ls -al /storage/1A30-3598/Android/data/com.commonsware.myapplication/files
-rwxrwx--x u0_a29   sdcard_rw        0 2017-05-03 18:02 test

所以,我猜这是特定于设备的不兼容问题。

【讨论】:

  • @CommonsWare 查看我的回答,类似于
【解决方案2】:

出于多种原因,我想询问@CommonsWare 如何让代码在没有 ArrayIndexOutOfBoundsException 的情况下运行:length=1; index=1 错误 [0] 需要设置为 [0] 我们已经测试这个概念一段时间了,以编写一个让用户选择内部或外部存储的方法有人可以解释它是如何工作的或为什么它不起作用为我们 上面的答案需要这样格式化

        File removable = ContextCompat.getExternalFilesDirs(this,null)[0];
    if (removable.exists() && removable.canRead() && removable.canWrite()) {

        THE_PATH = String.valueOf(removable);
        THE_PATH = THE_PATH + "/Documents/";

    }else {
        Toast.makeText(getApplicationContext(),"NO SD CARD", 
    Toast.LENGTH_LONG).show();

    }

【讨论】:

    猜你喜欢
    • 2020-12-11
    • 2015-05-16
    • 2016-02-06
    • 1970-01-01
    • 2022-12-21
    • 2019-11-23
    • 2021-12-31
    • 2013-10-27
    • 1970-01-01
    相关资源
    最近更新 更多