İçerik sağlayıcı oluşturma

İçerik sağlayıcı, merkezi bir veri deposuna erişimi yönetir. Bir sağlayıcısını bir veya daha fazla sınıf olarak düzenleyebilir ve manifest dosyasıdır. Sınıflarınızdan birinde şu alt sınıf uygulanıyor: ContentProvider, yani sağlayıcınız ile başka uygulamalar da var.

İçerik sağlayıcıların amacı, diğer kullanıcıların da en az uygulamanızda, kullanıcının başka uygulamaları kullanarak sağlayıcınız tarafından yönetilen verileri sorgulayabilir ve değiştirebilirsiniz.

Bu sayfa, içerik sağlayıcı ve liste oluşturmaya ilişkin temel süreci içerir API'lerden genel olarak bahsetmek istiyorum.

Yapı oluşturmaya başlamadan önce

Sağlayıcı oluşturmaya başlamadan önce aşağıdakileri göz önünde bulundurun:

  • İçerik sağlayıcıya ihtiyacınız olup olmadığına karar verin. İçerik üretmeniz ve aşağıdaki özelliklerden birini veya daha fazlasını sunmak isterseniz:
    • Karmaşık verileri veya dosyaları diğer uygulamalara sunmak istiyorsanız.
    • Kullanıcıların uygulamanızdaki karmaşık verileri diğer uygulamalara kopyalamasına izin vermek istiyorsunuz.
    • Arama çerçevesini kullanarak özel arama önerileri sunmak istiyorsunuz.
    • Uygulama verilerinizi widget'lara göstermek istiyorsunuz.
    • AbstractThreadedSyncAdapter öğesini uygulamak istiyorsanız, CursorAdapter veya CursorLoader sınıflar.

    Veritabanlarını veya diğer veri tabanlarını kullanmak için bir sağlayıcıya kullanım tamamen kendi uygulamanızdan gerçekleştiriliyorsa kalıcı depolama alanı Bu nedenle, yukarıda listelenen özelliklerden hiçbirine ihtiyacınız yok. Bunun yerine şurada açıklanan depolama sistemlerinden birini kullanmalısınız: Veri ve dosya depolamaya genel bakış.

  • Henüz yapmadıysanız İçerik sağlayıcılar ve bunların işleyiş şekli hakkında daha fazla bilgi edinmek için İçerik Sağlayıcı ile ilgili temel bilgiler bölümüne göz atın.

Ardından, sağlayıcınızı oluşturmak için aşağıdaki adımları uygulayın:

  1. Verileriniz için ham depolama alanını tasarlayın. İçerik sağlayıcı, verileri iki şekilde sunar:
    Dosya verileri
    . Örneğin, fotoğraf, ses veya video olabilir. Dosyaları uygulamanızın gizli boşluk oluşturur. Başka bir uygulamadan gelen dosya isteğine yanıt olarak, sağlayıcı, dosya için bir herkese açık kullanıcı adı sunabilir.
    "Yapılandırılmış" veri
    . Normalde bir veritabanına, diziye veya benzer bir yapıya giden verilerdir. Verileri, satır ve sütun tablolarıyla uyumlu bir formda depolayın. Bir satır envanterdeki bir kişi veya öğe gibi bir varlığı temsil eder. Bir sütun, varlıkla ilgili bazı veriler (ör. kişinin adı veya ürünün fiyatı). Bir projede bir SQLite veritabanında bulunmasını gerektirir, ancak kalıcı depolama alanıdır. Şurada kullanılabilen depolama alanı türleri hakkında daha fazla bilgi edinin: Android sistemi için: Veri depolamayı tasarlayın bölümüne bakın.
  2. ContentProvider sınıfının somut bir uygulamasını tanımlama ve yöntemlerine göz atacağız. Bu sınıf, verilerinizle diğer Android sistemi. Bu sınıf hakkında daha fazla bilgi için bkz. ContentProvider sınıfını uygulama bölümünü inceleyin.
  3. Sağlayıcının yetki dizesini, içerik URI'lerini ve sütun adlarını tanımlayın. Şunu istiyorsanız: amaca hizmet eden, ayrıca intent işlemlerini, ekstra verileri ve ve işaretler. Ayrıca verilerinize erişmek için tıklayın. Tüm bu değerleri bir tablodaki sabit değerler olarak ayrı sözleşme sınıfı oluşturabilirsiniz. Daha sonra, bu sınıfı diğer geliştiricilere sunabilirsiniz. Daha fazla hakkında daha fazla bilgi için İçerik URI'leri tasarlama bölümü. Amaçlar hakkında daha fazla bilgi için şuraya bakın: Amaçlar ve veri erişimi bölümü.
  4. Örnek veri veya uygulama gibi diğer isteğe bağlı parçaları ekleyin Şu veriler arasında veri senkronize edebilen: AbstractThreadedSyncAdapter sağlayıcı ve bulut tabanlı verilerdir.

Veri depolamayı tasarlayın

İçerik sağlayıcı, verilerin yapılandırılmış bir biçimde kaydedilmesi için kullanılan arayüzdür. Oluşturmadan önce arayüzde, verilerin nasıl depolanacağına karar verir. Verileri, Google Etiket Yöneticisi'ni kullanarak ve ardından arayüzü, verileri gerektiği gibi okuyup yazacak şekilde tasarlar.

