İçerik sağlayıcı, merkezi bir veri deposuna erişimi yönetir. Sağlayıcı, genellikle verilerle çalışmak için kendi kullanıcı arayüzünü sağlayan bir Android uygulamasının parçasıdır. Ancak içerik sağlayıcılar, temel olarak sağlayıcı istemci nesnesi kullanarak sağlayıcıya erişen diğer uygulamalar tarafından kullanılır. Sağlayıcılar ve sağlayıcı istemcileri birlikte, veri için tutarlı ve standart bir arayüz sunar. Bu arayüz, işlemler arası iletişimi ve güvenli veri erişimini de yönetir.
Genellikle içerik sağlayıcılarla iki senaryodan birinde çalışırsınız: Başka bir uygulamadaki mevcut bir içerik sağlayıcıya erişmek için kod uygulama veya uygulamanızda diğer uygulamalarla veri paylaşmak için yeni bir içerik sağlayıcı oluşturma.
Bu sayfada, mevcut içerik sağlayıcılarla çalışmayla ilgili temel bilgiler verilmektedir. Kendi uygulamalarınızda içerik sağlayıcıları uygulama hakkında bilgi edinmek için İçerik sağlayıcı oluşturma başlıklı makaleyi inceleyin.
Bu konuda aşağıdakiler 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.
- Bir içerik sağlayıcıya 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 harici uygulamalara ilişkisel veritabanında bulunan tablolara benzer bir veya daha fazla tablo olarak 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 bir veri parçasını temsil eder.
İçerik sağlayıcı, uygulamanızdaki veri depolama katmanına erişimi çeşitli API'ler ve bileşenler için koordine eder. Şekil 1'de gösterildiği gibi bunlar arasında şunlar bulunur:
- Uygulama verilerinize erişimi diğer uygulamalarla paylaşma
- Widget'a veri gönderme
SearchRecentSuggestionsProvider
kullanarak arama çerçevesi üzerinden uygulamanız için özel arama önerileri döndürmeAbstractThreadedSyncAdapter
uygulamasını kullanarak uygulama verilerini sunucunuzla senkronize etmeCursorLoader
kullanarak kullanıcı arayüzünüze veri yükleme
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
bölümündeki ContentResolver
nesnesini kullanırsınız. ContentResolver
nesnesi, ContentProvider
'ü uygulayan bir sınıfın örneği olan sağlayıcı nesnesi ile 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 nesnenin, ContentProvider
'nin somut alt sınıflarından birinin örneği olan sağlayıcı nesnesinde aynı ada sahip yöntemleri çağıran yöntemleri vardır. ContentResolver
yöntemleri, kalıcı depolama alanındaki temel "CRUD" (oluşturma, alma, güncelleme ve silme) işlevlerini sağlar.
Kullanıcı arayüzünüzden ContentProvider
'e erişmek için yaygın bir kalıp, arka planda eşzamansız bir sorgu çalıştırmak üzere CursorLoader
kullanır. Kullanıcı arayüzündeki
Activity
veya Fragment
, sorgu için bir CursorLoader
çağırır. Bu da,
ContentResolver
kullanarak ContentProvider
öğesini alır.
Bu sayede sorgu çalışırken kullanıcı arayüzü kullanıcı tarafından kullanılabilir durumda kalır. Bu kalıp, Şekil 2'de gösterildiği gibi, bir dizi farklı nesnenin yanı sıra temel depolama mekanizmasının etkileşimini içerir.
Not: Bir sağlayıcıya erişmek için uygulamanızın genellikle manifest dosyasında belirli izinler istemesi gerekir. Bu geliştirme kalıbı, İçerik sağlayıcı izinleri bölümünde daha ayrıntılı olarak açıklanmaktadır.
Android platformundaki yerleşik sağlayıcılardan biri, kullanıcının saklamak istediği standart olmayan kelimeleri saklayan Kullanıcı Sözlüğü Sağlayıcı'dır. Tablo 1'de, bu sağlayıcının tablosunda verilerin nasıl görünebileceği gösterilmektedir:
kelime | uygulama kimliği | sıklığı | yerel_ayar | _Kimlik |
---|---|---|---|---|
mapreduce |
kullanici1 | 100 | en_US | 1 |
precompiler |
user14 | 200 | fr_FR | 2 |
applet |
user2 | 225 | tr_TR | 3 |
const |
kullanici1 | 255 | pt_BR | 4 |
int |
user5 | 100 | en_UK | 5 |
Tablo 1'de her satır, standart bir sözlükte bulunmayan bir kelime örneğini temsil etmektedir. Her sütun, söz konusu kelimeye ait bir veri parçasını temsil eder (örneğin, ilk kez karşılaştığı yerel ayar). Sütun başlıkları, sağlayıcıda depolanan sütun adlarıdır. Bu nedenle, bir satırın yerel ayarına başvurmak için örneğin locale
sütununa başvurursunuz. Bu sağlayıcı için _ID
sütunu, sağlayıcının otomatik olarak sürdürdüğü bir birincil anahtar sütunu görevi görür.
Kullanıcı Sözlüğü Sağlayıcı'dan kelimelerin ve yerel ayarlarının listesini almak için ContentResolver.query()
işlevini ç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österilmektedir:
query() bağımsız değişkeni |
SELECT anahtar kelime/parametre | 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çiminde kullanılacak ölçütleri belirtir. |
selectionArgs |
Tam eşdeğeri yoktur. Seçim bağımsız değişkenleri, seçim yan tümcesinde ? yer tutucularının yerini alır.
|
|
sortOrder |
ORDER BY col,col,... |
sortOrder , döndürülen Cursor 'da satırların görüneceği 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ı (yetki) ve bir tabloyu işaret eden bir adı (yol) içerir. Bir sağlayıcıdaki 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üğü Sağlayıcısı Words
tablosunun içerik URI'sini içerir. ContentResolver
nesnesi, URI'nin yetkilisini 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. 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 bölümünü kullanır. Sağlayıcılar genellikle kullanıma sunduğu her tablo için bir yola sahiptir.
Önceki kod satırlarında, Words
tablosunun tam URI'si şöyle olur:
content://user_dictionary/words
content://
dizesi, her zaman mevcut olan ve içeriği içerik URI'si olarak tanımlayan şemadır.user_dictionary
dizesi, sağlayıcının yetkilisidir.words
dizesi, tablonun yoludur.
Birçok sağlayıcı, URI'nin sonuna bir kimlik değeri ekleyerek tablodaki tek bir satıra erişmenize izin verir. Örneğin, Kullanıcı Sözlüğü Sağlayıcı'dan _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);
Bir satır grubunu aldıktan sonra bunlardan birini güncellemek veya silmek istediğinizde genellikle kimlik değerlerini 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ı, URI'ye kimlik değerleri eklemek için kolaylık sağlayan yöntemler içerir. Önceki snippet'te, User Dictionary Provider içerik URI'sine kimlik eklemek için withAppendedId()
kullanılır.
Sağlayıcıdan veri alma
Bu bölümde, kullanıcı sözlüğü sağlayıcısını örnek olarak kullanarak bir sağlayıcıdan nasıl veri alınacağı açıklanmaktadır.
Daha net ifadelerle bu bölümdeki kod snippet'leri, UI iş parçacığında ContentResolver.query()
yöntemini çağırır. Ancak gerçek kodda sorguları ayrı bir iş parçacığında eşzamansız olarak yapın.
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. Tam bir uygulama göstermezler.
Bir sağlayıcıdan veri almak için şu 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 isteyin
Bir sağlayıcıdan veri almak için uygulamanızın sağlayıcının okuma erişimi iznine ihtiyacı var. Ç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.
Manifest'inizde bu öğeyi belirttiğinizde, uygulamanız için bu izni istemiş olursunuz. Kullanıcılar uygulamanızı yüklediğinde bu isteği dolaylı olarak kabul eder.
Kullandığınız sağlayıcının okuma erişim izninin tam adını ve sağlayıcı tarafından kullanılan diğer erişim izinlerinin adlarını bulmak için sağlayıcının belgelerine bakın.
Sağlayıcılara erişme konusunda izinlerin rolü İçerik sağlayıcı izinleri bölümünde daha ayrıntılı olarak açıklanmıştır.
Kullanıcı Sözlüğü Sağlayıcı, android.permission.READ_USER_DICTIONARY
iznini manifest dosyasında tanımlar. Bu nedenle, sağlayıcıdan okumak isteyen bir uygulama bu izni istemelidir.
Sorguyu oluşturma
Bir sağlayıcıdan veri almayla ilgili bir 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 = {""};
Aşağıdaki snippet'te, kullanıcı sözlüğü sağlayıcısı örnek olarak kullanılarak ContentResolver.query()
işlevinin nasıl kullanılacağı gösterilmektedir. Sağlayıcı istemci sorgusu, SQL sorgusuna benzer ve döndürülecek bir sütun grubu, bir seçim ölçütleri grubu ve bir sıralama düzeni içerir.
Sorgunun döndürdüğü sütun grubuna projeksiyon denir ve değişken mProjection
olur.
Alınacak satırları belirten ifade, bir seçim yan tümcesine ve seçim bağımsız değişkenlerine bölünür. Seçim yan tümcesi, mantıksal ve boole ifadeleri, sütun adları ve değerlerinin bir birleşimidir. Değişken mSelectionClause
. Bir değer yerine, değiştirilebilir ?
parametresini belirtirseniz sorgu yöntemi, değeri mSelectionArgs
değişkeni olan seçim bağımsız değişkenleri dizisinden alır.
Sonraki snippet'te, kullanıcı bir kelime girmezse seçim yan tümcesi null
olarak ayarlanır ve sorgu, sağlayıcıdaki tüm kelimeleri döndürür. Kullanıcı bir kelime girerse seçim yan tümcesi 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 ifadesiyle benzerdir:
SELECT _ID, word, locale FROM words WHERE word = <userinput> ORDER BY word ASC;
Bu SQL ifadesi, sözleşme sınıfı sabitleri yerine gerçek sütun adlarını kullanır.
Kötü amaçlı girişlere karşı koruma
İçerik sağlayıcı tarafından yönetilen veriler bir SQL veritabanındaysa ham SQL ifadelerine güvenilmeyen harici veriler dahil etmek SQL yerleştirmeye neden olabilir.
Aşağıdaki seçim yan tümcesini ele alalım:
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 SQL ifadenize kötü amaçlı SQL eklemesine izin vermiş olursunuz.
Örneğin, kullanıcı mUserInput
için "nothing; DROP TABLE *;" yazabilir. Bu, var = nothing; DROP TABLE *;
seçim yan tümcesini oluşturur.
Seçim yan tümcesi bir SQL ifadesi olarak değerlendirildiğinden, sağlayıcı SQL yerleştirme girişimlerini yakalayacak şekilde ayarlanmadığı sürece sağlayıcının temel SQLite veritabanındaki tüm tabloları silmesine neden olabilir.
Bu sorunu önlemek için değiştirilebilir parametre olarak ?
ve seçimle ilgili ayrı bir bağımsız değişkenler dizisi kullanan bir seçim ifadesi kullanın. Bu sayede, kullanıcı girişi bir SQL ifadesi kapsamında yorumlanmak yerine doğrudan sorguya bağlanır.
SQL olarak değerlendirilmediğinden kullanıcı girişi, kötü amaçlı SQL enjeksiyonu yapamaz. Kullanıcı girişini dahil etmek için birleştirme yerine şu seçim yan tümcesini 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 şu şekilde bir değer koyun:
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;
Değiştirilebilir parametre olarak ?
kullanan bir seçim ifadesi ve bir seçim bağımsız değişkenleri dizisi, sağlayıcı SQL veritabanına dayalı olmasa bile seçim 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ı iteratif olarak inceleyebilir, her sütunun veri türünü belirleyebilir, verileri bir sütundan 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 bir gözlemci nesnesinde yöntemleri tetikler veya her ikisini de yapar.
Not: Sağlayıcı, sorguyu yapan nesnenin niteliğine göre sütunlara erişimi kısıtlayabilir. Örneğin, Kişiler Sağlayıcı, bazı sütunların senkronizasyon bağdaştırıcılarına erişimini kısıtlayarak bunları bir etkinliğe veya hizmete döndürmez.
Seçim ölçütleriyle eşleşen satır yoksa sağlayıcı, Cursor.getCount()
değerinin 0 olduğu (yani boş bir imleç) bir Cursor
nesnesi döndürür.
Dahili bir hata oluşursa sorgunun sonuçları ilgili sağlayıcıya bağlıdır. 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, SimpleCursorAdapter
kullanarak Cursor
'ü ListView
'a bağlamaktır.
Aşağıdaki snippet, önceki snippet'teki koda devam etmektedir. Sorgu tarafından alınan Cursor
öğesini içeren bir SimpleCursorAdapter
nesnesi oluşturur ve bu nesneyi bir 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 ListView
değerini Cursor
ile desteklemek için imlecin _ID
adlı bir sütun içermesi gerekir.
Bu nedenle, daha önce gösterilen sorgu, ListView
tablosunda görünmemesine rağmen Words
tablosunun _ID
sütununu alır.
Bu kısıtlama, çoğu sağlayıcının tablolarının her biri için _ID
sütunu olmasının nedenini de açıklar.
Sorgu sonuçlarından veri alma
Sorgu sonuçlarını görüntülemenin yanı sıra başka görevler için de kullanabilirsiniz. Örneğin, kullanıcı sözlüğü sağlayıcısından alınan yazım denetimi sonuçlarını diğer sağlayıcılarda arayabilirsiniz. Bunu yapmak için aşağıdaki örnekte gösterildiği gibi Cursor
içindeki satırları iterasyonla gezersiniz:
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ürleri almak için çeşitli "get" yöntemleri içerir. Örneğin, önceki snippet'te getString()
kullanılmaktadır. Ayrıca, sütunun veri türünü belirten bir değer döndüren getType()
yöntemine de sahiptirler.
Sorgu sonucu kaynaklarını serbest bırakın
Artık ihtiyaç duyulmayan Cursor
nesneleri, ilişkili kaynakların daha erken serbest bırakılması için kapatılmalıdır. Bu işlem, close()
çağrılarak veya Java programlama dilinde bir try-with-resources
ifadesi ya da Kotlin programlama dilinde use()
işlevi kullanılarak yapılabilir.
İçerik sağlayıcı izinleri
Sağlayıcının uygulaması, diğer uygulamaların sağlayıcının verilerine erişmek için sahip olması gereken izinleri belirtebilir. Bu izinler, kullanıcının bir uygulamanın hangi verilere erişmeye çalıştığı Diğer uygulamalar, sağlayıcının şartlarına göre sağlayıcıya erişmek için ihtiyaç duydukları izinleri ister. Son kullanıcılar uygulamayı yüklerken istenen izinleri görür.
Bir sağlayıcının uygulamasında herhangi bir izin belirtilmemişse 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özlükten veri almak için android.permission.READ_USER_DICTIONARY
iznine ihtiyaç duyar.
Sağlayıcının, veri ekleme, güncelleme veya silme için ayrı bir android.permission.WRITE_USER_DICTIONARY
izni vardır.
Bir uygulama, sağlayıcıya erişmek için gereken izinleri almak amacıyla manifest dosyasında <uses-permission>
öğesi ile sağlayıcıdan izin istiyor. Android Paket Yöneticisi uygulamayı yüklerken kullanıcının, uygulamanın istediği tüm izinleri onaylaması gerekir. Kullanıcı bunları onaylarsa Paket Yöneticisi yüklemeye devam eder. Kullanıcı bunları onaylamıyorsa Paket Yöneticisi kurulumu 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
Verileri bir sağlayıcıdan aldığınız gibi, verileri değiştirmek için de sağlayıcı istemcisi ile sağlayıcının ContentProvider
arasındaki etkileşimi kullanırsınız.
Karşılık gelen ContentProvider
yöntemine iletilen bağımsız değişkenlerle bir ContentResolver
yöntemini çağırırsınız. Sağlayıcı ve sağlayıcı istemcisi, güvenlik ve işlemler arası iletişimi otomatik olarak yönetir.
Veri ekleme
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, yeni bir kelimenin Kullanıcı Sözlük Sağlayıcısı'na nasıl 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ırın verileri, tek satırlık bir imlece benzer şekilde tek bir ContentValues
nesnesine gider. Bu nesnenin sütunlarını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.
Önceki snippet, _ID
sütununu eklemez çünkü bu sütun otomatik olarak yönetilir. Sağlayıcı, eklenen her satıra _ID
değerini 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
değerinin içeriğidir.
Çoğu sağlayıcı, bu içerik URI biçimini otomatik olarak algılayabilir ve ardından istenen işlemi söz konusu satırda gerçekleştirebilir.
Döndürülen Uri
değerinden _ID
değerini almak için ContentUris.parseId()
işlevini çağırın.
Verileri güncelleme
Bir satırı güncellemek için, ekleme işleminde olduğu gibi güncellenmiş değerleri içeren bir ContentValues
nesnesi ve sorgu işleminde olduğu gibi seçim ölçütleri 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"
olan tüm satırların yerel ayarını null
olarak değiştirir. Döndürülen değer, güncellenen satırların 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()
işlevini çağırırken kullanıcı girişini temizleyin. Bu konu hakkında daha fazla bilgi edinmek için Kötü amaçlı girişlere karşı koruma bölümünü okuyun.
Verileri sil
Satır silmek, satır verilerini almaya benzer. Silmek istediğiniz satırlar için seçim ölçütlerini siz belirtirsiniz ve istemci yöntemi, silinen satırların 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ırların 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()
işlevini çağırırken kullanıcı girişini temizleyin. Bu konu hakkında 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ı yalnızca metin sunar ancak sağlayıcılar aşağıdaki biçimleri de sunabilir:
- Tam sayı
- uzun tam sayı (long)
- 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 ikili büyük nesnedir (BLOB). Mevcut veri türlerini Cursor
sınıfının "get" yöntemlerine bakarak görebilirsiniz.
Bir sağlayıcıdaki her sütunun veri türü genellikle dokümanlarında listelenir.
Kullanıcı Sözlük Sağlayıcısı'na ait 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çıklanmaktadır.
Veri türünü Cursor.getType()
çağrısını kullanarak 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şleyemeyeceğini öğrenmek veya MIME türüne göre bir işleme türü seçmek için MIME türü bilgilerini kullanabilirsiniz. Genellikle karmaşık veri yapıları veya dosyaları içeren bir sağlayıcıyla çalışırken MIME türüne ihtiyacınız olur.
Örneğin, Kişi Sağlayıcı'daki ContactsContract.Data
tablosu, her satırda depolanan iletişim verilerinin türünü etiketlemek için MIME türlerini kullanır. Bir içerik URI'sine karşılık gelen MIME türünü almak için ContentResolver.getType()
işlevini çağırı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şim biçimleri
Uygulama geliştirmede önemli olan üç alternatif sağlayıcı erişimi biçimi vardır:
-
Toplu erişim:
ContentProviderOperation
sınıfındaki yöntemlerle bir erişim çağrısı grubu oluşturabilir ve bunlarıContentResolver.applyBatch()
ile uygulayabilirsiniz. -
Eşzamansız sorgular: Sorguları ayrı bir mesaj dizisinde yapın.
CursorLoader
nesnesi kullanabilirsiniz. Yükleyiciler kılavuzundaki örneklerde bunun nasıl yapılacağı gösterilmektedir. - Intent'leri kullanarak veri erişimi: Doğrudan bir sağlayıcıya intent gönderemezsiniz ancak sağlayıcının verilerini değiştirmek için genellikle en iyi donanıma sahip olan sağlayıcının uygulamasına intent gönderebilirsiniz.
Toplu erişim ve intent kullanarak değiştirme işlemi 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ındaki birden fazla tabloya satır eklemek ve genel olarak işlem sınırları içinde bir dizi işlem gerçekleştirmek (atomik işlem) açısından kullanışlıdır.
Bir sağlayıcıya toplu modda erişmek için ContentProviderOperation
nesnesi dizisi oluşturun ve ardından bu nesneleri 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 iletirsiniz.
Bu sayede dizideki her ContentProviderOperation
nesnesi farklı bir tabloda çalışır. ContentResolver.applyBatch()
çağrısı bir sonuç dizisi döndürür.
ContactsContract.RawContacts
sözleşme sınıfının açıklamasında, toplu eklemeyi gösteren bir kod snippet'i bulunur.
Intent'leri kullanarak veri erişimi
Intent'ler, içerik sağlayıcıya dolaylı erişim sağlayabilir. Uygulamanızda erişim izinleri olmasa bile, izinleri olan bir uygulamadan sonuç intent'i alarak veya izinleri olan bir uygulamayı etkinleştirip kullanıcının bu uygulamada işlem yapmasına izin vererek kullanıcının bir sağlayıcıdaki verilere erişmesine izin verebilirsiniz.
Geçici izinlerle erişim elde etme
Uygun erişim izinlerine sahip olmasanız bile, gerekli izinlere sahip bir uygulamaya intent göndererek ve URI izinleri içeren bir sonuç niyetini geri alarak içerik sağlayıcılardaki verilere erişebilirsiniz. Bunlar, belirli bir içerik URI'si için, bu URI'yi alan etkinlik tamamlanana kadar geçerli olan izinlerdir. Kalıcı izinlere sahip uygulama, sonuç amacıyla 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'nin kendisinedir.
Başka bir uygulamaya içerik URI'leri gönderirken bu işaretlerden en az birini ekleyin. İşaretler, intent alan ve Android 11 (API düzeyi 30) veya sonraki sürümleri hedefleyen tüm uygulamalara aşağıdaki özellikleri sağlar:
- Intent'e dahil edilen işarete bağlı olarak içerik URI'sinin temsil ettiği verileri okuma veya bu verilere yazma
- URI yetkilisiyle eşleşen içerik sağlayıcıyı içeren uygulamada paket görünürlüğü elde edin. Amacı gönderen uygulama ve içerik sağlayıcıyı içeren uygulama iki farklı uygulama olabilir.
Bir sağlayıcı, manifest dosyasında içerik URI'leri için URI izinlerini tanımlarken <provider>
öğesinin android:grantUriPermissions
özelliğinin yanı sıra <provider>
öğesinin alt öğesini de <grant-uri-permission>
kullanır. URI izinleri mekanizması, Android'de İzinler kılavuzunda daha ayrıntılı olarak açıklanmıştır.
Örneğin, READ_CONTACTS
izniniz olmasa bile Kişiler Sağlayıcı'daki bir kişinin verilerini alabilirsiniz. Bunu, bir kişiye doğum gününde e-posta tebriki gönderen bir uygulamada yapabilirsiniz. Kullanıcının tüm kişilerine ve bilgilerine erişmenizi sağlayan READ_CONTACTS
iznini istemek yerine, uygulamanızın hangi kişileri kullanacağını kullanıcının kontrol etmesine izin verin. Bunun için aşağıdaki süreci uygulayın:
-
Uygulamanızda,
startActivityForResult()
yöntemini kullanarakACTION_PICK
işlemini ve "contacts" MIME türünüCONTENT_ITEM_TYPE
içeren bir intent gönderin. - Bu intent, Kişiler uygulamasının "seçim" etkinliğinin intent filtresiyle eşleştiği için etkinlik öne çıkar.
-
Seçim etkinliğinde kullanıcı, güncellenecek bir kişiyi seçer. Bu durumda seçim etkinliği, uygulamanıza geri vermek için bir intent oluşturmak üzere
setResult(resultcode, intent)
çağrısında bulunur. Intent, kullanıcının seçtiği kişinin içerik URI'sini ve "ekstralar" işaretleriniFLAG_GRANT_READ_URI_PERMISSION
içerir. Bu işaretler, içerik URI'si tarafından işaret edilen kişinin verilerini okuması için uygulamanıza URI izni verir. Ardından seçim etkinliği, kontrolü uygulamanıza döndürmek içinfinish()
'ü çağırır. -
Etkinliğiniz ön plana geri 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ç intent'inden alınan içerik URI'si sayesinde, manifest'inizde sağlayıcıya kalıcı okuma erişimi izni istememiş olsanız bile Kişiler Sağlayıcı'dan kişinin verilerini okuyabilirsiniz. Ardından, kişinin doğum günü bilgilerini veya e-posta adresini alıp e-tebrik gönderebilirsiniz.
Başka bir uygulama kullan
Erişim izinlerinizin olmadığı verileri kullanıcının değiştirmesine izin vermenin bir başka yolu da, izinleri olan bir uygulamayı etkinleştirip kullanıcının bu uygulamada çalışmasını sağlamaktır.
Örneğin, Takvim uygulaması, uygulamanın ekleme kullanıcı arayüzünü etkinleştirmenizi sağlayan bir ACTION_INSERT
amacını kabul eder. Bu intent'e, uygulamanın kullanıcı arayüzünü önceden doldurmak için kullandığı "extras" verilerini iletebilirsiniz. Tekrarlanan etkinlikler karmaşık bir söz dizimi içerdiğinden, takvim sağlayıcısına etkinlik eklemenin tercih edilen yolu, takvim uygulamasını bir ACTION_INSERT
ile etkinleştirip kullanıcının etkinliği oraya eklemesine izin vermektir.
Yardımcı uygulama kullanarak verileri görüntüleme
Uygulamanız erişim izinlerine sahip olsa bile başka bir uygulamada veri görüntülemek için intent kullanabilirsiniz. Örneğin, Takvim uygulaması belirli bir tarihi veya etkinliği gösteren bir ACTION_VIEW
intent'i kabul eder.
Bu sayede, kendi kullanıcı arayüzünüzü oluşturmak zorunda kalmadan takvim bilgilerini görüntüleyebilirsiniz.
Bu özellik hakkında daha fazla bilgi edinmek için Takvim sağlayıcıya genel bakış başlıklı makaleyi inceleyin.
Intent'i gönderdiğiniz uygulamanın, sağlayıcıyla ilişkili uygulama olması gerekmez. Örneğin, Kişi Sağlayıcı'dan bir kişiyi alıp ardından bir resim görüntüleyiciye kişinin resmine ait içerik URI'sini içeren bir ACTION_VIEW
niyeti gönderebilirsiniz.
İlişkili 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 sabit değerleri tanımlar. Sözleşme sınıfları, sağlayıcıya 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 edilen sağlayıcıların çoğu, android.provider
paketinde karşılık gelen sözleşme sınıflarına sahiptir.
Örneğin, Kullanıcı Sözlüğü Sağlayıcısı, içerik URI'si ve sütun adı sabitlerini içeren bir sözleşme sınıfına UserDictionary
sahiptir. Words
tablosunun içerik URI'si UserDictionary.Words.CONTENT_URI
sabitinde tanımlanır.
UserDictionary.Words
sınıfı, bu kılavuzdaki örnek snippet'lerde kullanılan sütun adı sabitlerini 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 };
Kişiler sağlayıcısı için ContactsContract
adlı başka bir sözleşme sınıfı vardır.
Bu sınıfın referans dokümanları örnek kod snippet'leri içerir. 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, bilinen MIME türü text/html
, text
türüne ve html
alt türüne sahiptir. Sağlayıcının URI için bu türü döndürmesi, bu URI'yı kullanan sorgunun HTML etiketleri içeren metin döndürdüğü anlamına gelir.
Tedarikçiye özgü MIME türleri olarak da adlandırılan özel MIME türü dizelerinde daha karmaşık type ve subtype değerleri bulunur. Birden fazla 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 şu olur:
vnd.android.cursor.item
subtype, sağlayıcıya özgüdür. Android'in yerleşik sağlayıcıları genellikle basit bir alt türe sahiptir. Örneğin, Kişiler uygulaması bir telefon numarası için 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 yetkilisine ve tablo adlarına göre kendi alt tür kalıplarını oluşturabilir. Örneğin, tren tarifeleri içeren bir sağlayıcıyı düşünün.
Sağlayıcının yetkisi com.example.trains
'tür ve Satır1, Satır2 ve Satır3 tablolarını içerir. Satır1 tablosunun aşağıdaki içerik URI'sine yanıt olarak:
content://com.example.trains/Line1
Sağlayıcı aşağıdaki MIME türünü döndürür:
vnd.android.cursor.dir/vnd.example.line1
Line2 tablosundaki 5. satır için aşağıdaki içerik URI'sine yanıt olarak:
content://com.example.trains/Line2/5
Sağlayıcı aşağıdaki 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ı sabitleri tanımlar. Örneğin, Kişi Sağlayıcı sözleşme sınıfı ContactsContract.RawContacts
, tek bir ham iletişim satırının MIME türü için sabit CONTENT_ITEM_TYPE
değerini tanımlar.
Tek satırlar için İçerik URI'leri İçerik URI'leri bölümünde açıklanmıştır.