2014-05-07 23 views
16

Właśnie spadł wolny nowych uprawnień, które odnoszą się do zapisywania plików na kartach pamięci SD (zewnętrzny) na Androida 4.4 (EACCES Permission denied)Android 4.4 KitKat folderu na karcie SD

Przed KitKat ustawiamy nasz Folder zapisu tak:

mfolder = Environment.getExternalStorageDirectory().getPath() + "/appfiles"; 

jednak po wielu godzinach poszukiwania Doszedłem do wniosku, słusznie lub niesłusznie, że na 4,4 urządzeń w celu umożliwienia zapisu plików to musi być zmienione na:

mfolder = Environment.getExternalStorageDirectory().getPath() + "/Android/data/com.xyz.abc/appfiles"; 

Tak więc mfolder może wyglądać następująco: /mnt/sdcard/Android/data/com.xyz.abc/appfiles

Czy to prawda, czy tworzymy folder taki jak ten na sdcard, aby umożliwić 4.4 urządzenia do pisać pliki?

mfolder jest ciągiem, który zapisujemy w preferencjach współdzielonych.

Następnie mamy ten kod, który uruchamia się raz, jeśli API> = 19, który zmienia ciąg mfolder, a następnie kopiuje wszystkie pliki ze starego folderu do nowego folderu "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) { 

         } 
        } 

       } 


      } 

     } 

Następnie powiadomić użytkownika, że ​​ich pliki zostały skopiowane do nowego folderu i że w związku z nowymi uprawnieniami będą musieli ręcznie usunąć stary folder prekitkatfolder. Sądzę, że będą w stanie to zrobić tylko, jeśli mają menedżera plików giełdowych lub jeśli odmontowali kartę SD i umieścili ją na komputerze z powodu nowych uprawnień 4.4?

Ponadto wydaje się, że te uprawnienia 4.4 nie dotyczą wszystkich naszych użytkowników za pomocą KitKat. Niektóre z nich nadal mogą zapisywać do pierwotnej lokalizacji folderu w ich pamięci zewnętrznej, a niektóre otrzymują błąd EACCES (Odmowa uprawnień). Czy ktokolwiek rzuca jakiekolwiek światło na to, dlaczego tak się dzieje, można by pomyśleć, że dotyczyłoby wszystkich urządzeń 4.4 korzystających z pamięci zewnętrznej?

Ponieważ nie mamy rzeczywistego urządzenia 4.4, musimy przetestować ten kod za pomocą emulatora (API 19), ale nie otrzymujemy błędu EACCES Permission Denied. Wydaliśmy wersję beta z powyższym kodem i powiedziano nam, że skopiowane pliki trafiły do ​​pamięci wewnętrznej, jak to możliwe?

Wszelkie pomysły, co robimy źle, z góry dzięki

+0

Cześć Zorac, jestem w podobnej sytuacji na niektórych urządzeniach działa bez nazwy pakietu w ścieżce, a na niektórych potrzebujesz długiej ścieżki dołączonej jak /Android/data/com.xyz.abc/appfiles nie wiesz co się dzieje . Znalazłeś już rozwiązanie? – Ahmed

Odpowiedz

7

Updated rozwiązanie.

Ustawia a także tworzy folder w odpowiednim miejscu dla KitKat.

mfolder = this.getExternalFilesDir("asubfoldername").getAbsolutePath(); 

Jednak to nie jest pełny odporny, jeśli Androida urządzenie ma zarówno wewnętrzne, jak i zewnętrzne miejsce przechowywania wtórnego, powyższe będzie używać wewnętrznego.Nie naprawdę tego chcemy, ponieważ potrzebujemy ścieżki do wymiennego sdcarda lub jeszcze lepiej ścieżki do wtórnej storagelocation z najbardziej wolną dostępną przestrzenią.

File[] possible_kitkat_mounts = getExternalFilesDirs(null); 

Zwróć uwagę na "s" na końcu getExternalFilesDirs. Tworzy to szereg dodatkowych zewnętrznych lokalizacji pamięci.

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... 
} 

Z tablicy możemy sprawdzić poprzez test_mount aby sprawdzić, czy rzeczywiście możemy napisać do wybranej lokalizacji possible_kitkat_mounts a jeśli dodamy, że sukces lokalizację arrMyMounts.

Sortując arrMyMounts możemy uzyskać lokalizację z najbardziej dostępnym wolnym miejscem.

Hej presto, arrMyMounts.get (0) .name to dodatkowa lokalizacja pamięci Kitkat z największą ilością wolnego miejsca.

+0

Mam zainstalowaną aplikację na Samsung Galaxy Note 10.1, która zapewnia zarówno wbudowaną pamięć zewnętrzną jak i wymienne karty SD. Próbowałem pobrać ścieżkę do wymiennej karty SD za pomocą metody wspomnianej powyżej (tj. GetExternalFilesDirs (null)), ale nie istnieje taka metoda w kontekście. Wszystko, czego potrzebuję, to uzyskać ścieżkę do karty SD, więc mogę utworzyć katalog specyficzny dla pakietu do odczytu/zapisu plików aplikacji. Próbowałem również utworzyć ten katalog przy użyciu zakodowanej ścieżki, ale nie pozwala na to. Czy możesz pomóc w związku z tym? Dzięki –

+0

co to jest "to"? jaka to klasa? –

5

Google zablokował dostęp do zapisu do zewnętrznych urządzeń pamięci masowej w Androidzie 4.4. Dopóki go nie zmienią, nie ma możliwości przywrócenia go z powrotem bez uprawnień roota.

Więcej informacji: https://groups.google.com/forum/#!msg/android-platform/14VUiIgwUjY/UsxMYwu02z0J

To może działać na niektórych urządzeniach z KitKat które gniazdo kart miniSD. Jest to mylące :(

+2

, ale es file explorer może utworzyć folder w moim urządzeniu KitKat! Nie mogę –

Powiązane problemy