Android'de kullanılabilen veri depolama teknolojilerinden bazıları şunlardır:

  • Yapılandırılmış verilerle çalışıyorsanız Google Analytics 4'teki gibi ilişkisel olmayan bir anahtar/değer veri deposu LevelDB. Çalışıyorsanız yapılandırılmamış verilerle (ör. ses, resim veya video medyası) kullanabilirsiniz. verileri dosya olarak kaydeder. Çeşitli depolama türlerini bir arada kullanabilir ve kullanabilirsiniz. tek bir içerik sağlayıcı kullanmayı deneyebilirsiniz.
  • Android sistemi, oda kalıcılık kitaplığıyla etkileşimde bulunabilir. Android'in kendi sağlayıcılarının kullandığı SQLite veritabanı API'sine erişim sağlar depolamak için de kullanabilirsiniz. Bu komutu kullanarak veritabanı oluşturmak için alt sınıfını örneklendirir, RoomDatabase, aşağıda açıklandığı gibi Odayı kullanarak verileri yerel bir veritabanına kaydedin.

    Deponuzu uygulamak için veritabanı kullanmanız gerekmez. Sağlayıcı harici olarak, ilişkisel bir veritabanına benzer şekilde bir tablo grubu olarak görünür ancak bu, sağlayıcının dahili uygulaması için bir gereklilik değildir.

  • Android'de dosya verilerini depolamak için çeşitli dosya odaklı API'ler bulunur. Dosya depolama alanı hakkında daha fazla bilgi edinmek için Veri ve dosya depolamaya genel bakış. Eğer müzik veya video gibi medyayla ilgili veriler sunan bir sağlayıcı tasarlarken, tablo verilerini ve dosyaları birleştiren bir sağlayıcıya sahip olmanız gerekir.
  • Nadir durumlarda, birden fazla içerik sağlayıcıdan yararlanmak için tek bir uygulamada kullanılabilir. Örneğin, widget'la veri paylaşmak için ve diğer kullanıcılarla paylaşmak için farklı bir veri kümesi sunmanız, izin verir.
  • Ağ tabanlı verilerle çalışmak için java.net ve android.net. Ağ tabanlı verileri yerel verilerle senkronize edebilirsiniz daha sonra verileri tablo veya dosyalar halinde sunabilirsiniz.

Not: Deponuzda olduğu için depoyu yeni bir sürümle işaretlemeniz sayı. Ayrıca, uygulamanızın sürüm numarasını da yeni içerik sağlayıcıyı uygular. Bu değişiklik, sistemin bir uygulamayı yeniden yüklemeyi denediğinde sistemin çökmesine neden uygulamama e-posta göndeririz.

Veri tasarımıyla ilgili dikkat edilmesi gereken noktalar

Aşağıda sağlayıcınızın veri yapısını tasarlamaya yönelik bazı ipuçları verilmiştir:

  • Tablo verilerinde her zaman "birincil anahtar" olmalıdır her bir imza için kullanabilirsiniz. Satırı ilgili satırlarını ("yabancı anahtar" olarak kullanarak) seçin. Her ne kadar BaseColumns._ID kullanmak en iyisidir. çünkü sağlayıcı sorgusunun sonuçlarını ListView, alınan sütunlardan birinin adının olmasını gerektiriyor _ID.
  • Bit eşlem resimleri veya diğer çok büyük dosya odaklı verileri sağlamak isterseniz, depolayıp doğrudan bir dosyada saklamak yerine dolaylı olarak sağlamak tablosunu oluşturalım. Bunu yaparsanız sağlayıcınızın kullanıcılarına bir ContentResolver dosya yöntemini kullanarak verilere erişebilirsiniz.
  • Boyut olarak değişiklik gösteren veya yapılabiliyor. Örneğin, her bir anahtar kelime için bir BLOB sütunu protokol arabelleği veya JSON yapısı.

    BLOB'u, şemadan bağımsız bir tablo uygulamak için de kullanabilirsiniz. İçinde bir birincil anahtar sütunu, MIME türü sütun ve bir ya da daha fazla daha genel sütunları BLOB olarak değiştirin. BLOB sütunlarındaki verilerin anlamı MIME türü sütunundaki değere göre. Bu, farklı satır türlerini şurada depolamanıza olanak tanır: aynı tablodur. Kişi Sağlayıcı'nın "verileri" masa ContactsContract.Data, şemadan bağımsız bir örnektir tablosunu oluşturalım.

İçerik URI'lerini tasarlama

İçerik URI'si, bir sağlayıcıdaki verileri tanımlayan bir URI'dir. İçerik URI'leri şunları içerir: tüm sağlayıcının (yetkilendirmesi) sembolik adı bir tabloyu veya dosyayı işaret eden ad (yol). İsteğe bağlı kimlik bölümü, tek bir satıra ekleyebilirsiniz. Şunun her veri erişim yöntemi: ContentProvider, bağımsız değişken olarak bir içerik URI'sine sahip. Bu şekilde şunları yapabilirsiniz: erişilecek tabloyu, satırı veya dosyayı belirleyin.

İçerik URI'leri hakkında bilgi için bkz. İçerik sağlayıcıyla ilgili temel bilgiler.

Bir otorite tasarlayın

