Android
FileIO z systemem Android
Szukaj…
Wprowadzenie
Odczytywanie i zapisywanie plików w Androidzie nie różni się od odczytu i zapisu plików w standardowej Javie. Można użyć tego samego pakietu java.io
Istnieją jednak pewne szczególne związane z folderami, w których wolno pisać, ogólnie uprawnienia i obejścia MTP.
Uwagi
Android zapewnia sposób udostępniania pliku między wieloma aplikacjami, jak tu udokumentowano. Nie jest to wymagane, jeśli istnieje tylko jedna aplikacja, która tworzy i używa pliku.
Android zapewnia alternatywne opcje przechowywania, takie jak preferencje współdzielone i prywatne, zapisane pakiety i wbudowana baza danych. W niektórych przypadkach są lepszym wyborem niż zwykłe pliki.
Aktywność Androida ma kilka konkretnych metod, które wyglądają jak zamienniki standardowych Java File IO metod. Na przykład zamiast File.delete()
możesz wywołać Context.deleteFile()
, a zamiast rekurencyjnego zastosowania File.listFiles()
możesz wywołać Context.fileList()
aby uzyskać listę wszystkich plików specyficznych dla Twojej aplikacji z nieco mniejszą ilością kod. Nie zapewniają one jednak dodatkowej funkcjonalności poza standardowym pakietem java.io
Uzyskiwanie folderu roboczego
Możesz uzyskać swój folder roboczy, wywołując metodę getFilesDir()
w działaniu (Activity jest klasą centralną w aplikacji, która dziedziczy z kontekstu. Zobacz tutaj ). Czytanie nie jest inne. Tylko twoja aplikacja będzie miała dostęp do tego folderu.
Twoja aktywność może zawierać na przykład następujący kod:
File myFolder = getFilesDir();
File myFile = new File(myFolder, "myData.bin");
Pisanie surowej tablicy bajtów
File myFile = new File(getFilesDir(), "myData.bin");
FileOutputStream out = new FileOutputStream(myFile);
// Write four bytes one two three four:
out.write(new byte [] { 1, 2, 3, 4}
out.close()
Z tym kodem nie ma nic specyficznego dla Androida. Jeśli często zapisujesz wiele małych wartości, użyj BufferedOutputStream, aby zmniejszyć zużycie wewnętrznego dysku SSD urządzenia.
Serializacja obiektu
W systemie Android dostępna jest stara, dobra serializacja obiektów Java. możesz zdefiniować klasy nadające się do szeregowania, takie jak:
class Cirle implements Serializable {
final int radius;
final String name;
Circle(int radius, int name) {
this.radius = radius;
this.name = name;
}
}
a następnie napisz do ObjectOutputStream:
File myFile = new File(getFilesDir(), "myObjects.bin");
FileOutputStream out = new FileOutputStream(myFile);
ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(out));
oout.writeObject(new Circle(10, "One"));
oout.writeObject(new Circle(12, "Two"));
oout.close()
Serializacja obiektów Java może być albo doskonałym, albo naprawdę złym wyborem, w zależności od tego, co chcesz z tym zrobić - poza zakresem tego samouczka, a czasem na podstawie opinii. Przeczytaj najpierw o wersji, jeśli zdecydujesz się jej użyć.
Zapis do pamięci zewnętrznej (karta SD)
Możesz także czytać i zapisywać z / na kartę pamięci (kartę SD), która jest obecna na wielu urządzeniach z Androidem. Pliki w tej lokalizacji są dostępne dla innych programów, również bezpośrednio przez użytkownika po podłączeniu urządzenia do komputera za pomocą kabla USB i włączeniu protokołu MTP.
Znalezienie lokalizacji karty SD jest nieco bardziej problematyczne. Klasa Środowisko zawiera statyczne metody uzyskiwania „katalogów zewnętrznych”, które normalnie powinny znajdować się na karcie SD, a także informacje, czy karta SD w ogóle istnieje i czy można ją zapisać. To pytanie zawiera cenne odpowiedzi, jak upewnić się, że zostanie znaleziona właściwa lokalizacja.
Dostęp do pamięci zewnętrznej wymaga uprawnień w manifeście Androida:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
W przypadku starszych wersji Androida umieszczanie uprawnień wystarczy ujawnić te uprawnienia (użytkownik musi to zatwierdzić podczas instalacji). Jednak począwszy od Androida 6.0 Android prosi użytkownika o zatwierdzenie w momencie pierwszego dostępu i musisz wspierać to nowe podejście. W przeciwnym razie dostęp zostanie odmówiony bez względu na manifest.
W Androidzie 6.0 najpierw musisz sprawdzić uprawnienia, a następnie, jeśli nie zostaną przyznane, poproś o nie. Przykłady kodu można znaleźć w tym pytaniu SO .
Rozwiązywanie problemu „Niewidocznych plików MTP”.
Jeśli tworzysz pliki do wyeksportowania za pomocą kabla USB na komputer stacjonarny za pomocą protokołu MTP, może być problem, że nowo utworzone pliki nie są natychmiast widoczne w eksploratorze plików uruchomionym na podłączonym komputerze stacjonarnym. Aby nowe pliki były widoczne, musisz wywołać MediaScannerConnection :
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS), "theDocument.txt");
FileOutputStream out = new FileOutputStream(file)
... (write the document)
out.close()
MediaScannerConnection.scanFile(this, new String[] {file.getPath()}, null, null);
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.fromFile(file)));
Ten kod wywołania MediaScannerConnection działa tylko dla plików, a nie dla katalogów. Problem opisano w tym raporcie o błędach Androida . Można to naprawić w przypadku niektórych wersji w przyszłości lub na niektórych urządzeniach.
Praca z dużymi plikami
Małe pliki są przetwarzane w ułamku sekundy i możesz je odczytywać / zapisywać zamiast kodu tam, gdzie jest to potrzebne. Jeśli jednak plik jest większy lub wolniejszy w przetwarzaniu, może być konieczne użycie AsyncTask w Androidzie do pracy z plikiem w tle:
class FileOperation extends AsyncTask<String, Void, File> {
@Override
protected File doInBackground(String... params) {
try {
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS), "bigAndComplexDocument.odf");
FileOutputStream out = new FileOutputStream(file)
... (write the document)
out.close()
return file;
} catch (IOException ex) {
Log.e("Unable to write", ex);
return null;
}
}
@Override
protected void onPostExecute(File result) {
// This is called when we finish
}
@Override
protected void onPreExecute() {
// This is called before we begin
}
@Override
protected void onProgressUpdate(Void... values) {
// Unlikely required for this example
}
}
}
i wtedy
new FileOperation().execute("Some parameters");
To pytanie SO zawiera pełny przykład tworzenia i wywoływania AsyncTask. Zobacz także pytanie dotyczące obsługi błędów dotyczące obsługi wyjątków IOException i innych błędów.