Bir kişinin ayrıntılarını alma

Bu derste bir kişiyle ilgili e-posta adresi, telefon numarası gibi ayrıntılı verilerin nasıl alınacağı gösterilmektedir. Kullanıcıların bir kişiyi geri alırken aradığı ayrıntılardır. Onlara bir kişiyle ilgili tüm ayrıntıları verebilir veya yalnızca belirli türdeki ayrıntıları (ör. e-posta adresleri) görüntüleyebilirsiniz.

Bu dersteki adımlarda, kullanıcının seçtiği bir kişi için zaten bir ContactsContract.Contacts satırınızın olduğu varsayılmaktadır. Kişi adlarını alma dersinde, kişi listesinin nasıl alınacağı gösterilmektedir.

Bir kişiye ilişkin tüm ayrıntıları alma

Bir kişiyle ilgili tüm ayrıntıları almak için ContactsContract.Data tablosunda kişinin LOOKUP_KEY özelliğini içeren tüm satırları arayın. Kişi Sağlayıcısı ContactsContract.Contacts tablosu ile ContactsContract.Data tablosu arasında dolaylı bir birleştirme işlemi yaptığından bu sütun ContactsContract.Data tablosunda bulunur. LOOKUP_KEY sütunu, Kişi adlarını alma dersinde daha ayrıntılı olarak açıklanmıştır.

Not: Bir kişiyle ilgili tüm ayrıntıların alınması, ContactsContract.Data tablosundaki tüm sütunları alması gerektiği için 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 okuyabilmek için uygulamanızın READ_CONTACTS izni olması gerekir. Bu izni istemek için manifest dosyanıza şu <manifest> alt öğesini ekleyin:

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

Projeksiyon oluşturma

Bir satır, içerdiği veri türüne bağlı olarak yalnızca birkaç sütun veya çok sayıda sütun kullanabilir. Ayrıca veriler, veri türüne bağlı olarak farklı sütunlarda bulunur. Olası tüm veri türleri için mümkün olan tüm sütunları aldığınızdan emin olmak amacıyla tüm sütun adlarını projeksiyonunuza eklemeniz gerekir. Cursor sonucunu bir ListView öğesine bağlıyorsanız her zaman Data._ID dosyasını alın. Aksi takdirde bağlama çalışmaz. Ayrıca, aldığınız her satırın veri türünü tanımlayabilmeniz için Data.MIMETYPE öğesini 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ıra ait tüm sütunları alır.

İsteğe bağlı olarak, ContactsContract.Data sınıfında tanımlanan veya bu sınıf tarafından 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ılması amaçlandığından bu sütunların verileri faydalı değildir.

Seçim ölçütlerini tanımlayın

Seçim ifadeniz için bir sabit değer, 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 metin ifadenizde yer tutucu olarak "?" kullanmanız, sonuçta kullanılacak aramanın SQL derlemesi yerine bağlama ile oluşturulmasını sağlar. Bu yaklaşım, kötü amaçlı SQL yerleştirme ihtimalini ortadan kaldırır.

Sıralama ölçütünü tanımlayın

Sonuçta elde edilen Cursor içinde istediğiniz sıralama düzenini tanımlayın. Belirli bir veri türüne ait tüm satırları bir arada tutmak için Data.MIMETYPE ölçütüne 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ı ve benzer şekilde 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ürleri alt tür kullanmadığından alt türe göre sıralama yapamazsınız. Bunun yerine, döndürülen Cursor öğesini yinelemeniz, geçerli satırın veri türünü belirlemeniz ve alt tür kullanan satırlara ait verileri 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şi Sağlayıcı'dan (ve diğer tüm içerik sağlayıcılardan) alma işlemlerini her zaman bir arka plan ileti dizisinde gerçekleştirin. Arka plan alma işlemleri yapmak için LoaderManager sınıfıyla ve LoaderManager.LoaderCallbacks arayüzüyle tanımlanan Yükleyici çerçevesini kullanın.

Satırları almaya hazır olduğunuzda initLoader() yöntemini çağırarak yükleyici çerçevesini başlatın. Yönteme bir tam sayı tanımlayıcı iletin. Bu tanımlayıcı, LoaderManager.LoaderCallbacks yöntemlerine iletilir. Tanımlayıcı, aralarında ayrım yapmanıza 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 başlatılacağı 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() işlevini uygulama

initLoader() çağrısından hemen sonra yükleyici çerçevesi tarafından çağrılan onCreateLoader() yöntemini uygulayın. Bu yöntemden bir CursorLoader döndürün. ContactsContract.Data tablosunda arama yaptığınızdan içerik URI'si olarak Data.CONTENT_URI sabit değerini 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şlevini uygulayın

onLoadFinished() yöntemini uygulayın. Kişi Sağlayıcısı sorgunun sonuçlarını döndürdüğünde yükleyici çerçevesi onLoadFinished() işlevini çağırır. Ö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, Cursor sonucunu destekleyen verilerin değiştiğini algıladığında onLoaderReset() yöntemi çağrılır. Bu noktada, Cursor öğesine yönelik mevcut referansları boş olarak ayarlayarak kaldırın. Bunu yapmazsanız yükleyici çerçevesi eski Cursor öğesini kaldırmaz ve bellek sızıntısı yaşanır. Ö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 ayrıntıları alma

Bir kişi için belirli bir veri türünü (örneğin, tüm e-postaları) alma, tüm ayrıntıları almayla aynı kalıbı izler. Bir kişiyle ilgili tüm ayrıntıları alma bölümünde listelenen kodda yalnızca aşağıdaki değişiklikleri yapmanız yeterlidir:

Projeksiyon
Veri türüne özel sütunları almak için projeksiyonunuzu değiştirin. Ayrıca, projeksiyonu, veri türüne karşılık gelen ContactsContract.CommonDataKinds alt sınıfında tanımlanan sütun adı sabitlerini kullanacak şekilde değiştirin.
Seçim
Veri türünüze özgü MIMETYPE değerini aramak için seçim metnini değiştirin.
Sıralama şekli
Yalnızca tek bir ayrıntı türü seçtiğinizden, döndürülen Cursor öğesini Data.MIMETYPE ölçütüne göre gruplandırmayın.

Bu değişiklikler aşağıdaki bölümlerde açıklanmaktadı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 cihazınızı bir 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 özgü sütun adlarını kullanmak, kodu daha okunaklı hale getirir.

Projeksiyonda, ContactsContract.CommonDataKinds alt sınıfında tanımlanan diğer sütunlardan da herhangi birini kullanabilirsiniz.

Seçim ölçütlerini tanımlayın

Belirli bir kişinin LOOKUP_KEY ve istediğiniz ayrıntıların Data.MIMETYPE kısmı için satırları alan bir arama metin ifadesi tanımlayın. Bir "'" (tek tırnak) karakterini sabit değerin başında ve sonunda birleştirerek MIMETYPE değerini tek tırnak içine alın. Aksi takdirde, sağlayıcı sabit değeri dize değeri yerine değişken adı olarak yorumlar. Kullanıcı tarafından sağlanan değer yerine sabit bir değer kullandığınızdan 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 düzeni tanımlayın. Belirli bir veri türünü aldığınız için MIMETYPE bölümündeki 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 verilerini Email.TYPE öğesine göre sıralayabilirsiniz:

Kotlin

private const val SORT_ORDER: String = "${Email.TYPE} ASC"

Java

    private static final String SORT_ORDER = Email.TYPE + " ASC ";