Bir sağlayıcının genellikle Android dahili adı olarak işlev gören tek bir yetkilisi vardır. Alıcı: diğer sağlayıcılarla çakışmaları önler, internet alan adı sahipliğini kullan (ters sırada) belirlemektir. Bu öneri Android için de geçerli olduğu için bir uzantı olarak tanımlarsanız, sağlayıcı yetkilinizi paketinin verilerini içerir.

Örneğin, Android paketinizin adı com.example.<appname>, sağlayıcınıza yetkili com.example.<appname>.provider.

Yol yapısı tasarlama

Geliştiriciler genellikle yetkiliden içerik URI'leri oluşturur. Bunun için kullanabilirsiniz. Örneğin, iki tablonuz varsa: table1 ve tablo2'yi kullanarak aşağıdaki örnekteki yetkiliyle birleştirebilirsiniz: içerik URI'leri com.example.<appname>.provider/table1 ve com.example.<appname>.provider/table2. Yollar tek bir segmentle sınırlıdır ve yolun her düzeyi için bir tablo olması gerekmez.

İçerik URI'si kimliklerini işleme

Genel olarak, sağlayıcılar içerik URI'sini kabul ederek tablodaki tek bir satıra erişim sunar URI'nın sonundaki satır için bir kimlik değeriyle birlikte girin. Ayrıca kurala göre, sağlayıcılar Kimlik değerini, tablonun _ID sütununa girin ve istenen erişimi satır ekleyin.

Bu kural, sağlayıcıya erişen uygulamalar için ortak bir tasarım kalıbını basitleştirir. Uygulama sağlayıcıya karşı bir sorgu yapar ve sonuç olarak elde edilen Cursor değerini görüntüler CursorAdapter kullanarak ListView içinde. CursorAdapter tanımı için _ID olacak Cursor

Daha sonra, kullanıcı arayüzünde görüntülenen satırlardan birini seçerek dışı verilerdir. Uygulama, ilgili satırı Cursor sütunundan alır ve ListView, bu satır için _ID değerini alır ve şunu ekler: içerik URI'sini bulup erişim isteğini sağlayıcıya gönderir. Ardından sağlayıcı kullanıcının seçtiği satıra göre sorgu veya değişiklik yapabilirsiniz.

İçerik URI'si kalıpları

Sağlayıcı API'si, gelen içerik URI'si için hangi işlemi gerçekleştireceğinizi seçmenize yardımcı olmak üzere içerik URI'si kalıplarınıUriMatcher tamsayı değerleri. Bir switch ifadesinde tam sayı değerlerini kullanabilirsiniz: belirli bir kalıpla eşleşen içerik URI'si veya URI'lar için istenen işlemi seçer.

İçerik URI'si kalıbı, joker karakterler kullanarak içerik URI'lerini eşleştirir:

  • *, herhangi bir uzunluktaki geçerli herhangi bir karakterden oluşan bir dizeyle eşleşir.
  • #, herhangi bir uzunluktaki sayısal karakterlerden oluşan bir dizeyle eşleşir.

İçerik URI işlemesini tasarlama ve kodlamayla ilgili örnek olarak Aşağıdaki içerik URI'lerini tanıyan yetkili com.example.app.provider bir örnek:

  • content://com.example.app.provider/table1: table1 adlı bir tablo.
  • content://com.example.app.provider/table2/dataset1: adlı tablo dataset1.
  • content://com.example.app.provider/table2/dataset2: adlı tablo dataset2.
  • content://com.example.app.provider/table3: table3 adlı bir tablo.

Sağlayıcı, eklenmiş bir satır kimliği varsa bu içerik URI'larını da tanır. Örneğin,content://com.example.app.provider/table3/1 table3 içinde 1.

Aşağıdaki içerik URI'si kalıpları mümkündür:

content://com.example.app.provider/*
. Sağlayıcıdaki herhangi bir içerik URI'siyle eşleşir.
content://com.example.app.provider/table2/*
. dataset1 tabloları için bir içerik URI'siyle eşleşir ve dataset2 ile eşleşmez ancak table1 veya table3.
content://com.example.app.provider/table3/#
. Bir içerik URI'si ile eşleşir table3 değerindeki tek satırlar için; örneğin, tarafından tanımlanan satır için content://com.example.app.provider/table3/6 6.

Aşağıdaki kod snippet'i, UriMatcher içindeki yöntemlerin nasıl çalıştığını gösterir. Bu kod, bir tablonun tamamı için URI'ları, bir içerik URI kalıbı kullanılarak tek satır Tablolar için content://<authority>/<path> ve Tek satırlar için content://<authority>/<path>/<id>.

addURI() yöntemi otoriteyi ve tam sayı değerine giden yolu gösterir. match() yöntemi, bir URI için tam sayı değerini döndürür. switch ifadesi Tüm tabloyu sorgulama ile tek bir kayıt için sorgulama arasında seçim yapar.

Kotlin

