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.

  1. Shared Preferences kullanılarak Veriler yarı kalıcı hale getirilebilir.
  2. Dosya Sistemi Kullanılarak Veriler yarı kalıcı ya da tam kalıcı hale getirilir.
  3. 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_READABLE
  • MODE_WORLD_WRITEABLE geç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 bir USERID'si bulunur.Aslında içsel hafıza MODE_PRIVATE ile yazılan dosyalar USERID'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şkin FileOutput 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 da apply 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)