Bu derste, bir kişinin e-posta adresleri, telefon numaraları gibi ayrıntılı verilerinin nasıl alınacağı gösterilmektedir. Kullanıcılar bir kişiyi aldıklarında bu ayrıntıları arar. Kişiyle ilgili tüm ayrıntıları verebilir veya yalnızca belirli bir türdeki ayrıntıları (ör. e-posta adresleri) gösterebilirsiniz.
Bu dersteki adımlarda, kullanıcının seçtiği bir kişi için zaten bir ContactsContract.Contacts satırınız olduğu varsayılır.
Kişi adlarını alma dersinde, kişi listesinin nasıl alınacağı gösterilmektedir.
Bir kişinin tüm ayrıntılarını alma
Bir kişiyle ilgili tüm bilgileri almak için ContactsContract.Data tablosunda kişinin LOOKUP_KEY bilgisini içeren satırları arayın. Bu sütun, ContactsContract.Data tablosunda kullanılabilir. Bunun nedeni, Contacts Provider'ın ContactsContract.Contacts tablosu ile ContactsContract.Data tablosu arasında örtülü bir birleştirme yapmasıdır. LOOKUP_KEY sütunu, Kişi adlarını alma dersinde daha ayrıntılı olarak açıklanmaktadır.
Not: Bir kişiyle ilgili tüm ayrıntıların alınması, ContactsContract.Data tablosundaki tüm sütunların alınmasını gerektirdiğinden cihazın performansını düşürür. Bu tekniği kullanmadan önce performans üzerindeki etkisini göz önünde bulundurun.
İzin iste
Kişiler sağlayıcıdan okuma yapmak için uygulamanızda
READ_CONTACTS izni olmalıdır.
Bu izni istemek için manifest dosyanıza
<manifest> öğesinin aşağıdaki alt öğesini ekleyin:
<uses-permission android:name="android.permission.READ_CONTACTS" />
Yansıtma ayarlama
Bir satırın içerdiği veri türüne bağlı olarak yalnızca birkaç sütun veya çok sayıda sütun kullanılabilir. Ayrıca, veriler veri türüne göre farklı sütunlarda yer alır.
Olası tüm veri türleri için olası tüm sütunları aldığınızdan emin olmak istiyorsanız tüm sütun adlarını projeksiyonunuza eklemeniz gerekir. Sonucu ListView ile bağlıyorsanız her zaman Data._ID değerini alın. Aksi takdirde bağlama işlemiCursor çalışmaz. Ayrıca, aldığınız her satırın veri türünü belirleyebilmek için Data.MIMETYPE değerini de alın. Örneğin:
Kotlin
private val PROJECTION: Array<out String> = arrayOf( ContactsContract.Data._ID, ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1, ContactsContract.Data.DATA2, ContactsContract.Data.DATA3, ContactsContract.Data.DATA4, ContactsContract.Data.DATA5, ContactsContract.Data.DATA6, ContactsContract.Data.DATA7, ContactsContract.Data.DATA8, ContactsContract.Data.DATA9, ContactsContract.Data.DATA10, ContactsContract.Data.DATA11, ContactsContract.Data.DATA12, ContactsContract.Data.DATA13, ContactsContract.Data.DATA14, ContactsContract.Data.DATA15 )
Java
private static final String[] PROJECTION = { ContactsContract.Data._ID, ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1, ContactsContract.Data.DATA2, ContactsContract.Data.DATA3, ContactsContract.Data.DATA4, ContactsContract.Data.DATA5, ContactsContract.Data.DATA6, ContactsContract.Data.DATA7, ContactsContract.Data.DATA8, ContactsContract.Data.DATA9, ContactsContract.Data.DATA10, ContactsContract.Data.DATA11, ContactsContract.Data.DATA12, ContactsContract.Data.DATA13, ContactsContract.Data.DATA14, ContactsContract.Data.DATA15 };
Bu projeksiyon, ContactsContract.Data sınıfında tanımlanan sütun adlarını kullanarak ContactsContract.Data tablosundaki bir satırın tüm sütunlarını alır.
İsteğe bağlı olarak, ContactsContract.Data sınıfında tanımlanan veya bu sınıftan devralınan diğer sütun sabitlerini de kullanabilirsiniz. Ancak SYNC1 ile SYNC4 arasındaki sütunların senkronizasyon bağdaştırıcıları tarafından kullanılmak üzere tasarlandığını ve bu nedenle verilerinin yararlı olmadığını unutmayın.
Seçim ölçütlerini tanımlama
Seçim koşulunuz için bir sabit, seçim bağımsız değişkenlerini tutacak bir dizi ve seçim değerini tutacak bir değişken tanımlayın. Kişiyi bulmak için Contacts.LOOKUP_KEY sütununu kullanın. Örneğin:
Kotlin
// Defines the selection clause private const val SELECTION: String = "${ContactsContract.Data.LOOKUP_KEY} = ?" ... // Defines the array to hold the search criteria private val selectionArgs: Array<String> = arrayOf("") /* * Defines a variable to contain the selection value. Once you * have the Cursor from the Contacts table, and you've selected * the desired row, move the row's LOOKUP_KEY value into this * variable. */ private var lookupKey: String? = null
Java
// Defines the selection clause private static final String SELECTION = Data.LOOKUP_KEY + " = ?"; // Defines the array to hold the search criteria private String[] selectionArgs = { "" }; /* * Defines a variable to contain the selection value. Once you * have the Cursor from the Contacts table, and you've selected * the desired row, move the row's LOOKUP_KEY value into this * variable. */ private lateinit var lookupKey: String
Seçim metni ifadesinde yer tutucu olarak "?" kullanmak, sonuçtaki aramanın SQL derlemesi yerine bağlama yoluyla oluşturulmasını sağlar. Bu yaklaşım, kötü amaçlı SQL yerleştirme olasılığını ortadan kaldırır.
Sıralama ölçütünü tanımlama
Sonuçtaki Cursor için istediğiniz sıralama ölçütünü tanımlayın. Belirli bir veri türüne ait tüm satırları bir arada tutmak için Data.MIMETYPE sütununa göre sıralayın. Bu sorgu bağımsız değişkeni, tüm e-posta satırlarını, tüm telefon satırlarını vb. gruplandırır. Örneğin:
Kotlin
/* * Defines a string that specifies a sort order of MIME type */ private const val SORT_ORDER = ContactsContract.Data.MIMETYPE
Java
/* * Defines a string that specifies a sort order of MIME type */ private static final String SORT_ORDER = ContactsContract.Data.MIMETYPE;
Not: Bazı veri türlerinde alt tür kullanılmadığı için alt türe göre sıralama yapamazsınız.
Bunun yerine, döndürülen Cursor üzerinde iterasyon yapmanız, mevcut satırın veri türünü belirlemeniz ve bir alt tür kullanan satırların verilerini depolamanız gerekir. İmleci okumayı bitirdiğinizde her veri türünü alt türe göre sıralayabilir ve sonuçları görüntüleyebilirsiniz.
Yükleyiciyi başlatma
Kişiler Sağlayıcı'dan (ve diğer tüm içerik sağlayıcılardan) veri alma işlemlerini her zaman arka plan iş parçacığında yapın. Arka planda veri alma işlemleri için LoaderManager sınıfı ve LoaderManager.LoaderCallbacks arayüzü tarafından tanımlanan Loader çerçevesini kullanın.
Satırları almaya hazır olduğunuzda initLoader() yöntemini çağırarak yükleyici çerçevesini ilk kullanıma hazırlayın. Yönteme bir tam sayı tanımlayıcı iletin. Bu tanımlayıcı, LoaderManager.LoaderCallbacks yöntemlerine iletilir. Tanımlayıcı, yükleyicileri ayırt etmenize olanak tanıyarak bir uygulamada birden fazla yükleyici kullanmanıza yardımcı olur.
Aşağıdaki snippet'te yükleyici çerçevesinin nasıl ilk kullanıma hazırlanacağı gösterilmektedir:
Kotlin
// Defines a constant that identifies the loader private const val DETAILS_QUERY_ID: Int = 0 class DetailsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor> { ... override fun onCreate(savedInstanceState: Bundle?) { ... // Initializes the loader framework loaderManager.initLoader(DETAILS_QUERY_ID, null, this)
Java
public class DetailsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { ... // Defines a constant that identifies the loader static int DETAILS_QUERY_ID = 0; ... @Override public void onCreate(Bundle savedInstanceState) { ... // Initializes the loader framework getLoaderManager().initLoader(DETAILS_QUERY_ID, null, this);
onCreateLoader() yöntemini uygulama
onCreateLoader() yöntemini uygulayın. Bu yöntem, initLoader() yöntemini çağırdıktan hemen sonra yükleyici çerçevesi tarafından çağrılır. Bu yöntemden bir CursorLoader döndürün. ContactsContract.Data tablosunda arama yaptığınız için içerik URI'si olarak Data.CONTENT_URI sabitini kullanın.
Örneğin:
Kotlin
override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { // Choose the proper action mLoader = when(loaderId) { DETAILS_QUERY_ID -> { // Assigns the selection parameter selectionArgs[0] = lookupKey // Starts the query activity?.let { CursorLoader( it, ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, SORT_ORDER ) } } ... } return mLoader }
Java
@Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { // Choose the proper action switch (loaderId) { case DETAILS_QUERY_ID: // Assigns the selection parameter selectionArgs[0] = lookupKey; // Starts the query CursorLoader mLoader = new CursorLoader( getActivity(), ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, SORT_ORDER ); }
onLoadFinished() ve onLoaderReset() işlevlerini uygulama
onLoadFinished() yöntemini uygulayın. Yükleyici çerçevesi, Kişiler Sağlayıcı sorgu sonuçlarını döndürdüğünde onLoadFinished()
çağrısını yapar. Örneğin:
Kotlin
override fun onLoadFinished(loader: Loader<Cursor>, data: Cursor) { when(loader.id) { DETAILS_QUERY_ID -> { /* * Process the resulting Cursor here. */ } ... } }
Java
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { switch (loader.getId()) { case DETAILS_QUERY_ID: /* * Process the resulting Cursor here. */ } break; ... } }
Yükleyici çerçevesi, sonucu destekleyen verilerin onLoaderReset() değiştiğini algıladığında Cursor yöntemi çağrılır. Bu noktada, Cursor ile ilgili mevcut tüm referansları null olarak ayarlayarak kaldırın. Bunu yapmazsanız yükleyici çerçevesi eski Cursor öğesini yok etmez ve bellek sızıntısı yaşarsınız. Örneğin:
Kotlin
override fun onLoaderReset(loader: Loader<Cursor>) { when (loader.id) { DETAILS_QUERY_ID -> { /* * If you have current references to the Cursor, * remove them here. */ } ... } }
Java
@Override public void onLoaderReset(Loader<Cursor> loader) { switch (loader.getId()) { case DETAILS_QUERY_ID: /* * If you have current references to the Cursor, * remove them here. */ } break; }
Bir kişiyle ilgili belirli bilgileri alma
Bir kişiyle ilgili belirli bir veri türünü (ör. tüm e-postalar) alma işlemi, tüm ayrıntıları alma işlemiyle aynı şekilde yapılır. Bir kişiyle ilgili tüm ayrıntıları alma bölümünde listelenen kodda yapmanız gereken tek değişiklikler şunlardır:
- Projeksiyon
-
Veri türüne özgü sütunları almak için projeksiyonunuzu değiştirin. Ayrıca, yansıtmayı, veri türüne karşılık gelen
ContactsContract.CommonDataKindsalt sınıfında tanımlanan sütun adı sabitlerini kullanacak şekilde değiştirin. - Seçim
-
Seçim metnini, veri türünüze özgü
MIMETYPEdeğerini arayacak şekilde değiştirin. - Sıralama şekli
-
Yalnızca tek bir ayrıntı türü seçtiğiniz için döndürülen
CursordeğerleriniData.MIMETYPEile gruplandırmayın.
Bu değişiklikler aşağıdaki bölümlerde açıklanmıştır.
Projeksiyon tanımlama
Veri türü için ContactsContract.CommonDataKinds alt sınıfındaki sütun adı sabitlerini kullanarak almak istediğiniz sütunları tanımlayın.
Cursor öğenizi ListView öğesine bağlamayı planlıyorsanız _ID sütununu aldığınızdan emin olun. Örneğin, e-posta verilerini almak için aşağıdaki projeksiyonu tanımlayın:
Kotlin
private val PROJECTION: Array<String> = arrayOf( ContactsContract.CommonDataKinds.Email._ID, ContactsContract.CommonDataKinds.Email.ADDRESS, ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.LABEL )
Java
private static final String[] PROJECTION = { ContactsContract.CommonDataKinds.Email._ID, ContactsContract.CommonDataKinds.Email.ADDRESS, ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.LABEL };
Bu projeksiyonun, ContactsContract.Data sınıfında tanımlanan sütun adları yerine ContactsContract.CommonDataKinds.Email sınıfında tanımlanan sütun adlarını kullandığına dikkat edin. E-postaya özel sütun adlarının kullanılması, kodun daha okunabilir olmasını sağlar.
Projeksiyonda, ContactsContract.CommonDataKinds alt sınıfında tanımlanan diğer sütunlardan herhangi birini de kullanabilirsiniz.
Seçim ölçütlerini tanımlama
Belirli bir kişinin LOOKUP_KEY ve istediğiniz ayrıntıların Data.MIMETYPE değerlerini içeren satırları alan bir arama metni ifadesi tanımlayın. Sabitin başına ve sonuna "'" (tek tırnak) karakteri ekleyerek MIMETYPE değerini tek tırnak içine alın. Aksi takdirde, sağlayıcı sabiti dize değeri olarak değil, değişken adı olarak yorumlar. Kullanıcı tarafından sağlanan bir değer yerine sabit bir değer kullandığınız için bu değer için yer tutucu kullanmanız gerekmez. Örneğin:
Kotlin
/* * Defines the selection clause. Search for a lookup key * and the Email MIME type */ private const val SELECTION = "${ContactsContract.Data.LOOKUP_KEY} = ? AND " + "${ContactsContract.Data.MIMETYPE} = '${Email.CONTENT_ITEM_TYPE}'" ... // Defines the array to hold the search criteria private val selectionArgs: Array<String> = arrayOf("")
Java
/* * Defines the selection clause. Search for a lookup key * and the Email MIME type */ private static final String SELECTION = Data.LOOKUP_KEY + " = ?" + " AND " + Data.MIMETYPE + " = " + "'" + Email.CONTENT_ITEM_TYPE + "'"; // Defines the array to hold the search criteria private String[] selectionArgs = { "" };
Sıralama ölçütü tanımlama
Döndürülen Cursor için bir sıralama ölçütü tanımlayın. Belirli bir veri türünü aldığınız için MIMETYPE üzerindeki sıralamayı atlayın.
Bunun yerine, aradığınız ayrıntı verisi türü bir alt tür içeriyorsa buna göre sıralayın.
Örneğin, e-posta verileri için Email.TYPE göre sıralama yapabilirsiniz:
Kotlin
private const val SORT_ORDER: String = "${Email.TYPE} ASC"
Java
private static final String SORT_ORDER = Email.TYPE + " ASC ";