private val sUriMatcher = UriMatcher(UriMatcher.NO_MATCH).apply {
    /*
     * The calls to addURI() go here for all the content URI patterns that the provider
     * recognizes. For this snippet, only the calls for table 3 are shown.
     */

    /*
     * Sets the integer value for multiple rows in table 3 to 1. Notice that no wildcard is used
     * in the path.
     */
    addURI("com.example.app.provider", "table3", 1)

    /*
     * Sets the code for a single row to 2. In this case, the # wildcard is
     * used. content://com.example.app.provider/table3/3 matches, but
     * content://com.example.app.provider/table3 doesn't.
     */
    addURI("com.example.app.provider", "table3/#", 2)
}
...
class ExampleProvider : ContentProvider() {
    ...
    // Implements ContentProvider.query()
    override fun query(
            uri: Uri?,
            projection: Array<out String>?,
            selection: String?,
            selectionArgs: Array<out String>?,
            sortOrder: String?
    ): Cursor? {
        var localSortOrder: String = sortOrder ?: ""
        var localSelection: String = selection ?: ""
        when (sUriMatcher.match(uri)) {
            1 -> { // If the incoming URI was for all of table3
                if (localSortOrder.isEmpty()) {
                    localSortOrder = "_ID ASC"
                }
            }
            2 -> {  // If the incoming URI was for a single row
                /*
                 * Because this URI was for a single row, the _ID value part is
                 * present. Get the last path segment from the URI; this is the _ID value.
                 * Then, append the value to the WHERE clause for the query.
                 */
                localSelection += "_ID ${uri?.lastPathSegment}"
            }
            else -> { // If the URI isn't recognized,
                // do some error handling here
            }
        }

        // Call the code to actually do the query
    }
}

Java

public class ExampleProvider extends ContentProvider {
...
    // Creates a UriMatcher object.
    private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        /*
         * The calls to addURI() go here for all the content URI patterns that the provider
         * recognizes. For this snippet, only the calls for table 3 are shown.
         */

        /*
         * Sets the integer value for multiple rows in table 3 to one. No wildcard is used
         * in the path.
         */
        uriMatcher.addURI("com.example.app.provider", "table3", 1);

        /*
         * Sets the code for a single row to 2. In this case, the # wildcard is
         * used. content://com.example.app.provider/table3/3 matches, but
         * content://com.example.app.provider/table3 doesn't.
         */
        uriMatcher.addURI("com.example.app.provider", "table3/#", 2);
    }
...
    // Implements ContentProvider.query()
    public Cursor query(
        Uri uri,
        String[] projection,
        String selection,
        String[] selectionArgs,
        String sortOrder) {
...
        /*
         * Choose the table to query and a sort order based on the code returned for the incoming
         * URI. Here, too, only the statements for table 3 are shown.
         */
        switch (uriMatcher.match(uri)) {


            // If the incoming URI was for all of table3
            case 1:

                if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC";
                break;

            // If the incoming URI was for a single row
            case 2:

                /*
                 * Because this URI was for a single row, the _ID value part is
                 * present. Get the last path segment from the URI; this is the _ID value.
                 * Then, append the value to the WHERE clause for the query.
                 */
                selection = selection + "_ID = " + uri.getLastPathSegment();
                break;

            default:
            ...
                // If the URI isn't recognized, do some error handling here
        }
        // Call the code to actually do the query
    }

Başka bir sınıf (ContentUris), çalışma için kolaylık yöntemleri sunuyor içerik URI'lerinin id bölümü ile. Uri ve Uri.Builder, mevcut verileri ayrıştırmak için kolaylık yöntemleri içeriyor Uri nesne ve yeni nesneler oluşturuluyor.

ContentProvider sınıfını uygulama

Erişimi ContentProvider örneği yönetiyor istekleri ele alarak yapılandırılmış bir veri kümesine dönüştürmenize yardımcı olur. Tüm formlar en sonunda ContentResolver işlemini çağırır ve ardından bir somut ContentProvider yöntemini kullanarak erişebilirsiniz.

Gerekli yöntemler

ContentProvider soyut sınıfı alt sınıfınızın bir parçası olarak uygulayacaksınız. Aşağıdakiler hariç tüm bu yöntemler onCreate(), bir istemci uygulaması tarafından çağrılıyor bir hata alırsınız.

query()
. Sağlayıcınızdan veri alın. Aşağıdakileri yapmak için tabloyu seçmek üzere bağımsız değişkenleri kullanın: döndürülecek satırları ile sütunları ve sonucun sıralama düzenini belirtir. Verileri Cursor nesnesi olarak döndürün.
insert()
. Sağlayıcınıza yeni bir satır ekleyin. Şunu seçmek için bağımsız değişkenleri kullanın: hedef tablo oluşturmak ve kullanılacak sütun değerlerini almak için kullanılır. Şu öğe için içerik URI'si döndürün: yeni eklenen satır.
update()
. Sağlayıcınızdaki mevcut satırları güncelleyin. Tabloyu ve satırları seçmek için bağımsız değişkenleri kullanın değerini girin. Güncellenen satır sayısını döndürür.
delete()
. Sağlayıcınızdan satır silin. Tabloyu seçmek için bağımsız değişkenleri, kullanılacak satırları ve sil. Silinen satır sayısını döndürür.
getType()
. İçerik URI'sine karşılık gelen MIME türünü döndürür. Bu yöntem aşağıda açıklandığı gibi bölümündeki İçerik sağlayıcı MIME türlerini uygulama bölümündeki ayrıntıları inceleyin.
onCreate()
. Sağlayıcınızı başlatın. Android sistemi bu yöntemi hemen sonra çağırır sağlayıcınızı oluşturur. Sağlayıcınız şu tarihe kadar oluşturulmaz: ContentResolver nesnesi erişmeye çalışıyor.

Bu yöntemler, aynı ada sahip olan ContentResolver yöntem.

