Unde este rădăcina cardului de memorie pe Android. Unde este folderul rădăcină al unei unități flash sau al cardului de memorie? Ieșiți în meniul de setări program

Proprietarii de portabile dispozitive digitale au apreciat de mult avantajele și oportunitățile care se deschid la utilizarea cardurilor de memorie. De regulă, nu apar întrebări legate de funcționarea lor. În același timp, unele denumiri pot induce în eroare. Un exemplu este rădăcina unui card de memorie.

Originea și semnificația rădăcinii cardului de memorieDiverse informații în în format electronic poate fi salvat în dispozitiv special numit card de memorie.

Este conceput pentru a stoca documente text, înregistrări audio și video, imagini. Principalul avantaj al acestui tip de memorie este ușurința înregistrării informațiilor și compactitatea dispozitivului, alături de cantități semnificative de date stocate. Memoria internă este reprezentată de RAM, memoria permanentă și memoria cache. Avantajele sale includ viteza, dar dezavantajul este cantitatea limitată de date stocate utilizatorului modern calculator personalși alte echipamente electronice trebuie să vă ocupați de următoarea propoziție: „instalați în rădăcina cardului de memorie” sau „copiați în rădăcina cardului”. Poate fi găsit oriunde, pentru că tehnologie moderna toate în volum mai mareîncepe să sprijine carduri de la terți pentru a mări memoria internă.Cartele de memorie sunt standardizate. Au anumite dimensiuniși locația plăcuțelor de contact în funcție de tipul de dispozitiv pentru utilizare pentru care sunt destinate. Acestea includ laptopuri, tablete, smartphone-uri, camere digitaleși chiar PSP cu alții console de jocuri. Prin urmare pentru funcţionare corectă Nu vă puteți descurca cu ei fără o idee clară despre ce poate însemna expresia „rădăcină a unui card de memorie” și unde poate fi localizată rădăcină - „radical, rădăcină”, adică ceva primordial, original A intrat în uz chiar de la început, când au început să apară computerele. Pe ele, rădăcina era chiar conținutul dispozitivului, adică locul de unde a fost lansat sistemul și unde puteau fi salvate datele. În esență, în ceea ce privește cardurile de memorie actuale această desemnare nimic nu a fost schimbat. Directorul rădăcină În prezent, rădăcina unui card de memorie este directorul în sine, care se află pe card. Acesta este același folder care este lansat când faceți clic pe pictograma cardului de memorie dintr-un smartphone sau netbook. Doar că cuvântul rădăcină a fost tradus literal, iar acum analogul său rus este folosit pentru a se referi la cardul în sine. Astfel, dacă vi se cere să copiați datele la rădăcină, atunci nu trebuie să creați nimic suplimentar pe cardul de memorie, ci pur și simplu să copiați fisierele necesare pe el însuși, în directorul rădăcină.

Apoi a apărut Android Lollipop, și cu el noi funcții pentru lucrul cu un card SD. A apărut SAF(Storage Acces Framework), a apărut o nouă Intenție ACTION_OPEN_DOCUMENT_TREE, cu care poți selecta rădăcina cardului SD și apoi o poți folosi pentru nevoile tale. De fapt, SAF era încă pe KitKat, dar fără această Intenție era de puțin folos, deoarece pentru a accesa fișierele de pe card era necesar să se folosească Intent ACTION_OPEN_DOCUMENT , care, judecând după nume, permite utilizatorului să selecteze fișierul pe care îl dorește să editeze manual prin selectorul de sistem. Bine, dar dacă utilizatorul are 5000 de fișiere, va face asta? Nu.

Determinarea unităților externe de pe dispozitiv

Voi începe cu cel mai dureros subiect în lucrul cu cardurile de memorie. Avem o metodă minunată în Android

File Environment.getExternalStorageDirectory()

