Bagian pelajaran ini mengajarkan Anda cara
- Memilih Penyimpanan Internal atau Penyimpanan Eksternal
- Memperoleh Izin untuk Penyimpanan Eksternal
- Menyimpan File pada Penyimpanan Internal
- Menyimpan File pada Penyimpanan Eksternal
- Melakukan Kueri Ruang Bebas
- Menghapus File
Anda juga harus membaca
Android menggunakan sistem file yang
yang serupa dengan sistem file berbasis disk pada platform lain. Pelajaran ini menjelaskan
cara menangani sistem file Android untuk membaca dan menulis file dengan File
API.
Objek File cocok untuk membaca atau menulis data dalam jumlah besar dengan
urutan mulai-hingga-selesai tanpa melompat-lompat. Misalnya, objek ini cocok untuk file gambar atau
apa saja yang dipertukarkan lewat jaringan.
Pelajaran ini menampilkan cara melakukan tugas dasar menyangkut file dalam aplikasi Anda.
Pelajaran ini menganggap Anda sudah memahami dasar-dasar sistem file Linux dan
API masukan/keluaran file standar di java.io.
Memilih Penyimpanan Internal atau Penyimpanan Eksternal
Semua perangkat Android memiliki dua area storage file: penyimpanan “internal” dan penyimpanan “eksternal”. Nama-nama ini berasal dari masa awal Android, ketika sebagian besar perangkat menyediakan memori non-volatil bawaan (penyimpanan internal), plus media storage lepas-pasang seperti kartu microSD (penyimpanan eksternal). Sebagian perangkat membagi ruang storage permanen menjadi partisi “internal” dan “eksternal”, sehingga sekalipun tanpa media storage lepas-pasang, selalu ada dua ruang penyimpanan dan perilaku API adalah sama apakah di penyimpanan eksternal bersifat lepas-pasang maupun tidak. Daftar berikut merangkum fakta tentang setiap ruang penyimpanan.
Penyimpanan internal:
- Ini selalu tersedia.
- File yang disimpan di sini hanya bisa diakses oleh aplikasi Anda.
- Bila pengguna mencopot pemasangan aplikasi Anda, sistem akan membuang semua file aplikasi Anda dari penyimpanan internal.
Penyimpanan internal adalah yang terbaik bila Anda memastikan bahwa baik pengguna maupun aplikasi lain tidak bisa mengakses file Anda.
Penyimpanan eksternal:
- Penyimpanan ini tidak selalu tersedia, karena pengguna bisa memasang penyimpanan eksternal sebagai penyimpanan USB dan dalam beberapa kasus melepasnya dari perangkat.
- Penyimpanan ini bisa dibaca di seluruh dunia, sehingga file yang disimpan di sini bisa dibaca di luar kontrol Anda.
- Bila pengguna mencopot pemasangan aplikasi Anda, sistem akan membuang file aplikasi Anda dari sini
hanya jika Anda menyimpannya dalam direktori dari
getExternalFilesDir().
Penyimpanan eksternal adalah tempat terbaik untuk file yang tidak memerlukan pembatasan akses dan untuk file yang ingin Anda gunakan bersama aplikasi lain atau memperbolehkan pengguna mengaksesnya dengan komputer.
Catatan: Sebelum Android N, file internal dapat dibuat bisa diakses oleh aplikasi
lain dengan melonggarkan izin sistem file. Ini tidak berlaku lagi. Jika Anda ingin
membuat materi file privat dapat diakses oleh aplikasi lain, aplikasi Anda dapat menggunakan
FileProvider. Lihat Berbagi File.
Tip: Walaupun aplikasi dipasang pada penyimpanan internal
secara default, Anda bisa menetapkan atribut android:installLocation dalam manifes sehingga aplikasi bisa
dipasang pada penyimpanan eksternal. Pengguna akan merasakan manfaat opsi ini saat ukuran APK sangat besar dan
pengguna memiliki ruang penyimpanan eksternal yang lebih besar daripada penyimpanan internal. Untuk
informasi selengkapnya, lihat Lokasi Pemasangan Aplikasi.
Memperoleh Izin untuk Penyimpanan Eksternal
Untuk menulis ke penyimpanan eksternal, Anda harus meminta
izin WRITE_EXTERNAL_STORAGE dalam file manifes:
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
Perhatian:
Saat ini, semua aplikasi memiliki kemampuan membaca penyimpanan eksternal
tanpa izin khusus. Akan tetapi, hal ini akan berubah di rilis mendatang. Jika aplikasi Anda perlu
membaca penyimpanan eksternal (namun bukan menulisnya), maka Anda perlu mendeklarasikan izin READ_EXTERNAL_STORAGE. Untuk memastikan aplikasi Anda tetap
bekerja seperti yang diharapkan, Anda harus mendeklarasikan izin ini sekarang, sebelum perubahan berlaku.
<manifest ...>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
</manifest>
Akan tetapi, jika aplikasi Anda menggunakan izin WRITE_EXTERNAL_STORAGE
, maka aplikasi memiliki izin secara implisit untuk membaca penyimpanan eksternal juga.
Anda tidak memerlukan izin apa pun untuk menyimpan file pada penyimpanan internal. Aplikasi Anda selalu memiliki izin untuk membaca dan menulis file dalam direktori penyimpanan internalnya.
Menyimpan File pada Penyimpanan Internal
Saat menyimpan file ke penyimpanan internal, Anda bisa memperoleh direktori yang tepat sebagai
File dengan memanggil salah satu dari dua metode:
getFilesDir()- Mengembalikan
Fileyang mewakili direktori internal untuk aplikasi Anda. getCacheDir()- Mengembalikan
Fileyang mewakili direktori internal untuk file cache sementara aplikasi Anda. Pastikan menghapus setiap file setelah tidak lagi diperlukan dan mengimplementasikan batas ukuran yang wajar untuk jumlah memori yang Anda gunakan pada suatu waktu, misalnya 1 MB. Jika mulai kekurangan storage, sistem bisa menghapus file cache Anda tanpa peringatan.
Untuk membuat file baru di salah satu direktori ini, Anda bisa menggunakan konstruktor File(), dengan meneruskan File yang disediakan oleh salah satu
metode di atas yang menetapkan direktori penyimpanan internal Anda. Misalnya:
File file = new File(context.getFilesDir(), filename);
Selain itu, Anda bisa memanggil openFileOutput() untuk mengambil FileOutputStream
yang menulis ke file dalam direktori internal Anda. Misalnya, inilah
cara menulis sejumlah teks ke file:
String filename = "myfile";
String string = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
Atau, jika Anda perlu menyimpan sementara beberapa file, lebih baik gunakan createTempFile(). Misalnya, metode berikut mengekstrak
nama file dari URL dan membuat file dengan nama itu
dalam direktori cache internal aplikasi Anda:
public File getTempFile(Context context, String url) {
File file;
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
} catch (IOException e) {
// Error while creating file
}
return file;
}
Catatan:
direktori penyimpanan internal aplikasi Anda ditetapkan
oleh nama paket aplikasi di lokasi khusus sistem file Android.
Secara teknis, aplikasi lain bisa membaca file internal itu jika Anda mengatur
mode file ke bisa dibaca. Akan tetapi, aplikasi lain nanti juga perlu mengetahui
nama paket dan nama file aplikasi Anda. Aplikasi lain tidak bisa menjelajah direktori internal Anda dan tidak memiliki
akses baca atau akses tulis kecuali Anda mengatur file itu secara eksplisit agar bisa dibaca atau bisa ditulis. Asalkan
Anda menggunakan MODE_PRIVATE untuk file pada penyimpanan internal,
file tersebut tidak akan bisa diakses aplikasi lain.
Menyimpan File pada Penyimpanan Eksternal
Karena penyimpanan eksternal mungkin saja tidak tersedia—misalnya saat pengguna memasang
storage ke PC atau melepaskan kartu SD yang menyediakan penyimpanan eksternal—Anda
harus selalu memverifikasi bahwa tersedia volume sebelum mengaksesnya. Anda bisa membuat kueri
status penyimpanan eksternal dengan memanggil getExternalStorageState(). Jika status yang dikembalikan
sama dengan MEDIA_MOUNTED, maka Anda bisa membaca dan
menulis file. Misalnya, metode berikut ini berguna untuk menentukan
ketersediaan storage:
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
Walaupun penyimpanan eksternal bisa dimodifikasi oleh pengguna dan aplikasi lain, ada dua kategori file yang bisa Anda simpan di sini:
- File publik
- File yang
harus tersedia secara bebas bagi aplikasi lain dan bagi pengguna. Bila pengguna mencopot pemasangan aplikasi Anda,
semua file ini harus tetap tersedia bagi pengguna.
Misalnya, foto yang dijepret oleh aplikasi Anda atau file unduhan lainnya.
- File privat
- File yang secara sah dimiliki aplikasi Anda dan harus dihapus bila pengguna mencopot pemasangan
aplikasi itu. Walaupun secara teknis semua file ini bisa diakses oleh pengguna dan aplikasi lain karena
berada di penyimpanan eksternal, secara realistis file itu tidak berharga bagi pengguna
di luar aplikasi Anda. Bila pengguna mencopot pemasangan aplikasi Anda, sistem akan menghapus
semua file dalam direktori privat eksternal aplikasi Anda.
Misalnya, sumber daya tambahan yang diunduh oleh aplikasi Anda atau file media sementara.
Jika Anda ingin menyimpan file publik pada penyimpanan eksternal, gunakan metode
getExternalStoragePublicDirectory() untuk mendapatkan File yang menyatakan
direktori yang sesuai pada penyimpanan eksternal. Metode ini mengambil argumen yang menetapkan
tipe file yang ingin Anda simpan sehingga file bisa ditata secara logis bersama file publik lainnya,
misalnya DIRECTORY_MUSIC atau DIRECTORY_PICTURES. Misalnya:
public File getAlbumStorageDir(String albumName) {
// Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
Jika ingin menyimpan file yang bersifat privat ke aplikasi, Anda bisa memperoleh
direktori yang sesuai dengan memanggil getExternalFilesDir() dan dengan meneruskan ke sana nama yang menunjukkan
tipe direktori yang Anda inginkan. Setiap direktori yang dibuat dengan cara ini akan ditambahkan ke satu
direktori induk yang membungkus semua file penyimpanan eksternal aplikasi Anda, yang akan dihapus sistem bila
pengguna mencopot pemasangan aplikasi Anda.
Misalnya, inilah metode yang bisa Anda gunakan untuk membuat direktori bagi album foto individual:
public File getAlbumStorageDir(Context context, String albumName) {
// Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
Jika tidak satu pun nama subdirektori yang telah didefinisikan cocok dengan file Anda, maka sebagai gantinya Anda bisa memanggil getExternalFilesDir() dan meneruskan null. Ini
mengembalikan direktori akar untuk direktori privat aplikasi Anda pada penyimpanan eksternal.
Ingatlah bahwa getExternalFilesDir()
akan membuat direktori dalam direktori yang akan dihapus bila pengguna mencopot pemasangan aplikasi Anda.
Jika file yang Anda simpan harus tetap tersedia setelah pengguna mencopot pemasangan
aplikasi Anda—misalnya bila aplikasi Anda adalah kamera dan pengguna ingin menyimpan foto—Anda
seharusnya menggunakan getExternalStoragePublicDirectory().
Terlepas dari apakah Anda menggunakan {@linkandroid.os.Environment#getExternalStoragePublicDirectory
getExternalStoragePublicDirectory()} untuk file yang digunakan bersama atau
getExternalFilesDir() untuk file yang bersifat privat bagi aplikasi Anda, Anda perlu menggunakan
nama direktori yang disediakan oleh konstanta API seperti
DIRECTORY_PICTURES. Nama direktori ini memastikan
file tersebut diperlakukan dengan benar oleh sistem. Misalnya, file yang disimpan di DIRECTORY_RINGTONESdigolongkan oleh pemindai media sistem sebagai nada dering,
bukannya musik.
Melakukan Kueri Ruang Bebas
Jika Anda sudah mengetahui jumlah data yang disimpan, Anda bisa mengetahui
apakah tersedia ruang yang cukup tanpa menyebabkan IOException dengan memanggil getFreeSpace() atau getTotalSpace(). Metode-metode ini masing-masing memberitahukan ruang tersedia saat ini dan
total ruang di volume storage. Informasi ini juga berguna untuk menghindari pengisian
volume storage di atas ambang tertentu.
Akan tetapi, sistem tidak menjamin Anda bisa menulis sebanyak jumlah byte
yang ditunjukkan oleh getFreeSpace(). Jika jumlah yang dikembalikan adalah
beberapa MB lebih dari ukuran data yang ingin Anda simpan, atau jika sistem file
kurang dari 90% penuh, maka mungkin akan aman untuk melanjutkan.
Jika tidak, mungkin Anda seharusnya tidak menulis ke storage.
Catatan: Anda tidak harus memeriksa jumlah ruang yang tersedia
sebelum menyimpan file. Sebagai gantinya, Anda bisa mencoba menulis file secara langsung, kemudian
menangkap IOException jika terjadi. Anda mungkin perlu melakukan
hal ini jika tidak mengetahui secara persis jumlah ruang yang diperlukan. Misalnya, jika Anda
mengubah enkode file sebelum menyimpannya dengan mengonversi gambar PNG ke
JPEG, Anda tidak akan mengetahui ukuran file sebelumnya.
Menghapus File
Anda harus selalu menghapus file yang tidak lagi diperlukan. Cara paling langsung untuk menghapus
file adalah membuat referensi file yang terbuka untuk memanggil delete() pada dirinya sendiri.
myFile.delete();
Jika file disimpan pada penyimpanan internal, Anda juga bisa meminta Context untuk menemukan dan
menghapus file dengan memanggil deleteFile():
myContext.deleteFile(fileName);
Catatan: Bila pengguna mencopot pemasangan aplikasi Anda, sistem Android akan menghapus yang berikut ini:
- Semua file Anda yang disimpan pada penyimpanan internal
- Semua file Anda yang disimpan pada penyimpanan eksternal dengan menggunakan
getExternalFilesDir().
Akan tetapi, Anda harus menghapus secara manual semua file cache yang dibuat dengan
getCacheDir() secara rutin, juga menghapus file lain
yang tidak lagi diperlukan secara rutin.