Bu yöntemleri uygularken aşağıdakileri göz önünde bulundurmanız gerekir:

  • onCreate() hariç tüm bu yöntemler aynı anda birden çok iş parçacığı tarafından çağrılabilir; bu nedenle, ileti dizisi açısından güvenli olmaları gerekir. Öğrenmek için daha fazla bilgi edinmek için Süreçlere ve ileti dizilerine genel bakış.
  • onCreate() öğesinde uzun işlemler yapmaktan kaçının. Başlatma görevlerini gerçekten ihtiyaç duyulana kadar erteleyin. onCreate() yöntemini uygulama ile ilgili bölüm bu konuyu daha ayrıntılı olarak ele alacağız.
  • Bu yöntemleri uygulamanız gerekse de, kodunuzun başka bir işlem yapması gerekmez. beklenen veri türünü döndürür. Örneğin, belirli bir uygulama için bazı tablolara veri eklenmesini engelleyebilirsiniz. insert() ve dönüş 0

query() yöntemini uygulama

İlgili içeriği oluşturmak için kullanılan ContentProvider.query() yöntemi, Cursor nesnesi döndürmelidir veya başarısız olursa Exception hatası verir. Verileriniz olarak SQLite veritabanı kullanıyorsanız depolama alanı dışında kalan Cursor SQLiteDatabase sınıfının query() yöntemi.

Sorgu hiçbir satırla eşleşmezse Cursor döndürün getCount() yöntemi 0 döndüren örnek. null değerini yalnızca sorgu işlemi sırasında dahili bir hata oluştuysa döndürün.

Veri depolamanız olarak SQLite veritabanı kullanmıyorsanız somut alt sınıflardan birini kullanın / Cursor. Örneğin, MatrixCursor sınıfı her satırın Object örnekten oluşan bir dizi olduğu bir imleç uygular. Bu dersle yeni bir satır eklemek için addRow() öğesini kullanın.

Android sistemi, Exception ile iletişim kurabilmelidir çok daha fazlasıdır. Android, bu işlemi aşağıdaki faydalı istisnalar için yapabilir: bazı hatalar mevcut:

Insert() yöntemini uygulama

insert() yöntemi, uygun tabloya ContentValues içindeki değerler kullanılarak yeni satır ekleyebilirsiniz. bağımsız değişkeninin önüne geçer. ContentValues bağımsız değişkeninde sütun adı yoksa sağlayıcı kodunuzda veya veritabanınızda bunun için varsayılan bir değer sağlamak isteyebilirsiniz. şema.

Bu yöntem, yeni satırın içerik URI'sini döndürür. Bunu oluşturmak için satırın birincil anahtarını (genellikle _ID değerini) tablonun içerik URI'sine ekleyin. withAppendedId().

delete() yöntemini uygulama

delete() yöntemi veri depolama alanınızdaki satırları silmesi gerekmez. Senkronizasyon adaptörü kullanıyorsanız sağlayıcınıza danışarak, silinmiş satırları işaretleyebilirsiniz "sil" ile işaretini kullanın. Senkronizasyon bağdaştırıcısı, sağlayıcıdan silmeden önce silinmiş satırları kontrol edip sunucudan kaldırın.

Update() yöntemini uygulama

update() yöntemi,ContentValues insert() ve tarafından kullanılan aynı selection ve selectionArgs bağımsız değişkenleri delete() ve ContentProvider.query(). Bu sayede kodu bu yöntemler arasında yeniden kullanabilirsiniz.

onCreate() yöntemini uygulama

Android sistemi onCreate() çağırıyor sağlayıcıyı başlatır. Yalnızca hızlı çalışan başlatma yap ve veri tabanı oluşturma ile veri yüklemeyi, sağlayıcı gerçekten satın alınana kadar Veriler için bir istek alır. Sauce and Spoon’un tablet projesinde onCreate(), için bir fırsattır. Bu da sağlayıcının verdiği yanıtın diğerlerine izin verir.

Aşağıdaki iki snippet, önceki videoda gördüğümüz ContentProvider.onCreate() ve Room.databaseBuilder(). İlk snippet, ContentProvider.onCreate() burada: veritabanı nesnesi oluşturulur ve veri erişimi nesnelerinin tutamaçları oluşturulduğunda:

Kotlin

// Defines the database name
private const val DBNAME = "mydb"
...
class ExampleProvider : ContentProvider() {

    // Defines a handle to the Room database
    private lateinit var appDatabase: AppDatabase

    // Defines a Data Access Object to perform the database operations
    private var userDao: UserDao? = null

    override fun onCreate(): Boolean {

        // Creates a new database object
        appDatabase = Room.databaseBuilder(context, AppDatabase::class.java, DBNAME).build()

        // Gets a Data Access Object to perform the database operations
        userDao = appDatabase.userDao

        return true
    }
    ...
    // Implements the provider's insert method
    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        // Insert code here to determine which DAO to use when inserting data, handle error conditions, etc.
    }
}

Java

public class ExampleProvider extends ContentProvider

    // Defines a handle to the Room database
    private AppDatabase appDatabase;

    // Defines a Data Access Object to perform the database operations
    private UserDao userDao;

    // Defines the database name
    private static final String DBNAME = "mydb";

    public boolean onCreate() {

        // Creates a new database object
        appDatabase = Room.databaseBuilder(getContext(), AppDatabase.class, DBNAME).build();

        // Gets a Data Access Object to perform the database operations
        userDao = appDatabase.getUserDao();

        return true;
    }
    ...
    // Implements the provider's insert method
    public Cursor insert(Uri uri, ContentValues values) {
        // Insert code here to determine which DAO to use when inserting data, handle error conditions, etc.
    }
}

