İçerik sağlayıcı, merkezi bir veri havuzuna erişimi yönetir. Sağlayıcı, verilerle çalışmak için genellikle kendi kullanıcı arayüzünü sağlayan Android uygulamasının bir parçasıdır. Bununla birlikte, içerik sağlayıcılar öncelikli olarak sağlayıcıya bir sağlayıcı istemci nesnesi kullanarak erişen diğer uygulamalar tarafından kullanılır. Sağlayıcılar ve sağlayıcı istemcileri, işlemler arası iletişimi ve güvenli veri erişimini de işleyen tutarlı ve standart bir veri arayüzü sunar.
İçerik sağlayıcılarla genellikle şu iki senaryodan birinde çalışırsınız: Başka bir uygulamada mevcut içerik sağlayıcıya erişmek için kod uygulama veya uygulamanızda diğer uygulamalarla veri paylaşmak için yeni içerik sağlayıcı oluşturma.
Bu sayfa, mevcut içerik sağlayıcılarla çalışmaya ilişkin temel bilgileri içerir. İçerik sağlayıcıları kendi uygulamalarınızda kullanma hakkında bilgi edinmek için İçerik sağlayıcı oluşturma konusuna bakın.
Bu bölümde aşağıdaki konular açıklanmaktadır:
- İçerik sağlayıcıların işleyiş şekli.
- Bir içerik sağlayıcıdan veri almak için kullandığınız API.
- İçerik sağlayıcıda veri eklemek, güncellemek veya silmek için kullandığınız API.
- Sağlayıcılarla çalışmayı kolaylaştıran diğer API özellikleri.
Genel bakış
İçerik sağlayıcı, verileri ilişkisel veritabanında bulunan tablolara benzeyen en az bir tablo olarak harici uygulamalara sunar. Satır, sağlayıcının topladığı bir veri türünün örneğini temsil eder; satırdaki her sütun ise bir örnek için toplanan bağımsız veri parçasını temsil eder.
İçerik sağlayıcı, çeşitli API'ler ve bileşenler için uygulamanızdaki veri depolama katmanına erişimi koordine eder. Şekil 1'de gösterildiği gibi, bunlar aşağıdakileri içerir:
- Uygulama verilerinize erişimi diğer uygulamalarla paylaşma
- Widget'a veri gönderme
SearchRecentSuggestionsProvider
ile arama çerçevesi üzerinden uygulamanız için özel arama önerileri döndürmeAbstractThreadedSyncAdapter
kullanarak uygulama verilerini sunucunuzla senkronize etmeCursorLoader
kullanarak kullanıcı arayüzünüze veri yükleme

Şekil 1. İçerik sağlayıcı ile diğer bileşenler arasındaki ilişki.
Bir sağlayıcıya erişme
Bir içerik sağlayıcıdaki verilere erişmek istediğinizde, sağlayıcıyla istemci olarak iletişim kurmak için uygulamanızın Context
öğesindeki ContentResolver
nesnesini kullanırsınız. ContentResolver
nesnesi, ContentProvider
uygulayan bir sınıfın bir örneği olan sağlayıcı nesnesiyle iletişim kurar.
Sağlayıcı nesnesi istemcilerden veri istekleri alır, istenen işlemi gerçekleştirir ve sonuçları döndürür. Bu nesne, sağlayıcı nesnesinde aynı şekilde adlandırılmış yöntemleri çağıran yöntemlere sahiptir. Bu yöntemler, ContentProvider
öğesinin somut alt sınıflarından birinin örneğidir. ContentResolver
yöntemleri, kalıcı depolama alanının temel "CRUD" (oluşturma, alma, güncelleme ve silme) işlevlerini sağlar.
Kullanıcı arayüzünüzden bir ContentProvider
öğesine erişmek için yaygın olarak kullanılan bir kalıp, arka planda eşzamansız sorgu çalıştırmak için CursorLoader
kullanır. Kullanıcı arayüzünüzdeki Activity
veya Fragment
, sorguya bir CursorLoader
çağırır ve bu da ContentResolver
ile ContentProvider
kodunu alır.
Bu, sorgu çalışırken kullanıcı arayüzünün kullanılabilir olmaya devam etmesini sağlar. Bu kalıp, Şekil 2'de gösterildiği gibi temel depolama mekanizmasının yanı sıra bir dizi farklı nesnenin etkileşimini içerir.

