Mar*_*ark 16 android android-sdcard android-4.4-kitkat
我们刚刚违反了适用于在Android 4.4上将文件写入SD卡(外部存储)的新权限(EACCES权限被拒绝)
在KitKat之前,我们设置了可写文件夹,如下所示:
mfolder = Environment.getExternalStorageDirectory().getPath() + "/appfiles";
Run Code Online (Sandbox Code Playgroud)
然而,经过几个小时的搜索,我得出结论,无论是对还是错,在4.4设备上启用文件写入需要将其更改为:
mfolder = Environment.getExternalStorageDirectory().getPath() + "/Android/data/com.xyz.abc/appfiles";
Run Code Online (Sandbox Code Playgroud)
所以mfolder会是这样的:/mnt/sdcard/Android/data/com.xyz.abc/appfiles
这是正确的,我们是否在sdcard上创建了一个像上面那样的文件夹来启用4.4设备来写文件?
mfolder是我们保存为共享首选项的String.
然后,如果API> = 19,我们将运行此代码,该代码将更改mfolder String,然后将旧文件夹中的所有文件复制到新的"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) {
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我通知用户他们的文件已被复制到新文件夹,并且由于新的权限,他们必须手动删除旧的prekitkatfolder文件夹.我想如果他们有一个股票文件管理器,或者如果他们没有安装SD卡并将其放在PC中,由于新的4.4权限,他们只会这样做?
此外,对我们来说,这些4.4权限似乎并未影响我们所有使用Kitkat的用户.有些人仍然可以写入其外部存储器上的原始文件夹位置,有些人会收到EACCES(权限被拒绝)错误.任何人都可以解释为什么会这样,人们会认为这适用于使用外部存储的所有4.4设备吗?
由于我们没有实际的4.4设备,我们不得不使用模拟器(API 19)测试此代码,但我们没有得到EACCES Permission Denied错误.所以我们发布了一个带有上面代码的测试版,并且已经被告知复制的文件最终在内部存储中,这怎么可能呢?
任何想法,我们做错了,提前谢谢
更新解决方案
这将设置并在KitKat的正确位置创建文件夹.
mfolder = this.getExternalFilesDir("asubfoldername").getAbsolutePath();
Run Code Online (Sandbox Code Playgroud)
但是,这不是完全证明,如果Android设备同时具有内部和外部辅助存储位置,则上面将使用内部存储位置.不是我们想要的,因为我们需要可移动SD卡的路径,或者更好的是具有最多可用空间的辅助存储位置的路径.
File[] possible_kitkat_mounts = getExternalFilesDirs(null);
Run Code Online (Sandbox Code Playgroud)
注意getExternalFilesDirs末尾的"s".这将创建一系列辅助外部存储位置.
for (int x = 0; x < possible_kitkat_mounts.length; x++) {
//Log.d("test", "possible_kitkat_mounts " + possible_kitkat_mounts[x].toString());
boolean isgood=false;
if (possible_kitkat_mounts[x] != null){
isgood = test_mount(possible_kitkat_mounts[x].toString());
if (isgood==true){
arrMyMounts.add(newymounts(Device_get_device_info(possible_kitkat_mounts[x].toString()), possible_kitkat_mounts[x].toString()));
}
}
}
//sort arrMyMounts size so we can use largest
Collections.sort(arrMyMounts, new Comparator<mymounts>(){
public int compare(mymounts obj1, mymounts obj2){
return (obj1.avaliablesize > obj2.avaliablesize) ? -1: (obj1.avaliablesize > obj2.avaliablesize) ? 1:0 ;
}
});
if (arrMyMounts.size()>0){
mfolder = arrMyMounts.get(0).name + "/asubfoldername";
//Log.d("test", "selected kitkat mount " + kitkatfolder);
}else{
//do something else...
}
Run Code Online (Sandbox Code Playgroud)
从possible_kitkat_mounts数组中,我们通过test_mount检查是否可以实际写入所选位置,如果成功,我们将该位置添加到arrMyMounts.
通过对arrMyMounts进行排序,我们可以获得具有最多可用空间的位置.
嘿presto,arrMyMounts.get(0).name是一个kitkat辅助存储位置,具有最大的可用空间.
Google已阻止Android 4.4中对外部存储设备的写入权限.在他们改变之前,没有办法在没有root的情况下将其还原.
更多信息:https://groups.google.com/forum/#! msg/ android-platform/ 14VUiIgwUjY/ UsxMYwu02z0J
它可能适用于Kitkat的某些设备,它们带有minisd卡插槽.这很令人困惑:(
| 归档时间: |
|
| 查看次数: |
10650 次 |
| 最近记录: |