ANDROID İŞLETİM SİSTEMLERİNDE VERİ SAKLAMA YÖNTEMLERİ
Bir uygulama içerisindeki veriler Andorid işletim sisteminde genel olarak 3 şekilde kalıcı hale getirilebilir.
- Shared Preferences kullanılarak Veriler yarı kalıcı hale getirilebilir.
- Dosya Sistemi Kullanılarak Veriler yarı kalıcı ya da tam kalıcı hale getirilir.
- Veri tabanı kullanarak Veriler yarı kalıcı ve tam kalıcı hale getirilir.
Yarı kalıcı hale getirme uygulamanın verilerinin silinmesi veya uygulmanının uninstall edilmesi durumunda verilerin kaybedilmesi anlamındadır.
Bu bölümde bu konular detaylı olarak ele alınacaktır.
DOSYA İŞLEMLERİ
Android işletim sistemlerinde dosya işlemlerinde genel olarak kalıcı iki hafıza bulunmaktadır. Bunlardan işletim sistemiyle elde edilen hafızaya internal(içsel) memory , sd kart takılarak kullanılan memory'de External(dışsal) memory denilmektedir. Tipik olarak bir uygulama internal hafızaya veya external hafızaya veri yazılabilir.Ancak external hafızaya veri yazmak izinle gerçekleşir. Dosyaya yazma ve okuma işlemleri için Java'nın dosya işlemlerine ilişkin sınıflar kullanılabilmektedir. Java Kursu Dökümanları 89.Sayfa File İşlemleri
Internal Hafızaya Veri Yazılması
İçsel hafızaya yazma yapmak için OpenFileOutput
metodu ile yazma yapılabilir.
Benzer şekilde okuma işlemi için de OpenFileInput metodu kullanılmaktadır.
Bu metodlar Context sınıfının metodlarıdır . Activity sınıfı da Context sınıfından türetildiğinden bu metodlar Activity sınıfı içerisinde direk çağrılabilir.
m_fos = this.openFileOutput("hello.dat" , MODE_APPEND);
OpenFileOutput metodu bir isim ve dosyayı açacağı mod parametresini almalıdır.Metodunun geri dönüş değeri FileOutputStream
referansıdır.
Metodun mod parametresi
MODE_PRIVATE
MODE_APPEND
MODE_WORLD_READABLEMODE_WORLD_WRITEABLEgeçilebilir.MODE_WORLD_READABLE - MODE_WORLD_WRITEABLE
Android_ApiLevel_17(4.2)'den itibaren güvenlik açısından depricated hale getirilmiştir. MODE_PRIVATE : sabiti yanlızca o uygulama tarafından erişilebilen bir dosya yaratmayı sağlar. Anahtar Notlar: Unix/Linux sistemlerde her bir processin birUSERID
'si bulunur.Aslında içsel hafızaMODE_PRIVATE
ile yazılan dosyalarUSERID
'si aynı olan processler tarafından da erişilebilir.Bu kavram Unix/Linux programlamaya ilişkin bir kavramdır. MODE_APPEND : sabiti ile dosyanın sonuna ekleme yapılabilir.OpenFileOutput
metodunun geri dönüş değeri internal hafızaya ilişkinFileOutput
referansıdır.Bu referans kullanılarak işlem yapılabilir. Örnek Kod:[Dropbox]031-SaveLoadInternalMemory
NOTLARIM
[031]SaveLoadInternalMemory Ne Yapar?
EditText'e girilen datayı butona tıklanınca Dosyaya yazdırır. Load Butonuna basınca dosyadan okuyup List View'a yazdırır.
Android Ide Üzerinden Emulatordeki Dosyaya ulaşmak için
- Android Device Monitor
- Device>Emulator
- File Explorer tabı altından
- data/data/
/files Internal Memory'e yazılan dosyalar uygulamaya özgüdür.Her uygulama belirlenen paket ismini imza olarak kullanılır ve Internal Memory'de dosya , database gibi ikincil belleklerin yeri genel olarak şu şekildedir. /data/data/<PACKAGE_NAME>/files
içerisindedir. Bir program uninstall edildiğinde bu dizin de kalmayacağından Internal hafızaya yazılan dosyalar uninstall edildiğinde yok olmaktadır. Bu durumda programcı daha kalıcı bir işlem için External memory'i tercih etmelidir. Bu dizin diğer processler tarafından erişilebilir bir dizin değildir. Bu dizine ulaşılmaya çalışıldığında exception oluşturur.
Internal memory'ye yazma ve okuma yapan metodlar FileOutputStream ve FileInputStream nesnesi döndürdüğü için Java içerisinde herhangi bir sarmalayan sınıfı kullanılabilirler.
Örnek Kod:[Dropbox]032-MyMemoApp
Internal Hafızada Cache Dizisine Dosya Yazılması
Her uygulamanın cache adında bir dizini bulunmaktadır. Bu dizin uygulama sistem tarafından kapatılırsa (kill) otomatik olarak boşaltılan bir dizindir. Programcı bu dizini geçici bir dizin olarak görmeli ve bu dizine ilişkin yazacağı dosyaları çok fazla boyutlu yapmamalıdır.
Tavsiye edilen boyut 1 Mb olarak kaynaklarda söylenmektedir.
Bu dizindeki bilgiler uygulama yöneticisinin önbelleği sil seçeneğiyle de kullanıcı tarafından silinebilir.
Uygulamaya ilişkin geçiçi bilgiler burada tutulabilir.
Context sınıfının getCahceDir
isimli metodu ile cache dosyanın directory'si elde edilebilir.
getCacheDir
metodu File türünden bir referans döndürür.
Örnek Kod:[Dropbox]033-CacheDir
033-CacheDir Ne yapar? MAINACTIVITIY
- BUTTON_OK
BUTTON_OK tıklanınca random bir sayıyı cache'deki dosyaya yazar.
Anahtar Notlar : Uygulama yöneticisinden Clear Data seçeneğiyle cache dosyası da temizlemektedir. Bu durumdaki kalıcılığa dikkat edilmelidir.
External Hafızaya Erişim
Environment Sınıfı
Android Kütüphanesi içerisinde bir çok yararlı çevresel bilgilerin elde edilebilidiği Environment isimli bir sınıf bulunur. Environment sınıfı android.os paketi içerisinde bildirilmiştir.
Burada bir çok yararlı metod bulunmaktadır.
Örneğin getDataDirectory metodu kullanıcıya ilişkin data dizinin File referansını vermektedir. External (Dışsal) Hafızaya ilişkin bilgiler bu sınıftan alınabilmektedir.
Örneğin cihazın External hafızasına ilişkin dizin bilgisi getExternalStorageDircetory ile elde edilir. Bazı cihazlarda External hafıza bulunmayabilir.Hatta bazı cihazlar bazı işletim sistemleriyle beraber kullanıldığında her program o dışsal hafızaya dosya yazamayabilir.
Örneğin Androin4.4(KITKAT) sürümü ile external hafızaya yazmak güvenlik açısından engellenmiştir. Buradaki engelleme hiç yazamamak anlamında değildir.Tamamen belirli bir yazma yetkisine sahip olmakla ilgilidir.
Öyleyse programcı External hafızanın durumunu bilmelidir.External (Dışsal) hafızanın durumunu elde etmek için API LEVEL 21(LOLIPOP)'den sonra getExternalStorageState isimli bir metod çağrılmalıdır. APILEVEL21(LOLIPOP)'den önce ise getStorageState metodu kullanılabilir.
Bu sınıfın is ile başlayan bir takım yararlı metodları bulunmaktadır.isExternalStorageRemovable metodu External hafızanın çıkarılabilir olup olmadığını belirtir.
Sınıfın isExternalStorageEmulated
metodu emule edilmiş External Storage olup olmadığı bilgisini verir.
getExternalStorageState
Ve getStorageState
Metodları
Environment.getExternalStorageState();
Environment.getExternalStorageState(File path);
Bu metodlar aldıkları File referansının durumuna ilişkin bir String bilgisi döndürür.Bu bilgi aşağıdakilerden biri olabilir.
- MEDIA_UNKNOWN
- MEDIA_REMOVED
- MEDIA_UNMOUNTED
- MEDIA_CHECKING
- MEDIA_NOFS
- MEDIA_MOUNTED
- MEDIA_MOUNTED_READ_ONLY
- MEDIA_SHARED
- MEDIA_BAD_REMOVAL
- MEDIA_UNMOUNTABLE
Bir programın özellikle takılabilir bir External hafızaya yazma yapabilmesi için programcının önce External hafıza olup olmadığına ve varsa yazılabilir olup olmadığına bakması gerekir.
Bunun için aşağıdaki gibi bir metod yazılabilir.
public boolean isExternalStorageMountedAndWritable()
{
String state = Environment.getExternalStorageState();
boolean isWritable = false, isMounted = false;
if (state.equals(Environment.MEDIA_MOUNTED))
isMounted = isWritable = true;
else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY))
isMounted = true;
return isMounted && isWritable;
}
Aslında bu metod External hafızanın takılıp takılamadığını çoğunlukla yazılıp yazılamadığını test eder.
Bilindiği gibi Android sistemlerde bir takım işlemler yapabilmek için izinler gerekebilir. Bu izinler kurulum sırasında kullanıcıya sorulmaktadır. Güvenlik açısından izinle yapılabilecek işlemler için uygulamada izin bildirimi yapılmazsa ya o işlem yapıldığında hiçbir etki olmaz ya da Exception oluşur.
İzinler için AndroidManifest.xml
içerisinde uses-permission
alt elemanı kullanılmalıdır.
Bu alt elemanın Android:name
Attribute ile izinler verilebilir.
External Hafıza için android.permission.WRITE_EXTERNAL_STORAGE
ile izin alınacaktır.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Aslında External Storage için API Level 19 (KITKAT)'dan sonra okuma hakkı da izne tabidir. Ancak WRITE izni alınmışsa READ izni de otomatik olarak alınmış demektir.
Bu durum API Level 19 dan önce izne tabi değildir. İleride ele alınacak olan güvenlik konusunda bakılacaktır.
External Storage içerisinde bir takım önemli dizinler de bulunmaktadır.Bu dizinlere genel olarak Public Directory denilmektedir.
Public dizinler örneğin; Downloads , Music , Alarms , Pictures gibi dizinlerdir.
Bu dizinlerin yol ifadeleri Environment sınıfının getExternalStoragePublicDirectory
isimli metoduyla elde edilebilir.
public File getExternalStoragePublicDirectory(String type)
Bu metodun String türünden type parametresi Environment sınıfının aşağıdaki parametrelerinden biri olabilir.
DIRECTORY_ALARMS
DIRECTORY_DCIM
DIRECTORY_DOCUMENTS
DIRECTORY_DOWNLOADS
DIRECTORY_MOVIES
DIRECTORY_MUSIC
DIRECTORY_NOTIFICATIONS
DIRECTORY_PICTURES
Bu metoda geçilen sabitlerin bir kısmı sürümden sürüme farklılık gösterebilmektedir. Programcı seçimini dokümanlara bakarak dikkatli şekilde yapmalıdır.
Bu metodda dönen File referansına ilişkin dizinin varlığı garanti değildir.
Bunun için programcının bu dizini kullanmadan önce File.mkdirs
metodunu kullanması tavsiye edilir.
Örnek Kod:[DROPBOX]034-ExternalStorage
13 Mart
Anahtar Notlar: Android içerisinde bazı durumlar tehlikeli olarak değerlendirilmektedir. İzin alınsa bile çalışma zamanı sırasında extra bazı izinlerin alınması kavramı belirli sürümlerden sonra getirilmiştir. Bu kavrama genel olarak çalışma zamanı izinleri (Runtime Permissions) denir.
Android 6.0(Marshmallow) ile birlikte External hafızaya erişim ve bunun içerisinde public dosyalara erişim de Runtime Permissions'larla yapılmaktadır.Bu konu detaylı olarak ileride ele alınacaktır.
Var Olan Bir Dosyanın Projeye Eklenmesi
Bazı uygulamalara daha önceden elimizde bulunan bir dosya iliştirilmek istenebilir. Şüphesiz bu dosya runtime sırasında da elde eldilebilir ve üzerine yazma yapılabilir.Ancak kaynak (resource) kullanılarak bir proje içerisine iliştirilebilir.
Genel olarak programcı Android Ide içerisinde res
dizini içerisinde raw
isimli bir dizin açar.Ve ilgili dosyayı bu dizine ekler.
Context sınıfının getResources
metodu ile tüm kaynak bilgileri elde edilebilir.
getResources
metodu Resources türünden bir referans döndürmektedir.
Bu sınıfın openRawResource
isimli metodu yardımıyla Raw kaynağındaki herhangi bir dosya InputStream türünden referans ile elde edilebilir.
openRawResource
metoduyla drawable sound gibi kaynaklar içerisindeki veriler de elde edilebilir.Fakat string ve color gibi kaynaklar bu metod ile elde edilemez.
InputStream is = this.getResources().openRawResources(R.raw.names)
Örnek Proje:[Dropbox]035-ResourceRawFiles
035-ResourceRawFiles ne yapar?
Text dosyası içerisindeki dataları Listview'e ekleme
Shared Preferences ile Uygulamanın Verilerinin Saklanması
Bir uygulama için bazı basit bilgilerin o an saklanması ve tekrar elde edilebilmesi için Shared Preferences denilen bir alan kullanılır.
Bu alandaki dosyalar uygulamanın verileri silindiğinde yok edilmektedir.Bu yüzden programcı açısından cache dosyalar gibi yarı kalıcı alanlar olarak düşünülmelidir.
Bu yöntemi kullanmak için SharedPreferences
isimli bir sınıf kullanılmaktadır.Bu sınıfın içerisinde nested(içiçe) olarak bildirilmiş Editor
isimli bir arayüz bulunmaktadır.SharedPreferences
sınıfının edit metodu ile bu arayüz türünden referans elde edilebilir.
Buna göre SharedPreferences'a kaydetme işlemi aşağıdaki adımlarla yapılabilir.
- Uygulamanın SharedPreferences referansı Context sınıfının
getSharedPreferences
isimli metoduyla elde edilebilir. - Elde Edilen Bu referansla
edit
metodu çağrılarak Edıtor elde edilir. - Elde edilen bu map collection refenrasının
putxx
metodlarıyla Edıtor'e elemanlar eklenir. - Eklenenlerin kaydedilmesi için
commit
ya daapply
metodu çağrılır.
android.Content
isimili paketin içerisinde bildirilimiştir.
SharedPreferences'a ekleme yapıldığında eklemeler bir xml dosyasına yapılır.Bu xml dosyası istenildiği gibi kullanılabilir.Programcının oluşacak dosyasnın ismini vermesi yeterlidir.Xml uzantısı otomatik eklenecektir.
Bu xml dosyası dışarıdan da verilebilir.Bu yüzden xml olarak tutulmaktadır.
[DROPBOX-038-SharedPreferences]
Varolan bir preferences dosyasından okuma yapmak için aşagıdaki adımlar izlenmedlidir.
SharedPreferences
nesnesi alınır.- Preferences nesnesinin
getXX
metodlarıyla daha önce elde edilen anahtarlara ilişkin değerler elde edilip kullanılabilir.
commit
ile apply
arasında küçük bir kaç fark vardır.
commit
metodu commit edilip edilmediğine ilişkin boolean değer döndürür.apply da geri dönüş değeri yoktur.commit
metodu commit işlemi bitene kadar akışı döndürmez senkron çalışır.Ancak apply metodu yazma işlemi yapana kadar beklemez ve akış yoluna devam eder.Bu konu çok thread'li çalışmada ayrıca ele alınacaktır.
Çok büyük verileri Shared Preferences da saklamak tavsiye edilen bir yöntem değildir.Ancak uygulamanın bir takım ayarları gibi basit bilgiler daha sonra elde edilmek üzere Shared Preferences da saklanabilir.
Peki uygulamanın activitysine ait ayar bilgileri ne zaman sharedPreferencesa eklenir ? Bunun en iyi çözüm yeri Activityni yaşam döngüsü içindeki onPause
metodudur.
Daha öncede belirtildiği gibi onStop
ve onDestroy
metodlarının çoğu zaman problem oluşmasada çağrılmasının garantisi yoktur.Bu yüzden en iyi yer onPause
metodunda yapılmasıdır.Şüphesiz Preferences bilgileri onCreate
ya da onResume
da okunabilir.
Bir uygulamaya ilişkin birden fazla Shared Preferences nesnesi olabilir.Bu durumda programcı getSharedPreferences
metdounun 1. parametresine ayrı ayrı isimler geçebilir.
SharedPreferences getSharedPreferences(String name , int mode)