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
但它似乎并非如此。
我也听过其他设备的报道,包括更现代的三星设备。这只是原始设备制造商没有正确实现这一点,还是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文件的任何尝试都将失败。
好吧,我把你的代码包装在这个活动中:
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的Huawei Honor 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如何在没有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();
}