După cum sugerează și numele, acesta este ceea ce aveți nevoie. „Extern” se traduce prin „extern”, nu? Dar nu ar trebui să te bazezi pe această metodă. Poate întoarce calea către memoria internă, poate către card, dar se întâmplă diferit pe fiecare dispozitiv. Această situație a apărut în mare parte din cauza la diferiți producători telefoanele și lor firmware modificat si scoici. Ideea mea este că metoda getExternalStorage() poate returna calea nu către cardul SD real, ci către ceea ce producătorul consideră a fi o unitate externă. Aici apare confuzia de definiție. Stocare externă aceasta nu este neapărat o unitate flash: pe unele dispozitive este memorie interioară, unele au de fapt un card SD. Punctele de montare a cardului pot fi oricare:

  • /storage/extSdCard/
  • /storage/sdcard1/
  • /storage/sdcard0/
  • /mnt/external_sd/
  • /mnt/extern/
  • /mnt/sdcard2/
  • /storage/sdcard0/external_sdcard/
  • /storage/removable/sdcard1/
  • /detașabil/microsd
  • /mnt/media_rw/sdcard1
  • /mnt/emmc

Și asta nu este un fel de problema mare până când îl întâlnești singur.

Există multe subiecte pe StackOverflow cu o tonă de opțiuni diferite determinarea unei unități flash, pornind de la căutarea prin toate combinațiile posibile de puncte de montare, încercarea de a obține variabilele de mediu Java System.getenv("EXTERNAL_STORAGE") , System.getenv("SECONDARY_STORAGE") și terminând cu parsare fișier de sistem/system/etc/vold.fstab. Aceste metode funcționează, dar fiecare numai într-un anumit caz. Nicio metodă nu acoperă toate dispozitivele sau nu funcționează deloc. Și dacă se pare că toate unitățile sunt detectate corect, atunci va exista întotdeauna un dispozitiv al cărui card nu este detectat prin aceste metode. Am încercat aproape toate metodele.

Pentru a înțelege amploarea problemei, voi spune că m-am ocupat de ea timp de aproximativ patru luni. Această problemă există din 2011, dar încă nu există o soluție exactă. De ceva timp m-am mulțumit cu acest cod mai mult sau mai puțin funcțional:

ArrayList allPaths = noua ArrayList<>(); ArrayList sdPaths = noua ArrayList<>(); pentru ( Fișier fișier: mContext.getExternalFilesDirs("extern")) ( if (fișier == null) (continuare; ) int index = file.getAbsolutePath().lastIndexOf("/Android/data"); if (index > 0) ( calea șirului de caractere = file.getAbsolutePath().substring(0, index); încercați ( calea = new File(path).getCanonicalPath(); ) catch (Excepție e) ( e.printStackTrace(); ) allPaths.add(path); !file.equals(mContext.getExternalFilesDir(„extern”))) ( sdPaths.add(cale); ) )

Dar s-a prăbușit și pe unele dispozitive. Și încă o dată, după ce am primit o unitate pe piață, am plecat în căutare.

Eram bântuit de selectorul de sistem Android (part-time manager de fișiere), în care toate unitățile sunt întotdeauna identificate corect. Fără să mă gândesc de două ori, m-am retras sistem apk folosind Root și l-am decompilat.

Insight

Am descoperit că selectorul folosește clasele StorageVolume și StorageManager. Iterează prin toate elementele StorageVolume obținute folosind metoda StorageManger.getVolumeList() și apelează metodele StorageVolume.getPath() și StorageVolume.getState() pe fiecare. Problema este că aceste metode sunt ascunse. Nu sunt private, dar sunt marcate cu adnotarea @hide. Ei bine, ce putem face, să ne scoatem reflecția:

