Content Provider (İçerik Sağlayıcı) Kullanımı ve Oluşturulması

Bilindiği gibi bir uygulama kendi veri tabanını dışarı açamaz.Fakat bilinidiği gibi Android İşletim Sisteminde tüm veriler çeşitli veritabanında sağlanmaktadır(Örneğin ContactList).Böylesi işlemler için ContentProvider yazılabilir. Content Providerlar bir adresie(URL) sahiptir.Bu adresin genel formatı şu şekildedir.

content://<authority>/<data-path>

Content Providerlar ile birçok bilgi elde edilebilir.

Örneğin bir Contactlist bilgileri için şu contentProvider kullanılabilir. content://contacts/people/1 şeklinde yazılırsa contactIdsi 1 olan kişi döndürülür.

Contactlist bilgileri izne tabidir.AndroidManifest.xml'e aşağıdaki gibi yazılmalıdır.

    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>

Ayrıca Android 6.0 Versiyonuyla beraber Contactlist erişimleri çalışma zamanı izinlerine göre de ele alınmaktadır.

Contacliste erişip listeleyen program aşağıdaki gibi yapılabilir. [Dropbox]085-ContactListContentProvider

Android APILEVEL11'den (Honeycomb modeliden) önce URI'a ilişkin bilgilerin elde edilmesi ManageQuery isimli senkron çalışan metodla yapılıyordu.Fakat bu modelden sonra CursorLoader isimli bir sınıf yardımıyla arkaplanda otomatik açılan bir akış yardımıyla bu işlem daha kolay bir biçimde yapılabilmektedir.

Anahtar Notlar: Bir uygulama içerisinde dinamik olarak versiyon kontrolü içerisinde android.os.Build.VERSION.SDK_INT ile kontrol edilebilir. Burada sdk_int değeri APILEVEL numarasıdır.

if (android.os.Build.VERSION.SDK_INT < 11) 
{
  //Honeycomb öncesi
}

ContentProviderlar aslında bir veritabanına ilişkin olduklarından bir Cursor kavramı her zaman gerekmektedir.

CursorLoader sınıfının başlangıç metodu 6 parametrelidir. Metodun 1.parametresi context referansı , 2.paramtresi URI referansıdır. Diğer parametreler null geçilebilir.Ne anlamlara geldikleri ileride ele alınacaktır.

Cursor yüklemek için loadingBackground metodu çağrılmaktadır.Bu metod arkaplanda bir akış oluşturarak ilgili kriterlere ilişkin Cursor nesnesi geri döndürmektedir.

Her contact bilgisinin bir id bilgisi bulunmaktadır.

ContentProvider isimlerinin hatırlanması zordur.Bu nedenle bu isimleri ve URI referansları bir sabit ile erişilebilir durumda bildirilmişlerdir.

Uri uri = ContactsContract.Contacts.CONTENT_URI

Contactlist'ten hareketle telefon bilgileri aşağıdaki gibi elde edilebilir.

 do {
            String id = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID));
            String name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

            Cursor phoneCursor = this.getContentResolver().query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + id, null, null
            );
            if (!phoneCursor.moveToFirst())
                continue;

            ContactInfo ci = new ContactInfo(id, name);

            while (phoneCursor.moveToNext()) {
                ci.addPhone(phoneCursor.getString(phoneCursor.getColumnIndex(
                        ContactsContract.CommonDataKinds.Phone.NUMBER
                )));
            }

            contacts.add(ci);

        } while (c.moveToNext());

Burada telefon numaraları başka bir tablodan alınmaktadır.Bu tablonun URI bilgisi şu şekildedir: ContactsContract.CommonDataKinds.Phone.CONTENT_URI

CursorLoader ile Dataların Filtrelenmesi

CursorLoader sınıfının başlangıç metodunun 4. ve 5. parametreleri filtrelenecek kriterleri içermektedir.Filtreleme işlemleri sql Where cümlesinin karşılığıdır.

            Cursor c = null;

            CursorLoader cl = new CursorLoader(
                    this,
                    uri,
                    null,
                    ContactsContract.Contacts.DISPLAY_NAME + " LIKE '" + m_editTextFilter.getText().toString() + "%'",
                    null,
                    null
            );

            c = cl.loadInBackground();

            this.listContacts(c);

CursorLoader sınıfının başlangıç metodunun 5. parametresi select işlemi için diğer argümanları temsil etmektedir.

CursorLoader ile Sıralama İşlemleri

CursorLoader sınıfının başlangıç metodunun 6. parametresi sql'de orderBy'a karşılık gelen sıralama işlemlerini belirtmektedir.Buna göre sıralama azalan sırada aşağıdaki gibi yapılabilir.

            Cursor c = null;

            CursorLoader cl = new CursorLoader(
                    this,
                    uri,
                    null,
                    ContactsContract.Contacts.DISPLAY_NAME + " LIKE '" + m_editTextFilter.getText().toString() + "%'",
                    null,
                    ContactsContract.Contacts.DISPLAY_NAME + " ASC"
            );

            c = cl.loadInBackground();

            this.listContacts(c);

CursorLoader ile Projection İşlemleri

