我们刚刚遇到了在Android 4.4中写入sd卡(外部存储)文件的新权限问题(EACCES Permission Denied)。
在KitKat之前,我们是按照以下方式设置可写文件夹:
mfolder = Environment.getExternalStorageDirectory().getPath() + "/appfiles";
然而,经过数小时的搜索,我得出了结论,正确或错误,在4.4设备上启用文件写入需要更改为:
mfolder = Environment.getExternalStorageDirectory().getPath() + "/Android/data/com.xyz.abc/appfiles";
所以,mfolder应该是这样的:/mnt/sdcard/Android/data/com.xyz.abc/appfiles
这样创建一个类似上述sd卡上的文件夹,能让4.4设备写入文件吗?
mfolder是我们保存到共享偏好中的字符串。
然后,我们有了一段代码,如果API>=19,它将更改mfolder字符串,然后将所有文件从旧文件夹复制到新的“kitkat”文件夹。
if (android.os.Build.VERSION.SDK_INT>=19){
if (!mfolder.contains("/Android/data/com.xyz.abc/appfiles")){
if (prefs.getBoolean("kitkatcheck", false)==false){
//update mfolder from
// /mnt/sdcard/appfiles
// to
// /mnt/sdcard/Android/data/com.xyz.abc/appfiles
String prekitkatfolder = mfolder;
String kitkatfolder = mfolder.replace("/appfiles", "/Android/data/com.xyz.abc/appfiles");
mfolder = kitkatfolder;
try {
File sd = new File(mfolder);
if(!sd.exists() || !sd.isDirectory()) {
sd.mkdirs();
}
} catch (Exception e) {
Toast.makeText(getBaseContext(), "Error creating Kitkat folder!\n" + e.toString(), Toast.LENGTH_LONG).show();
return;
}
prefEditor.putString("patternfolder", mfolder);
prefEditor.putBoolean("kitkatcheck", true);
prefEditor.commit();
//copy files and folder from old appfiles folder to new.
AllFiles.clear();
listFilesAndFilesSubDirectories(prekitkatfolder);
if (AllFiles.size()>0){
for (File child : AllFiles ) {
try {
File dest = new File(child.toString().replace(prekitkatfolder, kitkatfolder));
try {
String filePath = dest.getPath().substring(0, dest.getPath().lastIndexOf(File.separator));
File subfolder = new File(filePath);
if(!subfolder.exists() || !subfolder.isDirectory()) {
subfolder.mkdirs();
}
} catch (Exception ex) {
}
copyFile(child, dest);
} catch (Throwable t) {
}
}
}
}
}
我会通知用户他们的文件已经复制到新文件夹,由于新权限,他们需要手动删除旧的prekitkatfolder文件夹。我猜只有当他们拥有原始文件管理器或将SD卡卸载并放入PC时,才能这样做,因为新的4.4权限限制了此操作?
另外,对我们来说,似乎这些4.4权限并没有影响所有使用Kitkat的用户。一些人仍然可以将文件写入其外部存储器的原始位置,而另一些人则会出现EACCES(权限被拒绝)错误。有谁能解释一下为什么会出现这种情况?人们可能认为这适用于所有使用外部存储器的4.4设备。
由于我们没有实际的4.4设备,我们必须使用模拟器(API 19)测试此代码,但我们没有收到EACCES权限被拒绝的错误。因此,我们发布了一个带有上述代码的beta版本,并被告知复制的文件最终存储在内部存储器中,这是怎么回事?
请问我们做错了什么,提前感谢您的帮助。