StorageManager getStorageManager() ( return (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE); ) /* Folosiți reflectarea pentru detectarea tuturor stocărilor așa cum face Android probabil că nu funcționează cu USB-OTG funcționează numai pe API 19+ */ Public List getAllPaths() (Lista allPaths = noua ArrayList<>(); încercați ( ClasastorageVolumeClass = Class.forName("android.os.storage.StorageVolume"); Metoda getVolumeList = getStorageManager().getClass().getMethod("getVolumeList"); Metoda getPath = storageVolumeClass.getMethod("getPath"); Metoda getState = storageVolumeClass.getMethod("getState"); Obiect getVolumeResult = getVolumeList.invoke(getStorageManager()); lungime int final = Array.getLength(getVolumeResult); pentru (int i = 0; i< length; ++i) { Object storageVolumeElem = Array.get(getVolumeResult, i); String mountStatus = (String) getState.invoke(storageVolumeElem); if (mountStatus != null && mountStatus.equals("mounted")) { String path = (String) getPath.invoke(storageVolumeElem); if (path != null) { allPaths.add(path); } } } } catch (Exception e) { e.printStackTrace(); } return allPaths; }

Se pune întrebarea de ce nu există mod oficial Fă-o? Da, utilizarea reflectării într-un proiect de luptă nu este pe deplin de încredere, dar nu există alte opțiuni: dacă sistemul însuși folosește acest cod, atunci funcționează în toate cazurile. Practica confirmă acest lucru.

SAF (cadru de acces la stocare)

Documentație oficială:

Platforma SAF facilitează căutarea și deschiderea documentelor, imaginilor și altor fișiere în arhivele tuturor furnizorilor cu care lucrează. Standard interfață ușor de utilizat Permite utilizatorilor să aibă un mod consecvent între aplicații și furnizori de a căuta fișiere și de a accesa cele mai recent fișiere adăugate.

p>SAF agregează furnizorii de conținut (Subclase ale clasei DocumentProvider). Acesta este, de exemplu, Google Drive, diverse galerii și manageri de fișiere.

SAF emite URI-ul documentelor (fișierelor) care au permisiuni de scriere sau citire. Putem spune că acesta este un strat deasupra accesului la fișier. Clasa File în sine nu știe nimic despre SAF.

p>Pentru a putea edita datele de pe card, trebuie să obțineți URI-ul rădăcinii cardului SD, care va avea drepturi de editare. Apoi, folosind acest URI, puteți obține URI-ul oricărui fișier de pe cardul de memorie. Pentru a face acest lucru, trebuie să lansați selectorul de sistem folosind Intent ACTION_OPEN_DOCUMENT_TREE și să cereți utilizatorului să selecteze rădăcina cardului SD (altfel nimic nu va funcționa!).

In imagini:


@TargetApi(Build.VERSION_CODES.LOLLIPOP) void showDocumentTreeDialog() ( Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); startActivityForResult(Intent.createChooser(intent, getString(R.string.permission_intent));)_SD_CEST_CODE);

Lucruri foarte importante se întâmplă aici: în onActivityResult procesăm alegerea utilizatorului și dobândim drepturile râvnite de a accesa harta. În general, drepturile sunt acordate până când dispozitivul este repornit, iar pentru a nu trimite utilizatorul din nou pentru permisiune după repornirea dispozitivului, trebuie să utilizați metoda

TakePersistableUriPermission(Uri uri, int modeFlags)

cu steaguri pentru scris și citit. După toate aceste mașinațiuni, trebuie să salvați undeva Uri-ul primit al cardului SD munca in continuare cu el, de exemplu, în SharedPreferences.

@RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override protected void onActivityResult(int requestCode, int resultCode, date Intent) ( super.onActivityResult(requestCode, resultCode, date); if (requestCode == REQUEST_CODE_SD_CARD == && RESULT_CARD) takePermission(getApplicationContext(), data.getData())) ( //faceți-vă lucrurile ) ) @RequiresApi(api = Build.VERSION_CODES.KITKAT) private boolean takePermission(Context context, Uri treeUri) ( /* Ar fi util să adăugați o verificare că URI-ul primit este URI-ul hărții Voi lăsa această sarcină ca un exercițiu pentru cititori */ try ( if (treeUri == null) ( return false; ) context.getContentResolver().takePersistableUriPermission(. treeUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION |. Intent.FLAG_GRANT_READ_URI_PERMISSION) ; sharedPreferences.putString(SD_CARD_URI,treeUri.toString() return true (Exception e2) return;

Interacțiune cu cardul SD

Cititorul probabil că deja ghicește că nu vom putea interacționa cu fișierele (cum ar fi file.renameTo(file2)) într-un mod normal. Dacă ne uităm la codul metodei file.renameTo(File), nu vom vedea nimic suspect, nici verificări. Și pe bună dreptate, pentru că verificările sunt la nivel Sistemul de fișiere. Și dacă încercăm să schimbăm un fișier aflat pe cardul SD folosind mijloacele obișnuite, vom obține următoarea excepție:

Java.io.IOException: Nu se pot face modificări în fișierul your_file.ext

Aici mod interesant stabiliți dacă fișierul poate fi modificat:

Boolean public isFileWritable(Fișier fișier) ( boolean de scriere; încercați ( new FileOutputStream(fișier, adevărat).close(); scriere = fișier.exists() && fișier.canWrite(); ) catch (IOException e) ( scriere = fals; ) return inscriptibil ;

Dacă fișierul este pe hartă, vom primi o IOException.

Pentru a schimba un fișier de pe cardul de memorie, trebuie să obținem un DocumentFile care să reprezinte fișierul nostru, dar cu permisiunile de scriere pe care le-am obținut cu SAF.

La începutul articolului, am vorbit despre două intenții pentru SAF: ACTION_OPEN_DOCUMENT_TREE și ACTION_OPEN_DOCUMENT . Și am spus că nu vom folosi a doua intenție, deoarece aceasta obligă utilizatorul să caute fișierul manual. Dar avem un URI, pe care l-am primit folosind prima intenție, și asta înseamnă... Nu, nu există un API standard pentru obținerea unui DocumentFile, totul se face manual.

Algoritmul este astfel:

  1. Avem File
  2. Determinați numele unității pe care se află acest fișier
  3. Determinăm calea fișierului în raport cu unitatea pe care se află. Primim o linie ca android/folder/file.txt
  4. Separați o linie cu un simbol «/»
  5. În buclă, pentru fiecare parte primită, găsim DocumentFile reprezentând această cale, pe baza DocumentFile pentru partea anterioară
  6. Dacă algoritmul este finalizat fără erori, rezultatul este un DocumentFile care reprezintă fișierul nostru

Public DocumentFile getDocumentFile(Fișier) ( DocumentFile = null; șir de bază Folder = nul; for (String cale: getAllPaths()) (Fișier filePath = new File(cale); if (filePath.getAbsolutePath().startsWith(file.getAbsolutePath) ())) (baseFolder = filePath.getAbsolutePath(); break; ) ) if (baseFolder == null) ( return null; ) try ( String relativePath = file.getCanonicalPath().substring(baseFolder.length() + 1) ; Uri permissionUri = Uri.parse(sharedPreferences.getString(SD_CARD_URI)); getDocumentFileForUri(Uri treeUri, String relativePath) ( String parts = relativePath.split("/"); if (parts.length == 0) ( return null; ) DocumentFile document = DocumentFile.fromTreeUri (mContext, treeUri); for (String parte: piese) ( DocumentFile nextDocument = document.findFile(part); if (nextDocument != null) ( document = nextDocument; ) ) returnează document; )

FileOutputStream outputStream = (FileOutputStream) mContentResolver.openOutputStream(documentFile.getUri());

Un exemplu de copiere a unui fișier de clasă File într-un DocumentFile:

Public void copyFile(Fișier sursă, document DocumentFile) ( FileInputStream inputStream = nul; FileOutputStream outputStream = nul; încercați ( inputStream = nou FileInputStream(sourceFile); outputStream = (FileOutputStream) mContentResolver.openOutputStream(document.getUri()); FileChannel = fileChannel inputStream.getChannel(); FileChannel FileChannelOut = outputStream.getChannel(); (); ) în final ( încercați ( if (inputStream != null) inputStream.close(); if (outputStream != null) outputStream.close(); ) catch (IOException e) ( e.printStackTrace(); ) )

Și mai vreau să spun că acum codul va fi completat cu astfel de verificări

Public void writeFile(Fișier fișier) ( boolean fileWritable = isFileWritable(fișier); boolean hasSdCardUri = !sharedPreferences.getString(SD_CARD_URI).isEmpty(); if (fișierWritable || hasSdCardUri) ( /* puteți edita fișierul în mod normal, sau SAF */ return; ) if (Build.VERSION.SDK_INT >= 21) ( /* bine ai venit! (cerem permisiunea utilizatorului) */ throw new NoLollipopWritePermissionException(); ` ) else if (Build.VERSION.SDK_INT == 19 ) ( / * la revedere! (nu pot edita) */ lansează NoKitkatWritePermissionException() ) )

Concluzie

Sper că experiența mea descrisă în articol îi va ajuta pe cei care nu au lucrat încă cu un card SD pentru a evita cercetările și căutările îndelungate.

unde este Dosarul rădăcină Unități flash sau carduri de memorie?

    Dacă conectați orice dispozitiv de stocare la computer, acesta va apărea în Explorer ca o unitate cu o unitate atribuită scrisoare engleză, dacă deschideți acest disc, acesta va fi folderul rădăcină. Puteți crea alte foldere în el, în fiecare dintre acele foldere puteți crea, la rândul său, alte foldere și așa mai departe, iar în fiecare folder există fișiere. Acesta poate fi imaginat ca un copac cu un trunchi și ramuri ramificate care se extind din el - foldere - ramuri, fișiere - frunze, iar rădăcina acestui copac este tocmai folderul rădăcină, de unde și numele.

    Numim folderul rădăcină doar folderul unei anumite unități flash sau card de memorie. De îndată ce introduceți o unitate flash, în fața dvs. se afișează un nou dispozitiv, deschiderea care vă va duce la folderul rădăcină al unității (dosarul rădăcină, adică cel inițial), care poate conține o grămadă de alte foldere.

    Dosarul rădăcină al oricărui disc este folderul principal al acestui disc.

    Adică, când vă aflați în folderul rădăcină al unui disc, vi se pare că nu ați fi intrat niciodată în niciun folder.

    Adică, adresa folderului rădăcină este:

    unitățile A: și B: sunt de obicei rezervate pentru unitățile de dischete, care sunt calculatoare moderne Adesea nici nu-l mai instalează.

    pentru un hard disk, acesta este de obicei C:

    D este adesea rezervat pentru DVD player:

    Restul sunt de obicei folosite pentru dispozitivele externe conectate.

    De exemplu, pentru o unitate flash.

    Dar, în opinia mea, nu trebuie neapărat să fie în această ordine. Cineva de pe computerul său poate avea o ordine diferită în care dispozitivele corespund numelor de disc. Conectați-vă la secțiune Calculatorul meu(dacă ai Windows) și vei vedea cum se află pentru tine.

    Dosarul rădăcină al site-ului are următoarea adresă: http://sitename/

    Deși pentru creatorul site-ului, pe găzduirea sa, același folder este cel mai adesea doar un subdosar, deoarece acolo pot fi create mai multe site-uri, plus stocate setări diferite configuratii.

    Folderul rădăcină este considerat folderul unității flash, al programului sau al discului în sine. Adică, pot exista și alte (subdosare) acolo. Adică rădăcină înseamnă original. Și dacă, de exemplu, se indică faptul că, de exemplu, un fișier trebuie să fie tras în directorul rădăcină al unei unități flash, atunci trebuie doar să-l plasați pe unitatea flash în sine, și nu într-un alt folder de pe acesta. unitate flash. Și, de asemenea, prin analogie cu alte resurse.

    Ce este folderul rădăcină și cum se ajunge acolo?

    De fapt, totul este foarte simplu, folderul rădăcină este folderul care este considerat cel original. Dacă, de exemplu, vă conectați unitatea flash la dispozitiv, va apărea un meniu prin care puteți merge la folderul rădăcină = aceasta este unitatea flash în sine, care poate conține atât foldere, cât și fișiere.

    Destul de des puteți auzi sau întâlni fraza: instalați/mutați/copiați fisier specific la rădăcina cardului de memorie sau la folderul rădăcină al cardului flash. Dar ce este și unde este folderul rădăcină sau doar rădăcina unității flash?

    Răspunsul este de fapt foarte simplu. Acest nume vine din directorul rădăcină. Adică, când facem clic pe pictograma cardului de memorie/cardului flash și se deschide o fereastră în fața noastră, acesta este același folder rădăcină. Deși de fapt nu vedem folderul acolo. Aceasta este zona hărții în sine, cu alte fișiere și alte foldere plasate pe ea. Dosarul rădăcină (sau rădăcină) al unei unități flash poate fi comparat cu ultimul etaj din ierarhia tuturor folderelor de pe acesta.

Diverse informații pot fi stocate electronic pe un dispozitiv special numit card de memorie. Este conceput pentru stocarea documentelor text, a înregistrărilor audio și video și a imaginilor. Principalul avantaj al acestui tip de memorie este ușurința înregistrării informațiilor și compactitatea dispozitivului, alături de cantități semnificative de date stocate.

Memoria internă este reprezentată de RAM, memorie permanentă și memorie cache. Avantajele sale includ viteza, dar dezavantajul este cantitatea limitată de date stocate.

Foarte des, un utilizator modern al unui computer personal și al altor echipamente electronice trebuie să se confrunte cu următoarea propoziție: „instalați în rădăcina cardului de memorie” sau „copiați în rădăcina cardului”. Poate fi găsit oriunde, deoarece tehnologia modernă începe din ce în ce mai mult să accepte carduri de la terți pentru a crește memoria internă.

Cardurile de memorie sunt standardizate. Acestea au anumite dimensiuni de gabarit și amplasarea plăcuțelor de contact în funcție de tipul de dispozitive pentru care sunt destinate a fi utilizate.

Acestea includ laptopuri, tablete, smartphone-uri, camere digitale și chiar PSP cu alte console de jocuri. Prin urmare, pentru a lucra cu ele corect, nu vă puteți lipsi de o idee clară despre ce poate însemna expresia „rădăcină card de memorie” și unde poate fi localizată.

Numele locului pentru salvarea datelor pe card provine de la cuvântul englezesc rădăcină - „indigen, rădăcină”, adică ceva curat, primordial. A intrat în uz chiar de la început, când au început să apară computerele. Pe ele, rădăcina era chiar conținutul dispozitivului, adică locul de unde a fost lansat sistemul și unde puteau fi salvate datele. De fapt, în ceea ce privește cardurile de memorie actuale, această denumire nu s-a schimbat deloc.

Directorul rădăcină

Astăzi, rădăcina unui card de memorie este directorul în sine, care se află pe card. Acesta este același folder care este lansat atunci când faceți clic pe pictograma cardului de memorie de pe telefonul smartphone sau. Doar că cuvântul rădăcină a fost tradus literal, iar acum analogul său rus este folosit pentru a se referi la cardul în sine. Astfel, dacă vi se cere să copiați datele în rădăcină, atunci nu trebuie să creați nimic suplimentar pe cardul de memorie, ci pur și simplu să copiați fișierele necesare pe acesta, în directorul rădăcină.

  • Serghei Savenkov

    un fel de recenzie „scurtă”... de parcă s-ar grăbi undeva