2. Şekil. ContentProvider
, diğer sınıflar ve depolama alanı arasındaki etkileşim.
Not: Bir sağlayıcıya erişmek için uygulamanızın genellikle manifest dosyasında belirli izinleri istemesi gerekir. Bu geliştirme kalıbı, İçerik sağlayıcı izinleri bölümünde daha ayrıntılı olarak açıklanmıştır.
Android platformundaki yerleşik sağlayıcılardan biri, kullanıcının saklamak istediği standart olmayan kelimeleri depolayan Kullanıcı Sözlüğü Sağlayıcısıdır. Tablo 1'de, bu sağlayıcının tablosundaki verilerin nasıl görünebileceğine dair bir fikir edinebilirsiniz:
Tablo 1: Örnek kullanıcı sözlüğü tablosu.
kelime | uygulama kimliği | sıklığı | yerel ayar | _Kimlik |
---|---|---|---|---|
mapreduce |
kullanici1 | 100 | en_US | 1 |
precompiler |
kullanıcı14 | 200 | tr_tr | 2 |
applet |
kullanici2 | 225 | tr_TR | 3 |
const |
kullanici1 | 255 | pt_BR | 4 |
int |
kullanıcı5 | 100 | tr_TR | 5 |
Tablo 1'deki her satır, standart bir sözlükte bulunmayan bir kelimenin bir örneğini temsil eder. Her sütun, söz konusu kelimeyle ilgili ilk karşılaşılan yerel ayar gibi bir veri parçasını temsil eder. Sütun başlıkları, sağlayıcıda depolanan sütun adlarıdır. Dolayısıyla, örneğin bir satırın yerel ayarına başvuruda bulunmak için locale
sütununa başvuruda bulunursunuz. Bu sağlayıcı için _ID
sütunu, sağlayıcının otomatik olarak tuttuğu bir birincil anahtar sütunu görevi görür.
Kullanıcı Sözlüğü Sağlayıcısı'ndan kelimelerin ve yerel ayarlarının listesini almak için ContentResolver.query()
yöntemini çağırırsınız.
query()
yöntemi, Kullanıcı Sözlüğü Sağlayıcısı tarafından tanımlanan ContentProvider.query()
yöntemini çağırır. Aşağıdaki kod satırlarında bir ContentResolver.query()
çağrısı gösterilmektedir:
Kotlin
// Queries the UserDictionary and returns results cursor = contentResolver.query( UserDictionary.Words.CONTENT_URI, // The content URI of the words table projection, // The columns to return for each row selectionClause, // Selection criteria selectionArgs.toTypedArray(), // Selection criteria sortOrder // The sort order for the returned rows )
Java
// Queries the UserDictionary and returns results cursor = getContentResolver().query( UserDictionary.Words.CONTENT_URI, // The content URI of the words table projection, // The columns to return for each row selectionClause, // Selection criteria selectionArgs, // Selection criteria sortOrder); // The sort order for the returned rows
Tablo 2'de, query(Uri,projection,selection,selectionArgs,sortOrder)
bağımsız değişkenlerinin bir SQL SELECT ifadesiyle nasıl eşleştiği gösterilmiştir:
Tablo 2: SQL sorgusuna kıyasla query()
.
query() bağımsız değişkeni |
Anahtar kelime/parametre SELECT | Notlar |
---|---|---|
Uri |
FROM table_name |
Uri , table_name adlı sağlayıcıdaki tabloyla eşlenir. |
projection |
col,col,col,... |
projection , alınan her satır için dahil edilen bir sütun dizisidir.
|
selection |
WHERE col = value |
selection , satır seçme ölçütlerini belirtir. |
selectionArgs |
Tam olarak eşdeğeri yoktur. Seçim bağımsız değişkenleri, seçim ifadesinde ? yer tutucularının yerini alır.
|
|
sortOrder |
ORDER BY col,col,... |
sortOrder , satırların döndürülen Cursor öğesinde göründüğü sırayı belirtir.
|
İçerik URI'leri
İçerik URI'si, sağlayıcıdaki verileri tanımlayan bir URI'dir. İçerik URI'leri, sağlayıcının tamamının sembolik adını (yetkililiğini) ve bir tabloya işaret eden bir yolu içerir. Sağlayıcıdaki bir tabloya erişmek için istemci yöntemini çağırdığınızda tablonun içerik URI'si bağımsız değişkenlerden biridir.
Önceki kod satırlarında CONTENT_URI
sabiti, Kullanıcı Sözlük Sağlayıcısı'nın Words
tablosunun içerik URI'sini içerir. ContentResolver
nesnesi, URI'nin yetkisini ayrıştırır ve yetkiliyi bilinen sağlayıcıların sistem tablosuyla karşılaştırarak sağlayıcıyı çözmek için kullanır. Daha sonra ContentResolver
, sorgu bağımsız değişkenlerini doğru sağlayıcıya gönderebilir.
ContentProvider
, erişilecek tabloyu seçmek için içerik URI'sinin yol kısmını kullanır. Sağlayıcıların genellikle gösterdiği her tablo için bir yolu vardır.
Önceki kod satırlarında, Words
tablosunun tam URI'si şu şekildedir:
content://user_dictionary/words
content://
dizesi, her zaman mevcut olan ve bunu içerik URI'si olarak tanımlayan şemadır.user_dictionary
dizesi, sağlayıcının yetkisidir.words
dizesi, tablonun yoludur.
Birçok sağlayıcı, URI'nın sonuna kimlik değeri ekleyerek bir tablodaki tek bir satıra erişmenize izin verir. Örneğin, Kullanıcı Sözlüğü Sağlayıcısı'ndan _ID
değeri 4
olan bir satırı almak için şu içerik URI'sini kullanabilirsiniz:
Kotlin
val singleUri: Uri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI, 4)
Java
Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
Kimlik değerlerini genellikle, bir satır kümesi aldığınızda ve daha sonra bunlardan birini güncellemek veya silmek istediğinizde kullanırsınız.
Not: Uri
ve Uri.Builder
sınıfları, dizelerden iyi biçimlendirilmiş URI nesneleri oluşturmaya yönelik kolaylık yöntemleri içerir. ContentUris
sınıfı, kimlik değerlerini URI'ye eklemek için kolaylık yöntemleri içerir. Önceki snippet, Kullanıcı Sözlüğü Sağlayıcısı içerik URI'sine kimlik eklemek için withAppendedId()
değerini kullanır.
Sağlayıcıdan veri alma
Bu bölümde, örnek olarak Kullanıcı Sözlüğü Sağlayıcısı kullanılarak bir sağlayıcıdan nasıl veri alınacağı açıklanmaktadır.
Anlaşılır olması için bu bölümdeki kod snippet'leri, kullanıcı arayüzü iş parçacığında ContentResolver.query()
komutunu çağırır. Ancak gerçek kodda, sorguları ayrı bir iş parçacığında eşzamansız olarak gerçekleştirin.
Yükleyiciler kılavuzunda daha ayrıntılı olarak açıklanan CursorLoader
sınıfını kullanabilirsiniz. Ayrıca, kod satırları yalnızca snippet'lerden oluşur. Bunlar uygulamanın tamamı gösterilmez.
Bir sağlayıcıdan veri almak için aşağıdaki temel adımları uygulayın:
- Sağlayıcı için okuma erişimi izni isteyin.
- Sağlayıcıya sorgu gönderen kodu tanımlayın.
Okuma erişimi izni iste
Bir sağlayıcıdan veri almak için uygulamanızın ilgili sağlayıcının okuma erişimi iznine ihtiyacı vardır. Çalışma zamanında bu izni isteyemezsiniz. Bunun yerine, <uses-permission>
öğesini ve sağlayıcı tarafından tanımlanan tam izin adını kullanarak manifest dosyanızda bu izne ihtiyacınız olduğunu belirtmeniz gerekir.
Bu öğeyi manifest dosyanızda belirttiğinizde uygulamanız için bu izni istersiniz. Kullanıcılar uygulamanızı yüklediğinde dolaylı olarak bu isteği yerine getirirler.
Kullandığınız sağlayıcının okuma erişimi izninin tam adını ve sağlayıcı tarafından kullanılan diğer erişim izinlerinin adlarını öğrenmek için sağlayıcının belgelerine bakın.
İzinlerin sağlayıcılara erişimdeki rolü, İçerik sağlayıcı izinleri bölümünde daha ayrıntılı olarak açıklanmaktadır.
Kullanıcı Sözlüğü Sağlayıcısı, android.permission.READ_USER_DICTIONARY
iznini manifest dosyasında tanımladığından, sağlayıcıdan okuma yapmak isteyen bir uygulama bu izni istemelidir.
Sorguyu oluşturma
Sağlayıcıdan veri almanın sonraki adımı sorgu oluşturmaktır. Aşağıdaki snippet, Kullanıcı Sözlüğü Sağlayıcısı'na erişmek için bazı değişkenleri tanımlar:
Kotlin
// A "projection" defines the columns that are returned for each row private val mProjection: Array<String> = arrayOf( UserDictionary.Words._ID, // Contract class constant for the _ID column name UserDictionary.Words.WORD, // Contract class constant for the word column name UserDictionary.Words.LOCALE // Contract class constant for the locale column name ) // Defines a string to contain the selection clause private var selectionClause: String? = null // Declares an array to contain selection arguments private lateinit var selectionArgs: Array<String>
Java
// A "projection" defines the columns that are returned for each row String[] mProjection = { UserDictionary.Words._ID, // Contract class constant for the _ID column name UserDictionary.Words.WORD, // Contract class constant for the word column name UserDictionary.Words.LOCALE // Contract class constant for the locale column name }; // Defines a string to contain the selection clause String selectionClause = null; // Initializes an array to contain selection arguments String[] selectionArgs = {""};
Bir sonraki snippet, örnek olarak Kullanıcı Sözlüğü Sağlayıcısı ile ContentResolver.query()
işlevinin nasıl kullanılacağını gösterir. Sağlayıcı istemci sorgusu, SQL sorgusuna benzerdir. Döndürülecek bir sütun kümesi, seçim ölçütleri ve sıralama düzeni içerir.
Sorgunun döndürdüğü sütun kümesine projeksiyon denir ve değişken mProjection
'dir.
Alınacak satırları belirten ifade, bir seçim ifadesi ve seçim bağımsız değişkenlerine bölünür. Seçim ifadesi mantıksal ve boole ifadelerinin, sütun adlarının ve değerlerinin bir kombinasyonudur. Değişken: mSelectionClause
. Bir değer yerine değiştirilebilir ?
parametresini belirtirseniz sorgu yöntemi, değeri seçim bağımsız değişkenleri dizisinden (mSelectionArgs
değişkeni) alır.
Sonraki snippet'te kullanıcı bir kelime girmezse seçim ifadesi null
olarak ayarlanır ve sorgu, sağlayıcıdaki tüm kelimeleri döndürür. Kullanıcı bir kelime girerse seçim ifadesi UserDictionary.Words.WORD + " = ?"
olarak ayarlanır ve seçim bağımsız değişkenleri dizisinin ilk öğesi, kullanıcının girdiği kelimeye ayarlanır.
Kotlin
/* * This declares a String array to contain the selection arguments. */ private lateinit var selectionArgs: Array<String> // Gets a word from the UI searchString = searchWord.text.toString() // Insert code here to check for invalid or malicious input // If the word is the empty string, gets everything selectionArgs = searchString?.takeIf { it.isNotEmpty() }?.let { selectionClause = "${UserDictionary.Words.WORD} = ?" arrayOf(it) } ?: run { selectionClause = null emptyArray<String>() } // Does a query against the table and returns a Cursor object mCursor = contentResolver.query( UserDictionary.Words.CONTENT_URI, // The content URI of the words table projection, // The columns to return for each row selectionClause, // Either null or the word the user entered selectionArgs, // Either empty or the string the user entered sortOrder // The sort order for the returned rows ) // Some providers return null if an error occurs, others throw an exception when (mCursor?.count) { null -> { /* * Insert code here to handle the error. Be sure not to use the cursor! * You might want to call android.util.Log.e() to log this error. */ } 0 -> { /* * Insert code here to notify the user that the search is unsuccessful. This isn't * necessarily an error. You might want to offer the user the option to insert a new * row, or re-type the search term. */ } else -> { // Insert code here to do something with the results } }
Java
/* * This defines a one-element String array to contain the selection argument. */ String[] selectionArgs = {""}; // Gets a word from the UI searchString = searchWord.getText().toString(); // Remember to insert code here to check for invalid or malicious input // If the word is the empty string, gets everything if (TextUtils.isEmpty(searchString)) { // Setting the selection clause to null returns all words selectionClause = null; selectionArgs[0] = ""; } else { // Constructs a selection clause that matches the word that the user entered selectionClause = UserDictionary.Words.WORD + " = ?"; // Moves the user's input string to the selection arguments selectionArgs[0] = searchString; } // Does a query against the table and returns a Cursor object mCursor = getContentResolver().query( UserDictionary.Words.CONTENT_URI, // The content URI of the words table projection, // The columns to return for each row selectionClause, // Either null or the word the user entered selectionArgs, // Either empty or the string the user entered sortOrder); // The sort order for the returned rows // Some providers return null if an error occurs, others throw an exception if (null == mCursor) { /* * Insert code here to handle the error. Be sure not to use the cursor! You can * call android.util.Log.e() to log this error. * */ // If the Cursor is empty, the provider found no matches } else if (mCursor.getCount() < 1) { /* * Insert code here to notify the user that the search is unsuccessful. This isn't necessarily * an error. You can offer the user the option to insert a new row, or re-type the * search term. */ } else { // Insert code here to do something with the results }
Bu sorgu, aşağıdaki SQL ifadesine benzer:
SELECT _ID, word, locale FROM words WHERE word = <userinput> ORDER BY word ASC;
Bu SQL deyiminde, sözleşme sınıfı sabit değerleri yerine gerçek sütun adları kullanılır.
Kötü amaçlı girişe karşı koru
İçerik sağlayıcı tarafından yönetilen veriler bir SQL veritabanındaysa harici güvenilmeyen verilerin ham SQL ifadelerine eklenmesi, SQL yerleştirilmesine yol açabilir.
Şu seçim cümlesini dikkate alın:
Kotlin
// Constructs a selection clause by concatenating the user's input to the column name var selectionClause = "var = $mUserInput"
Java
// Constructs a selection clause by concatenating the user's input to the column name String selectionClause = "var = " + userInput;
Bunu yaparsanız, kullanıcının potansiyel olarak kötü amaçlı SQL'i SQL ifadenize bağlamasına izin vermiş olursunuz.
Örneğin, kullanıcı mUserInput
için "nothing; DROP DROP *;" değerini girebilir ve bu durumda var = nothing; DROP TABLE *;
seçim ifadesi ortaya çıkar.
Seçim ifadesi SQL ifadesi olarak işlendiğinden, sağlayıcı SQL yerleştirme girişimlerini yakalayacak şekilde ayarlanmamışsa sağlayıcının bu SQLite veritabanındaki tüm tabloları silmesine neden olabilir.
Bu sorunu önlemek için değiştirilebilir parametre olarak ?
kullanan bir seçim ifadesi ve ayrı bir seçim bağımsız değişkenleri dizisi kullanın. Bu şekilde, kullanıcı girişi bir SQL ifadesinin parçası olarak yorumlanmak yerine doğrudan sorguya bağlanır.
SQL olarak değerlendirilmediği için kullanıcı girişi kötü amaçlı SQL yerleştiremez. Kullanıcı girişini dahil etmek için birleştirme yöntemi kullanmak yerine şu seçim ifadesini kullanın:
Kotlin
// Constructs a selection clause with a replaceable parameter var selectionClause = "var = ?"
Java
// Constructs a selection clause with a replaceable parameter String selectionClause = "var = ?";
Seçim bağımsız değişkenleri dizisini şu şekilde ayarlayın:
Kotlin
// Defines a mutable list to contain the selection arguments var selectionArgs: MutableList<String> = mutableListOf()
Java
// Defines an array to contain the selection arguments String[] selectionArgs = {""};
Seçim bağımsız değişkenleri dizisine aşağıdaki gibi bir değer girin:
Kotlin
// Adds the user's input to the selection argument selectionArgs += userInput
Java
// Sets the selection argument to the user's input selectionArgs[0] = userInput;
Sağlayıcı SQL veritabanına dayalı olmasa bile, değiştirilebilir parametre olarak ?
kullanan bir seçim ifadesi ve bir seçim bağımsız değişkeni dizisi kullanan bir seçim ifadesi, bir seçimi belirtmek için tercih edilen yöntemdir.
Sorgu sonuçlarını görüntüle
ContentResolver.query()
istemci yöntemi, her zaman sorgunun seçim ölçütleriyle eşleşen satırlar için sorgunun projeksiyonu tarafından belirtilen sütunları içeren bir Cursor
döndürür. Cursor
nesnesi, içerdiği satırlara ve sütunlara rastgele okuma erişimi sağlar.
Cursor
yöntemlerini kullanarak sonuçlardaki satırlar üzerinde yineleme yapabilir, her sütunun veri türünü belirleyebilir, bir sütundaki verileri alabilir ve sonuçların diğer özelliklerini inceleyebilirsiniz.
Bazı Cursor
uygulamaları, sağlayıcının verileri değiştiğinde nesneyi otomatik olarak günceller, Cursor
değiştiğinde gözlemci nesnesinde yöntemleri tetikler veya her ikisini de yapar.
Not: Sağlayıcı, sorguyu yapan nesnenin yapısına göre sütunlara erişimi kısıtlayabilir. Örneğin, Kişi Sağlayıcı bazı sütunlar için erişimi bağdaştırıcıların senkronize edilmesiyle kısıtladığından, bu sütunları bir etkinliğe veya hizmete döndürmez.
Seçim ölçütleriyle eşleşen satır yoksa sağlayıcı, Cursor.getCount()
için 0 olan bir Cursor
nesnesi, yani boş imleç döndürür.
Dahili bir hata oluşursa sorgunun sonuçları belirli sağlayıcıya bağlı olarak değişir. null
döndürebilir veya Exception
atabilir.
Cursor
bir satır listesi olduğundan Cursor
içeriğini görüntülemenin iyi bir yolu, bunu SimpleCursorAdapter
kullanarak bir ListView
öğesine bağlamaktır.
Aşağıdaki snippet'te, önceki snippet'teki kod devam eder. Sorgu tarafından alınan Cursor
öğesini içeren bir SimpleCursorAdapter
nesnesi oluşturur ve bu nesneyi ListView
için bağdaştırıcı olarak ayarlar.
Kotlin
// Defines a list of columns to retrieve from the Cursor and load into an output row val wordListColumns : Array<String> = arrayOf( UserDictionary.Words.WORD, // Contract class constant containing the word column name UserDictionary.Words.LOCALE // Contract class constant containing the locale column name ) // Defines a list of View IDs that receive the Cursor columns for each row val wordListItems = intArrayOf(R.id.dictWord, R.id.locale) // Creates a new SimpleCursorAdapter cursorAdapter = SimpleCursorAdapter( applicationContext, // The application's Context object R.layout.wordlistrow, // A layout in XML for one row in the ListView mCursor, // The result from the query wordListColumns, // A string array of column names in the cursor wordListItems, // An integer array of view IDs in the row layout 0 // Flags (usually none are needed) ) // Sets the adapter for the ListView wordList.setAdapter(cursorAdapter)
Java
// Defines a list of columns to retrieve from the Cursor and load into an output row String[] wordListColumns = { UserDictionary.Words.WORD, // Contract class constant containing the word column name UserDictionary.Words.LOCALE // Contract class constant containing the locale column name }; // Defines a list of View IDs that receive the Cursor columns for each row int[] wordListItems = { R.id.dictWord, R.id.locale}; // Creates a new SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter( getApplicationContext(), // The application's Context object R.layout.wordlistrow, // A layout in XML for one row in the ListView mCursor, // The result from the query wordListColumns, // A string array of column names in the cursor wordListItems, // An integer array of view IDs in the row layout 0); // Flags (usually none are needed) // Sets the adapter for the ListView wordList.setAdapter(cursorAdapter);
Not: Bir Cursor
içeren ListView
öğesini geri getirmek için imleç _ID
adlı bir sütun içermelidir.
Bu nedenle, gösterilen sorgu ListView
göstermese bile Words
tablosu için _ID
sütununu alır.
Bu kısıtlama, çoğu sağlayıcının her tablosunda neden bir _ID
sütunu olduğunu da açıklar.
Sorgu sonuçlarından veri alma
Bu sonuçları sorgu sonuçlarını görüntülemenin yanı sıra başka görevler için de kullanabilirsiniz. Örneğin, yazımları Kullanıcı Sözlüğü Sağlayıcısı'ndan alabilir ve ardından diğer sağlayıcılarda arayabilirsiniz. Bunun için Cursor
içindeki satırları aşağıdaki örnekte gösterildiği gibi yineleyin:
Kotlin
/* * Only executes if the cursor is valid. The User Dictionary Provider returns null if * an internal error occurs. Other providers might throw an Exception instead of returning null. */ mCursor?.apply { // Determine the column index of the column named "word" val index: Int = getColumnIndex(UserDictionary.Words.WORD) /* * Moves to the next row in the cursor. Before the first movement in the cursor, the * "row pointer" is -1, and if you try to retrieve data at that position you get an * exception. */ while (moveToNext()) { // Gets the value from the column newWord = getString(index) // Insert code here to process the retrieved word ... // End of while loop } }
Java
// Determine the column index of the column named "word" int index = mCursor.getColumnIndex(UserDictionary.Words.WORD); /* * Only executes if the cursor is valid. The User Dictionary Provider returns null if * an internal error occurs. Other providers might throw an Exception instead of returning null. */ if (mCursor != null) { /* * Moves to the next row in the cursor. Before the first movement in the cursor, the * "row pointer" is -1, and if you try to retrieve data at that position you get an * exception. */ while (mCursor.moveToNext()) { // Gets the value from the column newWord = mCursor.getString(index); // Insert code here to process the retrieved word ... // End of while loop } } else { // Insert code here to report an error if the cursor is null or the provider threw an exception }
Cursor
uygulamaları, nesneden farklı veri türlerini almak için çeşitli "get" yöntemleri içerir. Örneğin, önceki snippet getString()
değerini kullanır. Bunlar ayrıca, sütunun veri türünü belirten bir değer döndüren getType()
yöntemine sahiptir.
İçerik sağlayıcı izinleri
Bir sağlayıcının uygulaması, diğer uygulamaların sağlayıcı verilerine erişmek için sahip olması gereken izinleri belirtebilir. Bu izinler, kullanıcıya bir uygulamanın hangi verilere erişmeye çalıştığını bildirir. Sağlayıcının gereksinimlerine bağlı olarak, diğer uygulamalar sağlayıcıya erişmek için ihtiyaç duydukları izinleri ister. Son kullanıcılar uygulamayı yüklediklerinde istenen izinleri görür.
Bir sağlayıcının uygulamasında herhangi bir izin belirtilmezse sağlayıcı dışa aktarılmadığı sürece diğer uygulamalar, sağlayıcının verilerine erişemez. Ayrıca sağlayıcının uygulamasındaki bileşenler, belirtilen izinlerden bağımsız olarak her zaman tam okuma ve yazma erişimine sahiptir.
Kullanıcı Sözlüğü Sağlayıcısı, kendisinden veri almak için android.permission.READ_USER_DICTIONARY
iznini gerektirir.
Sağlayıcının veri eklemek, güncellemek veya silmek için ayrı bir android.permission.WRITE_USER_DICTIONARY
izni vardır.
Bir uygulama, bir sağlayıcıya erişmek üzere gereken izinleri almak için bu izinleri manifest dosyasında bir <uses-permission>
öğesiyle ister. Android Paket Yöneticisi uygulamayı yüklediğinde kullanıcı, uygulamanın istediği tüm izinleri onaylamalıdır. Kullanıcı bunları onaylarsa Paket Yöneticisi yükleme işlemine devam eder. Kullanıcı onaylamazsa Paket Yöneticisi yüklemeyi durdurur.
Aşağıdaki örnek <uses-permission>
öğesi, Kullanıcı Sözlüğü Sağlayıcısı'na okuma erişimi istiyor:
<uses-permission android:name="android.permission.READ_USER_DICTIONARY">
İzinlerin sağlayıcı erişimi üzerindeki etkisi, Güvenlik ipuçları bölümünde daha ayrıntılı olarak açıklanmıştır.
Veri ekleme, güncelleme ve silme
Bir sağlayıcıdan veri alırken olduğu gibi, verileri değiştirmek için sağlayıcı istemcisi ile sağlayıcının ContentProvider
arasındaki etkileşimi de kullanırsınız.
İlgili ContentProvider
yöntemine aktarılan bağımsız değişkenlerle bir ContentResolver
yöntemini çağırırsınız. Sağlayıcı ve sağlayıcı, güvenlik ve işlemler arası iletişimi otomatik olarak yönetir.
Veri ekle
Bir sağlayıcıya veri eklemek için ContentResolver.insert()
yöntemini çağırırsınız. Bu yöntem, sağlayıcıya yeni bir satır ekler ve bu satır için bir içerik URI'si döndürür.
Aşağıdaki snippet'te Kullanıcı Sözlüğü Sağlayıcısı'na nasıl yeni kelime ekleneceği gösterilmektedir:
Kotlin
// Defines a new Uri object that receives the result of the insertion lateinit var newUri: Uri ... // Defines an object to contain the new values to insert val newValues = ContentValues().apply { /* * Sets the values of each column and inserts the word. The arguments to the "put" * method are "column name" and "value". */ put(UserDictionary.Words.APP_ID, "example.user") put(UserDictionary.Words.LOCALE, "en_US") put(UserDictionary.Words.WORD, "insert") put(UserDictionary.Words.FREQUENCY, "100") } newUri = contentResolver.insert( UserDictionary.Words.CONTENT_URI, // The UserDictionary content URI newValues // The values to insert )
Java
// Defines a new Uri object that receives the result of the insertion Uri newUri; ... // Defines an object to contain the new values to insert ContentValues newValues = new ContentValues(); /* * Sets the values of each column and inserts the word. The arguments to the "put" * method are "column name" and "value". */ newValues.put(UserDictionary.Words.APP_ID, "example.user"); newValues.put(UserDictionary.Words.LOCALE, "en_US"); newValues.put(UserDictionary.Words.WORD, "insert"); newValues.put(UserDictionary.Words.FREQUENCY, "100"); newUri = getContentResolver().insert( UserDictionary.Words.CONTENT_URI, // The UserDictionary content URI newValues // The values to insert );
Yeni satırla ilgili veriler, tek satırlık imleç biçimine benzer şekilde tek bir ContentValues
nesnesine yerleştirilir. Bu nesnedeki sütunların aynı veri türüne sahip olması gerekmez. Hiçbir değer belirtmek istemiyorsanız ContentValues.putNull()
kullanarak bir sütunu null
olarak ayarlayabilirsiniz.
Bu sütun otomatik olarak korunduğu için önceki snippet _ID
sütununu eklemez. Sağlayıcı, eklenen her satıra benzersiz bir _ID
değeri atar. Sağlayıcılar genellikle bu değeri tablonun birincil anahtarı olarak kullanır.
newUri
içinde döndürülen içerik URI'si, yeni eklenen satırı aşağıdaki biçimde tanımlar:
content://user_dictionary/words/<id_value>
<id_value>
, yeni satır için _ID
öğesinin içeriğidir.
Çoğu sağlayıcı, bu içerik URI'si biçimini otomatik olarak algılayıp istenen işlemi söz konusu satırda gerçekleştirebilir.
Döndürülen Uri
öğesinden _ID
değerini almak için ContentUris.parseId()
çağrısı yapın.
Verileri güncelle
Sorguda olduğu gibi, ekleme ve seçim ölçütlerinde olduğu gibi, bir satırı güncellemek için güncellenen değerlere sahip bir ContentValues
nesnesi kullanırsınız.
Kullandığınız istemci yöntemi: ContentResolver.update()
. Yalnızca güncellediğiniz sütunlar için ContentValues
nesnesine değer eklemeniz gerekir. Bir sütunun içeriğini temizlemek istiyorsanız değeri null
olarak ayarlayın.
Aşağıdaki snippet, yerel ayarı "en"
diline sahip tüm satırları null
yerel ayarına sahip olacak şekilde değiştirir. Döndürülen değer, güncellenen satır sayısıdır.
Kotlin
// Defines an object to contain the updated values val updateValues = ContentValues().apply { /* * Sets the updated value and updates the selected words. */ putNull(UserDictionary.Words.LOCALE) } // Defines selection criteria for the rows you want to update val selectionClause: String = UserDictionary.Words.LOCALE + "LIKE ?" val selectionArgs: Array<String> = arrayOf("en_%") // Defines a variable to contain the number of updated rows var rowsUpdated: Int = 0 ... rowsUpdated = contentResolver.update( UserDictionary.Words.CONTENT_URI, // The UserDictionary content URI updateValues, // The columns to update selectionClause, // The column to select on selectionArgs // The value to compare to )
Java
// Defines an object to contain the updated values ContentValues updateValues = new ContentValues(); // Defines selection criteria for the rows you want to update String selectionClause = UserDictionary.Words.LOCALE + " LIKE ?"; String[] selectionArgs = {"en_%"}; // Defines a variable to contain the number of updated rows int rowsUpdated = 0; ... /* * Sets the updated value and updates the selected words. */ updateValues.putNull(UserDictionary.Words.LOCALE); rowsUpdated = getContentResolver().update( UserDictionary.Words.CONTENT_URI, // The UserDictionary content URI updateValues, // The columns to update selectionClause, // The column to select on selectionArgs // The value to compare to );
ContentResolver.update()
çağırırken kullanıcı girişini temizleyin. Bu konuda daha fazla bilgi edinmek için Kötü amaçlı girişe karşı koruma bölümünü okuyun.
Verileri sil
Satırları silmek, satır verilerini almaya benzer. Silmek istediğiniz satırlar için seçim ölçütleri belirtirsiniz ve istemci yöntemi, silinen satır sayısını döndürür.
Aşağıdaki snippet, uygulama kimliği "user"
ile eşleşen satırları siler. Yöntem, silinen satır sayısını döndürür.
Kotlin
// Defines selection criteria for the rows you want to delete val selectionClause = "${UserDictionary.Words.APP_ID} LIKE ?" val selectionArgs: Array<String> = arrayOf("user") // Defines a variable to contain the number of rows deleted var rowsDeleted: Int = 0 ... // Deletes the words that match the selection criteria rowsDeleted = contentResolver.delete( UserDictionary.Words.CONTENT_URI, // The UserDictionary content URI selectionClause, // The column to select on selectionArgs // The value to compare to )
Java
// Defines selection criteria for the rows you want to delete String selectionClause = UserDictionary.Words.APP_ID + " LIKE ?"; String[] selectionArgs = {"user"}; // Defines a variable to contain the number of rows deleted int rowsDeleted = 0; ... // Deletes the words that match the selection criteria rowsDeleted = getContentResolver().delete( UserDictionary.Words.CONTENT_URI, // The UserDictionary content URI selectionClause, // The column to select on selectionArgs // The value to compare to );
ContentResolver.delete()
çağırırken kullanıcı girişini temizleyin. Bu konuda daha fazla bilgi edinmek için Kötü amaçlı girişlere karşı koruma bölümünü okuyun.
Sağlayıcı veri türleri
İçerik sağlayıcılar birçok farklı veri türü sunabilir. Kullanıcı Sözlüğü Sağlayıcısı yalnızca metin sunar ancak sağlayıcılar aşağıdaki biçimleri de sunabilir:
- Tam sayı
- uzun tam sayı (uzun)
- kayan nokta
- uzun kayan nokta (çift)
Sağlayıcıların sıklıkla kullandığı bir diğer veri türü de 64 KB bayt dizisi olarak uygulanan bir ikili büyük nesne (BLOB) şeklindedir. Cursor
sınıfı "get" yöntemlerine bakarak kullanılabilir veri türlerini görebilirsiniz.
Bir sağlayıcıdaki her sütunun veri türü genellikle sağlayıcının dokümanlarında listelenir.
Kullanıcı Sözlüğü Sağlayıcısı için veri türleri, UserDictionary.Words
sözleşme sınıfının referans dokümanlarında listelenmiştir. Sözleşme sınıfları, Sözleşme sınıfları bölümünde açıklanmıştır.
Veri türünü Cursor.getType()
çağırarak da belirleyebilirsiniz.
Sağlayıcılar, tanımladıkları her içerik URI'si için MIME veri türü bilgilerini de korur. Uygulamanızın, sağlayıcının sunduğu verileri işleyip işleyemediğini öğrenmek veya MIME türüne göre bir işleme türü seçmek için MIME türü bilgilerini kullanabilirsiniz. Karmaşık veri yapıları veya dosyalar içeren bir sağlayıcıyla çalışırken genellikle MIME türüne ihtiyacınız vardır.
Örneğin, Kişi Sağlayıcı'daki ContactsContract.Data
tablosu, her satırda depolanan kişi verilerinin türünü etiketlemek için MIME türlerini kullanır. İçerik URI'sine karşılık gelen MIME türünü almak için ContentResolver.getType()
çağrısı yapın.
MIME türü referansı bölümünde, hem standart hem de özel MIME türlerinin söz dizimi açıklanmaktadır.
Alternatif sağlayıcı erişimi biçimleri
Uygulama geliştirmede üç alternatif sağlayıcı erişimi biçimi önemlidir:
-
Toplu erişim:
ContentProviderOperation
sınıfındaki yöntemlerle bir erişim çağrıları toplu olarak oluşturabilir ve daha sonra bunlarıContentResolver.applyBatch()
ile uygulayabilirsiniz. -
Eşzamansız sorgular: Sorguları ayrı bir iş parçacığında yapın. Bir
CursorLoader
nesnesi kullanabilirsiniz. Yükleyiciler kılavuzundaki örnekler, bunun nasıl yapılacağını gösterir. - Amaçlar kullanarak veri erişimi: Doğrudan sağlayıcıya niyet gönderemeseniz de sağlayıcının uygulamasına bir niyet gönderebilirsiniz. Bu uygulama, genellikle sağlayıcının verilerini değiştirmek için en iyi donanıma sahiptir.
Amaçlar kullanılarak yapılan toplu erişim ve değişiklik yapma aşağıdaki bölümlerde açıklanmıştır.
Toplu erişim
Bir sağlayıcıya toplu erişim, çok sayıda satır eklemek, aynı yöntem çağrısında birden çok tabloya satır eklemek ve genel olarak atom işlemi adı verilen işlem olarak işlem sınırları içinde bir dizi işlemi gerçekleştirmek için yararlıdır.
Toplu modda bir sağlayıcıya erişmek için ContentProviderOperation
nesne dizisi oluşturup bunları ContentResolver.applyBatch()
ile bir içerik sağlayıcıya dağıtın. Belirli bir içerik URI'si yerine, içerik sağlayıcının yetkisini bu yönteme geçirirsiniz.
Bu sayede dizideki her ContentProviderOperation
nesnesi farklı bir tabloda çalışabilir. ContentResolver.applyBatch()
çağrısı, bir sonuç dizisi döndürür.
ContactsContract.RawContacts
sözleşme sınıfının açıklaması, toplu eklemeyi gösteren bir kod snippet'i içerir.
Amaçları kullanarak veri erişimi
Amaçlar, içerik sağlayıcıya dolaylı erişim sağlayabilir. Uygulamanızın erişim izinleri olmasa bile, izinleri olan bir uygulamadan sonuç intent'i geri alarak veya izinlere sahip bir uygulamayı etkinleştirip kullanıcının uygulamada çalışmasına izin vererek kullanıcının erişim izinleri olmasa bile sağlayıcıdaki verilere erişmesine izin verebilirsiniz.
Geçici izinlerle erişim elde etme
Gerekli izinlere sahip bir uygulamaya niyet göndererek ve URI izinlerini içeren bir sonuç niyetini geri alarak uygun erişim izinlerine sahip olmasanız bile içerik sağlayıcıdaki verilere erişebilirsiniz. Bunlar, belirli bir içerik URI'sını alan etkinlik bitene kadar devam eden izinlerdir. Kalıcı izinlere sahip uygulama, sonuç amacında bir işaret ayarlayarak geçici izinler verir:
-
Okuma izni:
FLAG_GRANT_READ_URI_PERMISSION
-
Yazma izni:
FLAG_GRANT_WRITE_URI_PERMISSION
Not: Bu işaretler, yetkisi içerik URI'sinde bulunan sağlayıcıya genel okuma veya yazma erişimi vermez. Erişim yalnızca URI'nın kendisi içindir.
Başka bir uygulamaya içerik URI'leri gönderirken bu işaretlerden en az birini ekleyin. İşaretler, amacı alan ve Android 11 (API düzeyi 30) veya sonraki sürümleri hedefleyen tüm uygulamalar için aşağıdaki özellikleri sağlar:
- Amaçta yer alan bayrağa bağlı olarak içerik URI'sının temsil ettiği verileri okuma veya bu verilere yazma.
- URI yetkilisiyle eşleşen içerik sağlayıcısını içeren uygulamada paket görünürlüğü elde edin. Niyeti gönderen uygulama ile içerik sağlayıcısını içeren uygulama iki farklı uygulama olabilir.
Sağlayıcı, <provider>
öğesinin android:grantUriPermissions
özelliğini ve <provider>
öğesinin <grant-uri-permission>
alt öğesini kullanarak manifest dosyasındaki içerik URI'leri için URI izinlerini tanımlar. URI izin mekanizması, Android'de İzinler kılavuzunda daha ayrıntılı olarak açıklanmıştır.
Örneğin, READ_CONTACTS
iznine sahip olmasanız bile Kişi Sağlayıcı'da bir kişiyle ilgili verileri alabilirsiniz. Bunu, bir kişiye doğum gününde e-selamlar gönderen bir uygulamada yapmak isteyebilirsiniz. Kullanıcının tüm kişilerine ve tüm bilgilerine erişmenizi sağlayan READ_CONTACTS
istemek yerine kullanıcının, uygulamanızda hangi kişileri kullanacağını kontrol etmesini sağlayın. Bunun için aşağıdaki süreci uygulayın:
-
Uygulamanızda,
startActivityForResult()
yöntemini kullanarakACTION_PICK
işlemini ve "kişiler" MIME türünüCONTENT_ITEM_TYPE
içeren bir niyet gönderin. - Bu amaç, Kişiler uygulamasının "seçim" etkinliğine ait intent filtresiyle eşleştiğinden etkinlik ön plana gelir.
-
Kullanıcı, seçim etkinliğinde güncellemek için bir kişi seçer. Böyle bir durumda, seçim etkinliği, uygulamanıza geri dönüş yapmak üzere bir amaç oluşturmak için
setResult(resultcode, intent)
yöntemini çağırır. Amaç, kullanıcının seçtiği kişinin içerik URI'sını ve "ekstralar"FLAG_GRANT_READ_URI_PERMISSION
işaretini içerir. Bu işaretler, içerik URI'si ile işaret edilen kişinin verilerini okuması için uygulamanıza URI izni verir. Seçim etkinliği daha sonra kontrolü uygulamanıza geri döndürmek içinfinish()
işlevini çağırır. -
Etkinliğiniz ön plana döner ve sistem, etkinliğinizin
onActivityResult()
yöntemini çağırır. Bu yöntem, Kişiler uygulamasındaki seçim etkinliği tarafından oluşturulan sonuç amacını alır. - Sonuç amacındaki içerik URI'si ile manifest dosyanızdaki sağlayıcı için kalıcı okuma erişimi izni istememiş olsanız bile kişi verilerini Kişi Sağlayıcı'dan okuyabilirsiniz. Sonrasında kişinin doğum günü bilgilerini veya e-posta adresini alıp e-selamlama gönderebilirsiniz.
Başka bir uygulama kullan
Kullanıcının erişim izniniz olmayan verileri değiştirmesine izin vermenin bir başka yolu da izinleri olan bir uygulamayı etkinleştirmek ve işi kullanıcının yapmasına izin vermektir.
Örneğin, Takvim uygulaması, uygulamanın ekleme kullanıcı arayüzünü etkinleştirmenize olanak tanıyan ACTION_INSERT
niyetini kabul eder. Bu niyette "ekstralar" veri aktarabilirsiniz. Uygulama, bu verileri kullanıcı arayüzünü önceden doldurmak için kullanır. Düzenli etkinlikler karmaşık bir söz dizimine sahip olduğundan, etkinlikleri Takvim Sağlayıcı'ya eklemek için tercih edilen yöntem, Takvim uygulamasını bir ACTION_INSERT
ile etkinleştirmek ve ardından kullanıcının etkinliği oraya eklemesine izin vermektir.
Yardımcı uygulama kullanarak verileri göster
Uygulamanızın erişim izinleri varsa verileri başka bir uygulamada görüntülemek için intent kullanabilirsiniz. Örneğin, Takvim uygulaması belirli bir tarihi veya etkinliği görüntüleyen ACTION_VIEW
niyetini kabul eder.
Bu sayede, kendi kullanıcı arayüzünüzü oluşturmanıza gerek kalmadan takvim bilgilerini görüntüleyebilirsiniz.
Bu özellik hakkında daha fazla bilgi edinmek için
Takvim sağlayıcısına genel bakış bölümüne göz atın.
Niyeti gönderdiğiniz uygulamanın, sağlayıcıyla ilişkilendirilmiş uygulama olması gerekmez. Örneğin, Kişi Sağlayıcıdan bir kişi alabilir ve ardından, kişinin resmine ait içerik URI'sini içeren bir ACTION_VIEW
niyetini resim görüntüleyiciye gönderebilirsiniz.
Sözleşmeli sınıflar
Sözleşme sınıfı, uygulamaların içerik URI'leri, sütun adları, amaç işlemleri ve içerik sağlayıcının diğer özellikleriyle çalışmasına yardımcı olan sabitleri tanımlar. Sözleşme sınıfları, sağlayıcı ile otomatik olarak dahil edilmez. Sağlayıcının geliştiricisi, bunları tanımlamalı ve ardından diğer geliştiricilerin kullanımına sunmalıdır. Android platformuna dahil olan sağlayıcıların birçoğunun android.provider
paketinde ilgili sözleşme sınıfları vardır.
Örneğin, Kullanıcı Sözlüğü Sağlayıcısı, içerik URI'si ve sütun adı sabitlerini içeren UserDictionary
sözleşme sınıfına sahiptir. Words
tablosunun içerik URI'si UserDictionary.Words.CONTENT_URI
sabit değeri ile tanımlanır.
UserDictionary.Words
sınıfı, bu kılavuzdaki örnek snippet'lerde kullanılan sütun adı sabit değerlerini de içerir. Örneğin, bir sorgu projeksiyonu aşağıdaki gibi tanımlanabilir:
Kotlin
val projection : Array<String> = arrayOf( UserDictionary.Words._ID, UserDictionary.Words.WORD, UserDictionary.Words.LOCALE )
Java
String[] projection = { UserDictionary.Words._ID, UserDictionary.Words.WORD, UserDictionary.Words.LOCALE };
Başka bir sözleşme sınıfı, Kişi Sağlayıcısı için ContactsContract
şeklindedir.
Bu sınıfın referans belgeleri arasında örnek kod snippet'leri yer almaktadır. Alt sınıflarından biri olan ContactsContract.Intents.Insert
, amaçlar ve amaç verileri için sabit değerler içeren bir sözleşme sınıfıdır.
MIME türü referansı
İçerik sağlayıcılar; standart MIME medya türlerini, özel MIME türü dizelerini veya her ikisini birden döndürebilir.
MIME türleri aşağıdaki biçimdedir:
type/subtype
Örneğin, iyi bilinen text/html
MIME türü, text
türüne ve html
alt türüne sahiptir. Sağlayıcının bir URI için bu türü döndürmesi, o URI'yı kullanan sorgunun HTML etiketlerini içeren metni döndürdüğü anlamına gelir.
Sağlayıcıya özel MIME türleri olarak da adlandırılan özel MIME türü dizeleri, daha karmaşık type ve subtype değerlerine sahiptir. Birden çok satır için tür değeri her zaman aşağıdaki gibidir:
vnd.android.cursor.dir
Tek bir satır için tür değeri her zaman aşağıdaki gibidir:
vnd.android.cursor.item
subtype, sağlayıcıya özeldir. Yerleşik Android sağlayıcıların genellikle basit bir alt türü vardır. Örneğin, Kişiler uygulaması bir telefon numarası için bir satır oluşturduğunda, satırda aşağıdaki MIME türünü ayarlar:
vnd.android.cursor.item/phone_v2
Alt tür değeri: phone_v2
.
Diğer sağlayıcı geliştiricileri, sağlayıcının yetkisine ve tablo adlarına dayalı olarak kendi alt tür kalıplarını oluşturabilir. Örneğin, tren tarifelerini içeren bir sağlayıcıyı düşünün.
Sağlayıcının yetkisi com.example.trains
olup Satır1, Satır2 ve Satır3 tablolarını içerir. Line1 tablosu için aşağıdaki içerik URI'sine yanıt olarak:
content://com.example.trains/Line1
sağlayıcı şu MIME türünü döndürür:
vnd.android.cursor.dir/vnd.example.line1
Satır2 tablosunun 5. satırı için aşağıdaki içerik URI'sine yanıt olarak:
content://com.example.trains/Line2/5
sağlayıcı şu MIME türünü döndürür:
vnd.android.cursor.item/vnd.example.line2
Çoğu içerik sağlayıcı, kullandıkları MIME türleri için sözleşme sınıfı sabitlerini tanımlar. Örneğin, Kişi Sağlayıcı sözleşme sınıfı ContactsContract.RawContacts
, tek bir ham kişi satırının MIME türü için CONTENT_ITEM_TYPE
sabitini tanımlar.
Tek satırlara ilişkin içerik URI'leri İçerik URI'leri bölümünde açıklanmıştır.