ContentProvider MIME türlerini uygulama

ContentProvider sınıfının, MIME türlerini döndürmek için iki yöntemi vardır:

getType()
. Her sağlayıcı için uyguladığınız zorunlu yöntemlerden biridir.
getStreamTypes()
. Sağlayıcınız dosya sunuyorsa uygulamanız beklenen bir yöntem.

Tablolar için MIME türleri

getType() yöntemi, İçeriğin döndürdüğü veri türünü tanımlayan MIME biçiminde String URI bağımsız değişkeni. Uri bağımsız değişkeni, belirli bir URI yerine bir kalıp olabilir. Bu durumda desen.

Metin, HTML veya JPEG gibi yaygın veri türleri için getType(), standardı döndürür MIME türüdür. Bu standart türlerin tam listesi IANA MIME Medya Türleri web sitesi.

Tablo verileri satırına veya satırlarına işaret eden içerik URI'leri için getType() karşılığında iade Android'in tedarikçi firmaya özel MIME biçiminde bir MIME türü:

  • Parçayı yazın: vnd
  • Alt tür bölümü:
    • URI kalıbı tek bir satır içinse: android.cursor.item/
    • URI kalıbı birden fazla satır içinse: android.cursor.dir/
  • Sağlayıcıya özel bölüm: vnd.<name>.<type>

    <name> ve <type> sizin tarafınızdan sağlanır. <name> değeri genel olarak benzersizdir. ve <type> değeri, karşılık gelen URI'ye özgüdür desen. <name> için şirketinizin adı veya uygulamanızın Android paket adının bir kısmıdır. Proje yöneticisi için <type>, URI.

Örneğin, sağlayıcının yetkilisi com.example.app.provider ve table1, table1 içinde birden fazla satırın MIME türü:

vnd.android.cursor.dir/vnd.com.example.provider.table1

Tek bir table1 satırı için MIME türü:

vnd.android.cursor.item/vnd.com.example.provider.table1

Dosyalar için MIME türleri

Sağlayıcınız dosyalar sunuyorsa getStreamTypes() Yöntem, sağlayıcınızın dosyaları için bir String MIME türü dizisi döndürür döndürebilir. Sunduğunuz MIME türlerini MIME türüne göre filtreleyin filtre bağımsız değişkeninin önüne geçerek yalnızca istemcinin işlemek istediği MIME türlerini döndürürsünüz.