Bazen programcı bütün alanları almak istemeyebilir.Bu durumda 3.parametre kullanılarak alacağı alanlara ilişkin bir String dizisi verilir.

            Cursor c = null;
            String [] projection = {ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME};

            CursorLoader cl = new CursorLoader(
                    this,
                    uri,
                    projection,
                    ContactsContract.Contacts.DISPLAY_NAME + " LIKE '" + m_editTextFilter.getText().toString() + "%'",
                    null,
                    ContactsContract.Contacts.DISPLAY_NAME + " ASC"
            );
            c = cl.loadInBackground();

Projection parametresinin null geçilmesi sqlde "select * from" ile eş değerdir.

CallLog Content Provider

Bir cihaza ilişkin arama bilgileri ContentProvider yardımıyla elde edilebilmektedir. Bu ContentProvider'ın genel biçimi content://call_logs/calls biçimindedir. Ayrıca bu isme calllog.calls.content uri sabiti ilede erişilebilir. Bu işlemin yapılabilmesi için READ_CALL_LOG izni gereklidir.

CallLog sınıfının Calls isimli içsel sınıfı içerisinde aramaya ilişkin birçok değer bulunmaktadır.

cachedName elemanı aramanın concact listiyle ilişkilendirilen ismini vermektedir.

086-CallLogContentProvider

Call sınıfının DATE sabiti ile referans bir zamandan(epoch time) o zamana kadarki milisaniye sayısı elde edilir.

Call sınıfının DATA_USAGE elemanı o aramanın kaç bytelık yer kapladığına ilişkin LONG türden bir değer döner. DATA_USAGE sabiti Android API LEVEL 23'ten itibaren geçerlidir.

CallLog'a ilişkin diğer elemanlar dökümanlardan bakılabilir. deneme

Content Provider Oluşturma

Bir program içerisinde kendi Content Provider'ımızı oluşturabiliriz.Bunun için önce veritabanının oluşturulması gerekir.

Content Provider için oluşturma adımları şunlardır:

  • Dışarıya verilecek olan veritabanı hazırlanır.
  • Dışarıya paylaşılacak olan Provider için
  • Content Provider'dan türetme yapılmadır.Bu sınıf içerisinde Content Provider'ın ismi ve paylaşılacak gibi alanlar belirlenir.
  • AndroidManifest.xml dosyasına ContentProvider'a ilişkin bilgiler yazılır, örnek bir yazılım aşağıdaki gibidir: ```xml <provider

          android:name="BooksProvider"
          android:authorities="org.csystem.samples.customcontentprovider.BooksProvider" >
    

    <\/provider>``` Provider ismi ve bir takım bilgiler bu sınıfta belirlenebilir.

ContentProvider'a ilişkin bir veritabanı ister programlama yöntemiyle isterse dışardan belirlebilir.

Şüphesiz bir uygulama başka bir uygulamanın veritabanına erişemeyeceğine göre ContentProvider'a ilişkin sınıfın başka bir uygulama içerisinde olması ve Client uygulamanın o uygulamaya ilişkin sınıfa erişmesi gerekmetektedir.

ContentProvider sınıfının insert, delete, query, update, onCreate gibi bir takım önemli metotları bulunmaktadır. Bu metotlar türemiş sınıflar içerisinde override edilmelidir. Yani aslında bu metotlar veritabının dışa sunulmuş halini temsil etmektedir.

ContentPRovider yazan bir programcı genel olarak bir Helper sınıf yazar ve bu sınıfı ContentProvider sınıfından türetilmiş bir sınıf içerisinde sarmalayarak dışarıya delete, insert, ve update gibi metotları sunar.

  • insert metodunun 1. parametresi Uri referansıdır, 2. parametresi ise eklenecek verileri içeren ContentValues referansıdır.

  • onCreate metodu içerisinde genel olarak önce bir Context nesnesi yaratılır. Sonra helper sınıftan hareketle veritabanına ilişkin referans elde edilir. Örneğin:

    @Override
      public boolean onCreate() {
          Context context = getContext();
          DatabaseHelper dbHelper = new DatabaseHelper(context);
          booksDB = dbHelper.getWritableDatabase();
          return (booksDB == null)? false:true;
      }
    

    Veritabanına herhangi bir sebeple iletişim saglanamadıgında onCreate metodu false olarak geri dönmelidir.

  • Sınıfın query metodu, Sqlite doğrudan erişim olan query metoduyla hemen hemen aynıdır, Uri referansı istemektedir.

  • Sınıfın update ve delete metotları da benzer şekilde düşünülebilir.

  • Sınıfın getType metodu, Uri bilgisine ilişikin MIME tür bilgisini içermektedir, bu durum ilerde ele alınacaktır. Örneğimizde getType metodu şu şekilde yazılmıştır: \/\/en son hali yazılacak.

Bu sınıfı kullanmak için ilgili Uri parse edildikten sonra yine CursorLoader sınıfı kullanılabilir. Content sınıfının getContentResolver metodu sınıf isminden, CursorLoader sınıfı ise Uri olarak ContentProvider sınıfına erişmektedir.