Örneğin, fotoğraf resimlerini JPG dosyası olarak sunan bir sağlayıcı, PNG ve GIF biçiminde olması gerekir. Bir uygulama, image/* filtre dizesiyle ContentResolver.getStreamTypes() öğesini çağırırsa "görsel", ContentProvider.getStreamTypes() yöntemi diziyi döndürür:

{ "image/jpeg", "image/png", "image/gif"}

Uygulama yalnızca JPG dosyalarıyla ilgileniyorsa *\/jpeg filtre dizesiyle ContentResolver.getStreamTypes() ve getStreamTypes() şunu iade etti:

{"image/jpeg"}

Sağlayıcınız filtre dizesinde istenen MIME türlerinden herhangi birini sunmuyorsa getStreamTypes(). null değerini döndürür.

Sözleşme sınıfı uygulama

Sözleşme sınıfı,public final URI'lar, sütun adları, MIME türleri ve sağlayıcıyla ilgili diğer meta veriler. Sınıf uygun koşulları karşılayarak sağlayıcı ile diğer uygulamalar arasında bir sözleşme URL'lerin gerçek değerlerinde, sütun adlarının veya vb.

Sözleşme sınıfı, geliştiricilere de yardımcı olur çünkü genellikle sabit değerleri, hafızalarda önemli adlar verir. Bu nedenle, geliştiricilerin sütun adları veya URI'lar için yanlış değerler kullanma olasılığı daha düşüktür. Bu sınıfını değiştirmek için Javadoc dokümanlarını içerebilir. Şu gibi entegre geliştirme ortamları: Android Studio, sözleşme sınıfındaki sabit adları otomatik olarak tamamlar ve sabit değerler.

Geliştiriciler, sözleşme sınıfının sınıf dosyasına uygulamanızdan erişemezler, ancak şunları yapabilirler: sağladığınız bir JAR dosyasından uygulamasına statik olarak derler.

ContactsContract sınıfı ve iç içe yerleştirilmiş sınıfları sözleşmeli sınıflar.

İçerik sağlayıcı izinlerini uygulama

Android sisteminin tüm özellikleriyle ilgili izinler ve erişim şurada ayrıntılı olarak açıklanmıştır: Güvenlik ipuçları. Veri ve dosya depolama alanına genel bakış da , çeşitli depolama türleri için geçerli olan güvenliği ve izinleri açıklar. Özetle önemli noktalar şunlardır:

  • Varsayılan olarak, cihazın dahili depolama alanında depolanan veri dosyaları yalnızca ve sağlayıcıyı kullanabilirsiniz.
  • Oluşturduğunuz SQLiteDatabase veritabanı size özeldir ve sağlayıcıyı kullanabilirsiniz.
  • Harici depolama alanına kaydettiğiniz veri dosyaları varsayılan olarak herkese açıktır ve okunabilir. Şuradaki dosyalara erişimi kısıtlamak için bir içerik sağlayıcı kullanamazsınız: Çünkü diğer uygulamalar, bunları okumak ve yazmak için başka API çağrılarını kullanabilir.
  • Yöntem, cihazınızın dahili ayarlarında dosya veya SQLite veritabanlarının açılmasını ya da oluşturulmasını gerektirir depolama alanı potansiyel olarak tüm diğer uygulamalara hem okuma hem de yazma erişimi verebilir. Şu durumda: sağlayıcınızın deposu olarak dahili bir dosya veya veritabanı kullanın ve bunu "dünya tarafından okunabilir" veya "dünyada-yazılabilir" içinde sağlayıcınız için belirlediğiniz izinleri verilerinizi korumaz. Şuradaki dosyalar ve veritabanları için varsayılan erişim: dahili depolama "gizli"dir; sağlayıcınızın deposu için bunu değiştirmeyin.

Verilerinize erişimi kontrol etmek için içerik sağlayıcı izinlerini kullanmak isterseniz verilerinizi dahili dosyalarda, SQLite veritabanlarında veya bulutta 'a entegre edebilirsiniz. Ayrıca dosyalar ile veritabanlarını uygulamanıza özel tutabilirler.

İzinleri uygulama

Temel veriler temel alınan veriler olsa bile varsayılan olarak tüm uygulamalar sağlayıcınızdan okuma veya sağlayıcınıza yazma imkanı Gizli. Çünkü sağlayıcınız varsayılan olarak ayarlı izinlere sahip değildir. Bunu değiştirmek için özellikleri veya alt öğeyi kullanarak manifest dosyanızda sağlayıcınız için izinleri ayarlayın <provider> öğesinin öğeleri. Belirlenen sağlayıcıdan bir ya da daha fazla sağlayıcı için belirli kayıtlara veya üçüne birden uygulayabilirsiniz.

Sağlayıcınızın izinlerini bir veya daha fazla Manifest dosyanızda <permission> öğeleri. To sağlayıcınıza özel bir izin değilse, android:name özelliği için de kullanılmaktadır. Örneğin, okuma iznini adlandırın. com.example.app.provider.permission.READ_PROVIDER

Aşağıdaki listede önce sağlayıcı için geçerli olan ve daha ayrıntılı hale gelen izinler Daha ayrıntılı izinler, daha geniş kapsamlı izinlere göre önceliklidir.

Okuma-yazma sağlayıcı düzeyinde tek izin
. Sağlayıcının tamamına hem okuma hem de yazma erişimini kontrol eden bir izin, belirtilmiş şunun android:permission özelliğiyle <provider> öğesi.
Okuma ve yazma sağlayıcı düzeyinde ayrı izinler
. Sağlayıcının tamamı için okuma ve yazma izni. Bunları siz belirtirsiniz android:readPermission ve android:writePermission özellikleri <provider> öğesi. Bunlar, android:permission
Yol düzeyinde izin
. Sağlayıcınızdaki içerik URI'si için okuma, yazma veya okuma/yazma izni. Siz <path-permission> alt öğesi <provider> öğesi. Belirttiğiniz her içerik URI'si için bir okuma/yazma izni, okuma izni, yazma izni veya üçü de vardır. Okuma ve yazma izinleri, okuma/yazma iznine göre önceliklidir. Ayrıca, yol düzeyinde bu izin, sağlayıcı düzeyindeki izinlere göre önceliklidir.
Geçici izin
. Bir uygulamaya geçici erişim izni veren bir izin düzeyi, , normalde gerekli olan izinlere sahip değil. Geçici erişim özelliği, bir uygulamanın istekte bulunması gereken izin sayısını azaltır bildireceğiz. Geçici izinleri açtığınızda, yalnızca sağlayıcınızın kalıcı izinleri, tüm cihazlarınıza sürekli olarak erişen izinlerdir. verileriniz.

Örneğin, bir e-posta sağlayıcısı ve uygulaması uyguluyorsanız ve dışarıdaki bir resim görüntüleyici uygulamasının sağlar. Resim görüntüleyiciye izin gerektirmeden gerekli erişimi vermek için fotoğrafların içerik URI'lerine yönelik geçici izinler ayarlayabilirsiniz.

E-posta uygulamanızı Kullanıcı bir fotoğraf görüntülemek istediğinde uygulamanın bu fotoğrafı içeren fotoğraf içerik URI'si ve resim görüntüleyici için izin işaretleri içerir. Resim görüntüleyici fotoğraf getirmesi için e-posta sağlayıcınızdan sorgu göndererek sağlayıcınızın normal okuma iznine sahip olması gerekir.

Geçici izinleri etkinleştirmek için android:grantUriPermissions <provider> öğe veya bir ya da daha fazla öğe ekleyin <grant-uri-permission> <provider> öğesi. Telefonla arama Context.revokeUriPermission() sağlar.

Bu özelliğin değeri, sağlayıcınızın ne kadarının erişilebilir olduğunu belirler. Özellik "true" değerine ayarlanırsa sistem, için gerekli diğer tüm izinleri geçersiz kılarak, sağlayıcınıza veya yol düzeyindeki izinlerinize göre belirlemeniz gerekir.

Bu işaret "false" değerine ayarlanırsa <grant-uri-permission> <provider> öğesi. Her alt öğe, içerik URI'sini veya Geçici erişim izni verilen URI'lar.

Bir uygulamaya geçici erişim yetkisi vermek için amacın şunu içermesi gerekir: FLAG_GRANT_READ_URI_PERMISSION bayrağı, FLAG_GRANT_WRITE_URI_PERMISSION işareti veya her ikisi. Bu setFlags() yöntemiyle ayarlanır.

android:grantUriPermissions özelliği yoksa mevcut olduğu varsayılır. "false".

<provider> öğe

Activity ve Service bileşenlerinde olduğu gibi, ContentProvider alt sınıfı aşağıdaki komut dosyası kullanılarak uygulamasının manifest dosyasında tanımlanır: <provider> öğesi. Android sistemi, öğe:

Yetki (android:authorities)
. Sistemdeki tüm sağlayıcıyı tanımlayan sembolik adlar. Bu özelliği aşağıdaki sayfada daha ayrıntılı olarak açıklanmıştır: İçerik URI'leri tasarlama bölümü.
Sağlayıcı sınıf adı (android:name)
. ContentProvider uygulayan sınıf. Bu sınıf daha ayrıntılı olarak ContentProvider sınıfını uygulama bölümünü inceleyin.
İzinler
. Diğer uygulamaların erişebilmek için sahip olması gereken izinleri belirten özellikler sağlayıcı verileri:

İzinler ve bunlarla ilgili özellikler ve İçerik sağlayıcı izinlerini uygulama bölümünü inceleyin.

Başlangıç ve kontrol özellikleri
. Bu özellikler, Android sisteminin sağlayıcıyı nasıl ve ne zaman başlatacağını, diğer çalışma zamanı ayarları için de geçerlidir:
  • android:enabled: Sistemin sağlayıcıyı başlatmasına izin veren işaretleyici
  • android:exported: diğer uygulamaların bu sağlayıcıyı kullanmasına izin verdiğini işaretle
  • android:initOrder: Bu sağlayıcının başlatılma sırası, aynı süreçteki diğer sağlayıcılara kıyasla
  • android:multiProcess: Sistemin sağlayıcıyı başlatmasına izin veren işaretleyici arayan müşteriyle aynı süreçte
  • android:process: Sağlayıcının çalıştırıldığı işlemin adıdır.
  • android:syncable: Sağlayıcıya ait verilerin toplanacağını belirten işaret bir sunucudaki verilerle senkronize edildi

Bu özellikler, <provider> öğesi.

Bilgilendirici özellikler
. Sağlayıcı için isteğe bağlı bir simge ve etiket:
  • android:icon: Sağlayıcının simgesini içeren çekilebilir bir kaynaktır. Simge, Ayarlar > Uygulamalar > Tümü.
  • android:label: sağlayıcıyı, sağlayıcıyı ve firmayı tanımlayan bilgi etiketi verileri veya her ikisi de olabilir. Bu etiket, uygulama listesindeki uygulamalar listesinde görünür. Ayarlar > Uygulamalar > Tümü.

Bu özellikler, <provider> öğesi.

Not: Android 11 veya sonraki bir sürümü hedefliyorsanız şu makaleye göz atın: paket görünürlüğü belgeleri kullanın.

Amaçlar ve veri erişimi

Uygulamalar, Intent ile dolaylı olarak içerik sağlayıcıya erişebilir. Uygulama, ContentResolver veya ContentProvider. Bunun yerine bir etkinlik başlatan, Bu genellikle sağlayıcının kendi uygulamasının bir parçasıdır. Varış noktası etkinliğinde nelerden bahsedilir? kullanıcı arayüzünde verilerini alıp görüntüleyebilirsiniz.

Amaçtaki işleme bağlı olarak, hedef etkinliği, kullanıcıdan sağlayıcının verilerinde değişiklik yapmasını da isteyebilir. Niyet, "ekstralar"ı da içerebilir hedef etkinliğin gösterdiği veriler görüntülenir. Böylece kullanıcı, verileri değiştirmek için kullanmadan önce bu verileri değiştirme kontrol edebilirsiniz.

Veri bütünlüğüne yardımcı olmak için intent erişimini kullanabilirsiniz. Sağlayıcınız aşağıdakilere göre değişir: titizlikle tanımlanmış iş mantığına göre veri eklenmesini, güncellenmesini ve silinmesini sağlamakla ilgilidir. Eğer Bu durumda, diğer uygulamaların verilerinizi doğrudan değiştirmesine izin vermek, geçersiz veri.

Geliştiricilerin amaç erişimini kullanmasını istiyorsanız bunu ayrıntılı bir şekilde belgelediğinizden emin olun. Uygulamanızın kullanıcı arayüzünü kullanarak intent erişiminin neden kodu kullanarak verileri değiştirebilir.

Sağlayıcınızın verilerini değiştirmek isteyen gelen bir niyetin ele alınması, eleştirel düşünme yetinizi kullanmanız gerekiyor. Amaçları kullanma hakkında daha fazla bilgiyi şuradan edinebilirsiniz: Niyetler ve Amaç Filtreleri.

Daha fazla ilgili bilgi için Takvim sağlayıcısına genel bakış.