İçerik sağlayıcı, merkezi bir veri deposuna erişimi yönetir. Sağlayıcı Android uygulamasının bir parçasıdır. Bu uygulama genellikle bahsedeceğim. Bununla birlikte, içerik sağlayıcılar öncelikli olarak diğer Bunlar, sağlayıcıya bir sağlayıcı istemci nesnesi aracılığıyla erişen uygulamalardır. Sağlayıcılar birlikte ve sağlayıcı müşterileri, veri işlemeyi sağlayan tutarlı, standart bir arayüz sunar. güvenli veri erişimi sunar.
İçerik sağlayıcılarla genellikle şu iki senaryodan biriyle çalışırsınız: başka bir uygulamada mevcut bir içerik sağlayıcıya erişmek için kullanılacak kod uygulamanıza yeni bir içerik sağlayıcı ekleyebilir ve mevcut verileri diğer uygulamalarla paylaşabilirsiniz.
Bu sayfa mevcut içerik sağlayıcılarla çalışmanın temellerini ele alır. Proje başlatma belgesini içerik sağlayıcılara göz atmak için İçerik sağlayıcı oluşturun.
Bu konuda aşağıdakiler açıklanmaktadır:
- İçerik sağlayıcıların işleyiş şekli.
- İçerik sağlayıcıdan veri almak için kullandığınız API.
- İç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ı, harici uygulamalara verileri bir veya daha fazla tablo halinde sunar. ilişkisel veritabanında bulunan tablolara benzerdir. Satır, belirli bir türdeki örneği temsil eder temsil eder ve satırdaki her sütun tek bir veri parçasını temsil eder veri toplanmasını sağlar.
Bir içerik sağlayıcı, ve bileşenlerin sayısını artırır. Şekil 1'de gösterildiği gibi, bu özellikler aşağıdakileri içerir:
- Uygulama verilerinize erişimi diğer uygulamalarla paylaşma
- Widget'a veri gönderme
- Arama üzerinden uygulamanız için özel arama önerileri döndürme
SearchRecentSuggestionsProvider
kullanan çerçeve - Sunucunuzla uygulama verilerini,
AbstractThreadedSyncAdapter
. CursorLoader
kullanarak kullanıcı arayüzünüze veri yükleme
![İçerik sağlayıcı ile diğer bileşenler arasındaki ilişki.](https://developer.android.com/static/guide/topics/providers/images/content-provider-tech-stack.png?authuser=9&hl=tr)
Şekil 1. İçerik sağlayıcı ile diğer bileşenler arasındaki ilişki.
Sağlayıcıya erişme
Bir içerik sağlayıcıdaki verilere erişmek istediğinizde,
ContentResolver
nesne
Context
. İlgili içeriği oluşturmak için kullanılan
ContentResolver
nesnesi, sağlayıcı nesnesiyle iletişim kurar ve
ContentProvider
uygulayan bir sınıfın örneği.
Sağlayıcı
nesne, istemcilerden veri isteklerini alır, istenen işlemi gerçekleştirir ve
sonuç. Bu nesne, sağlayıcı nesnesinde aynı şekilde adlandırılmış yöntemleri çağıran yöntemler içeriyor.
ContentProvider
somut alt sınıflarından birinin örneği. İlgili içeriği oluşturmak için kullanılan
ContentResolver
yöntemleri,
"CRUD" (oluşturma, alma, güncelleme ve silme) işlevleri sunar.
Kullanıcı arayüzünden bir ContentProvider
öğesine erişmek için sık kullanılan bir kalıp
Arka planda eşzamansız sorgu çalıştırmak için CursorLoader
. İlgili içeriği oluşturmak için kullanılan
Kullanıcı arayüzündeki Activity
veya Fragment
, a
Sorguya CursorLoader
ekleyin. Bu da
ContentProvider
, ContentResolver
kullanıyor.
Bu sayede, sorgu çalışırken kullanıcı arayüzü kullanılabilir olmaya devam eder. Bu desen, birkaç farklı nesnenin ve aynı zamanda altta yatan öğelerin depolama mekanizmasına yerleştirin.
![ContentProvider, diğer sınıflar ve depolama arasındaki etkileşim.](https://developer.android.com/static/guide/topics/providers/images/content-provider-interaction.png?authuser=9&hl=tr)
Şekil 2. 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 belirli bir sağlayıcıyı talep etmesi gerekir izinlerini bildirmelidir. Bu geliştirme kalıbı İçerik sağlayıcı izinleri bölümü.
Android platformundaki yerleşik sağlayıcılardan biri de kullanıcı sözlüğü sağlayıcısıdır. Kullanıcının saklamak istediği standart olmayan kelimeleri depolar. Tablo 1, projenin veriler, bu sağlayıcının tablosunda aşağıdaki gibi görünebilir:
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 | fr_FR | 2 |
applet |
kullanıcı2 | 225 | tr_TR | 3 |
const |
kullanici1 | 255 | pt_BR | 4 |
int |
kullanıcı5 | 100 | tr_TR | 5 |
1. tabloda her satır,
standart bir sözlükte bulunabilir. Her sütun, o kelime için bir veri parçasını temsil eder; örneğin,
ilk karşılaştığı yer. Sütun başlıkları,
sağlayıcıdır. Örneğin, bir satırın yerel ayarına referans vermek için satırın locale
sütununa başvurursunuz. Örneğin,
_ID
sütunu, Google Analytics 4'te veri gönderen bir birincil anahtar sütunu
otomatik olarak sağlar.
Kullanıcı Sözlüğü Sağlayıcısı'ndan kelimelerin ve yerel ayarlarının listesini almak için
ContentResolver.query()
adlı kişiyi arayabilirsiniz.
query()
yöntemi
ContentProvider.query()
yöntemi
Kullanıcı Sözlüğü Sağlayıcısı. Aşağıdaki kod satırlarında gösterilen
ContentResolver.query()
sesli arama:
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, Arkadaş Bitkiler projesinin
query(Uri,projection,selection,selectionArgs,sortOrder)
, SQL SELECT ifadesiyle eşleşiyor:
Tablo 2: SQL sorgusu ile karşılaştırıldığında query()
.
query() bağımsız değişken |
SELECT anahtar kelime/parametre | Notlar |
---|---|---|
Uri |
FROM table_name |
Uri , table_name adlı sağlayıcıdaki tabloyla eşleniyor. |
projection |
col,col,col,... |
projection , her satır için dahil edilen bir sütun dizisidir
alındı.
|
selection |
WHERE col = value |
selection , satır seçiminde kullanılacak ölçütleri belirtir. |
selectionArgs |
Tam olarak eşdeğeri yoktur. Seçilen bağımsız değişkenler ?
seçim ifadesi.
|
|
sortOrder |
ORDER BY col,col,... |
sortOrder , satırların döndürülen
Cursor .
|
İçerik URI'leri
İçerik URI'si, bir sağlayıcıdaki verileri tanımlayan bir URI'dir. İçerik URI'leri Tüm sağlayıcının (otoritesinin) sembolik adını ve bir bir tabloya (yol) işaret eden adlar girin. Aradığınızda bir istemci yöntemi kullanıyorsanız tablonun içerik URI'si bağımsız değişkendir.
Önceki kod satırlarında sabit değer
CONTENT_URI
, şunun içerik URI'sini barındırıyor:
Kullanıcı Sözlüğü Sağlayıcısı'nın Words
tablosu. ContentResolver
nesne URI'nin yetkilisini ayrıştırır ve bunu sağlayıcıyı aşağıdakine göre çözmek için kullanır:
bilinen sağlayıcıların yer aldığı bir sistem tablosuyla karşılaştırma. İlgili içeriği oluşturmak için kullanılan
ContentResolver
, daha sonra sorgu bağımsız değişkenlerini doğru
sağlar.
ContentProvider
,
tabloya erişebilirsiniz. Sağlayıcının genellikle sunduğu her tablo için bir yolu vardır.
Önceki kod satırlarında, Words
tablosunun tam URI'si şöyle olur:
content://user_dictionary/words
content://
dizesi, her zaman mevcut olan şemadır ve bunu bir içerik URI'si olarak tanımlar.user_dictionary
dizesi, sağlayıcının yetkilisidir.words
dizesi, tablonun yoludur.
Birçok sağlayıcı, kimlik değeri ekleyerek tablodaki tek bir satıra erişmenize olanak tanır
bulunur. Örneğin, _ID
değeri
4
kullanıyorsanız, ş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 kümesi alıp bunları güncellemek veya silmek istediğinizde genellikle kimlik değerlerini kullanırsınız bunlardan biri olabilir.
Not: Uri
ve Uri.Builder
sınıfları
, dizelerden iyi biçimlendirilmiş URI nesneleri oluşturmaya yönelik kolaylık yöntemleri içerir. İlgili içeriği oluşturmak için kullanılan
ContentUris
sınıfı, kimlik değerlerinin eklenmesi için kolaylık yöntemleri içeriyor:
URI'dır. Önceki snippet, Kullanıcı Sözlüğü Sağlayıcı içerik URI'sine kimlik eklemek için withAppendedId()
kodunu kullanıyordu.
Sağlayıcıdan veri alma
Bu bölümde, Kullanıcı Sözlüğü Sağlayıcısı kullanılarak bir sağlayıcıdan nasıl veri alınacağı açıklanmaktadır açıklayacağım.
Daha net açıklamak gerekirse, bu bölümdeki kod snippet'leri
Kullanıcı arayüzü iş parçacığında ContentResolver.query()
. İçinde
ancak gerçek kod, sorguları eşzamansız olarak ayrı bir iş parçacığında yapar. Şunları yapabilirsiniz:
aşağıda açıklanan CursorLoader
sınıfını kullanın:
daha ayrıntılı olarak
Yükleyiciler kılavuzu. Ayrıca, kod satırları yalnızca snippet'lerden oluşur. Tam bir
bir uygulamadır.
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 iste
Bir sağlayıcıdan veri almak için uygulamanızın
sağlar. Çalışma zamanında bu izni isteyemezsiniz. Bunun yerine,
<uses-permission>
.
öğesinin ve
sağlar.
Manifest'inizde bu öğeyi belirttiğinizde bunu istemiş olursunuz ve izin vermiş olursunuz. Kullanıcılar uygulamanızı yüklediklerinde, arka arkaya isteyeceğim.
Kullandığınız sağlayıcıya ait okuma erişimi izninin tam adını da öğrenmek için diğer erişim izinlerinin adları arasında geçiş yapmak için sağlayıcının belgelerinden faydalanabilirsiniz.
Sağlayıcılara erişimde izinlerin rolü İçerik sağlayıcı izinleri bölümü.
Söz konusu izni Kullanıcı Sözlüğü Sağlayıcısı tanımlar
android.permission.READ_USER_DICTIONARY
ekler. Bu nedenle,
sağlayıcıdan okumak isteyen uygulamanın bu izni istemesi gerekir.
Sorguyu oluşturma
Bir sağlayıcıdan veri almanın 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 = {""};
Sonraki snippet,
ContentResolver.query()
(Kullanıcı Sözlüğü kullanılarak)
Örneğin, Provider (Sağlayıcı) Sağlayıcı istemci sorgusu, SQL sorgusuna benzer ve
döndürülecek sütun kümesi, bir seçim ölçütü kümesi ve sıralama düzeni.
Sorgunun döndürdüğü sütun kümesine projeksiyon adı verilir ve
değişken mProjection
.
Alınacak satırları belirten ifade, seçim tümcesine bölünür ve
seçim bağımsız değişkenleri. Seçim yan tümcesi, mantıksal ve boole ifadelerinin birleşiminden oluşur.
sütun adlarını ve değerleri görebilirsiniz. Değişken mSelectionClause
. Örneğin
değiştirilebilir parametre olan ?
, sorgu yöntemi kullanılarak
mSelectionArgs
değişkeni olan seçim bağımsız değişkenleri dizisinden.
Sonraki snippet'te kullanıcı bir kelime girmezse seçim ifadesi
null
ve sorgu, sağlayıcıdaki tüm kelimeleri döndürür. Kullanıcı giriş yaparsa
anahtar kelime için 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 deyimine 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şlere karşı koru
İçerik sağlayıcı tarafından yönetilen veriler, güvenilir olmayan harici kaynaklar dahil olmak üzere bir SQL veritabanındaysa verilerin ham SQL ifadelerine yüklenmesi SQL yerleştirmeye yol açabilir.
Şu seçim deyimini göz önünde bulundurun:
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ı "nothing; TABLO AÇILIR *;" Bu, mUserInput
için
sonuç, var = nothing; DROP TABLE *;
seçim ifadesiyle sonuçlanır.
seçim yan tümcesi bir SQL deyimi olarak kabul edilir; bu, sağlayıcının tüm anahtar kelimeleri sağlayıcı yakalayacak şekilde ayarlanmadığı sürece, temel SQLite veritabanındaki SQL yerleştirme denemeleri.
Bu sorunu önlemek için, değiştirilebilir öğe olarak ?
kullanan bir seçim ifadesi kullanın
parametresini kullanabilirsiniz. Bu şekilde, kullanıcı
bir SQL ifadesinin parçası olarak yorumlanmak yerine doğrudan sorguya bağlıdır.
SQL olarak işlenmediğinden, kullanıcı girişi kötü amaçlı SQL yerleştiremez. Bunun yerine
birleştirmeyi kullanıcı girişini dahil etmek için kullanın, ş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;
Değiştirilebilir parametre olarak ?
kullanan bir seçim ifadesi ve
seçim bağımsız değişkenleri dizisi, sağlayıcı her zaman geçerli olmasa bile bir seçimi belirtmek için
nasıl çalıştıracağınızı öğreneceksiniz.
Sorgu sonuçlarını görüntüle
ContentResolver.query()
istemci yöntemi her zaman
sorgunun etiketi tarafından belirtilen sütunları içeren bir Cursor
sorgunun seçim ölçütüyle eşleşen satırlar için projeksiyon. CEVAP
Cursor
nesnesi, içerdiği satır ve sütunlara rastgele okuma erişimi sağlar
içerir.
Cursor
yöntemlerini kullanarak
sonuçlarını incelemeli, her sütunun veri türünü belirleme, verileri bir sütundan çıkarma ve diğer sütunları
özelliklerini ekler.
Bazı Cursor
uygulamaları otomatik olarak
sağlayıcının verileri değiştiğinde nesneyi güncelleme, gözlemci nesnesinde yöntemleri tetikleme
(Cursor
veya her ikisi de değiştiğinde)
Not: Sağlayıcı, nesneden ibaret değildir. Örneğin, Kişi Sağlayıcı bazı sütunların erişimini senkronizasyon bağdaştırıcılarını bir etkinlik veya hizmete döndürmez.
Seçim ölçütleriyle eşleşen satır yoksa sağlayıcı
Cursor
nesnesini döndürür
Cursor.getCount()
0 - diğer bir deyişle, boş bir imleç.
Dahili bir hata oluşursa sorgunun sonuçları ilgili sağlayıcıya bağlıdır. Projenin
null
hatasını döndürür, yoksa Exception
hatası verebilir.
Cursor
bir satır listesi olduğundan,
bir Cursor
öğesinin içeriği, onu bir ListView
SimpleCursorAdapter
kullanarak.
Aşağıdaki snippet, önceki snippet'teki kodu devam ettirir. Bu,
Cursor
içeren SimpleCursorAdapter
nesne
sorgu tarafından alınır ve bu nesneyi bir
ListView
.
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
öğesini
Cursor
, imleç _ID
adlı bir sütun içermelidir.
Bu nedenle, daha önce gösterilen sorgu_ID
Words
tablosunu ListView
göstermese bile.
Bu kısıtlama, çoğu sağlayıcının her bir veri için neden bir _ID
sütunu
nasıl hazırlanabileceğini.
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,
Örneğin, Kullanıcı Sözlüğü Sağlayıcı'dan yazımları getirebilir ve daha sonra,
diğer sağlayıcılar. Bunu yapmak için, aşağıdaki örnekte gösterildiği gibi Cursor
içindeki satırlar üzerinde yineleme yaparsınız:
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ı birkaç "get" içeriyor yöntemleri
veri almanın başka yolları da var. Örneğin, önceki snippet'te
getString()
kullanır. Ayrıca,
getType()
yöntemi,
sütunun veri türünü belirtir.
İçerik sağlayıcı izinleri
Bir sağlayıcının uygulaması, diğer uygulamaların sahip olması gereken izinleri belirtebilir ve sağlayıcının verilerine erişebilir. Bu izinler, kullanıcının hangi verileri emin olun. Sağlayıcının gereksinimlerine bağlı olarak diğer uygulamalar Sağlayıcıya erişmek için ihtiyaç duydukları izinleri isteme. Son kullanıcılar istenen izin vermiş olursunuz.
Bir sağlayıcının uygulaması herhangi bir izin belirtmezse diğer uygulamaların sağlayıcı dışa aktarılmadığı sürece sağlayıcının verilerine erişemez. Ayrıca bileşenler bağlantısından bağımsız olarak her zaman tam okuma ve yazma erişimine izin verilmez.
Kullanıcı Sözlüğü Sağlayıcısı,
android.permission.READ_USER_DICTIONARY
içinden veri alma izni.
Sağlayıcının ayrı bir android.permission.WRITE_USER_DICTIONARY
veri ekleme, güncelleme veya silme izni.
Bir uygulama, bir sağlayıcıya erişmek için gereken izinleri almak amacıyla onlardan
<uses-permission>
.
öğesine sahip olmayabilir. Android Paket Yöneticisi uygulamayı yüklediğinde, kullanıcı
uygulamanın istediği tüm izinleri onaylamalıdır. Kullanıcı onaylarsa
Paket Yöneticisi, yükleme işlemine devam eder. Kullanıcı bunları onaylamazsa Paket Yöneticisi
yükleme işlemini durdurur.
Aşağıdaki örnek
<uses-permission>
.
öğesi, Kullanıcı Sözlüğü Sağlayıcısı'na okuma erişimi ister:
<uses-permission android:name="android.permission.READ_USER_DICTIONARY">
İzinlerin sağlayıcı erişimi üzerindeki etkisi şu makalede daha ayrıntılı olarak açıklanmıştır: Güvenlik ipuçları.
Veri ekleme, güncelleme ve silme
Bir sağlayıcıdan veri aldığınız gibi Google Analytics 360 ve
verileri değiştirmek için sağlayıcı müşterisi ve sağlayıcının ContentProvider
.
Şunlara aktarılan bağımsız değişkenlerle bir ContentResolver
yöntemini çağırıyorsunuz:
karşılık gelen ContentProvider
yöntemini kullanır. Sağlayıcı ve sağlayıcı
ve işlemler arası iletişimi otomatik olarak yönetir.
Veri ekle
Bir sağlayıcıya veri eklemek için
ContentResolver.insert()
.
yöntemidir. 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üğü 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ıra ilişkin veriler tek bir ContentValues
nesnesine yerleştirilir. Bu nesne,
tek satırlık bir imlece benzer. Bu nesnedeki sütunların,
hiçbir değer belirtmek istemiyorsanız bunun yerine bir sütun ayarlayabilirsiniz.
ContentValues.putNull()
kullanarak null
adresine.
Önceki snippet, _ID
sütununu eklemiyor, çünkü bu sütun korunuyor
otomatik olarak oluşturur. Sağlayıcı,_ID
eklendi. Sağlayıcılar genellikle bu değeri tablonun birincil anahtarı olarak kullanır.
newUri
işlevinde döndürülen içerik URI'si,
şu biçimdedir:
content://user_dictionary/words/<id_value>
<id_value>
, yeni satırda _ID
sütununun içeriğidir.
Çoğu sağlayıcı bu içerik URI'si biçimini otomatik olarak algılar ve daha sonra istenen
aynı satır üzerinde işlem yapabilirsiniz.
Döndürülen Uri
öğesinden _ID
değerini almak için şunu çağırın:
ContentUris.parseId()
.
Verileri güncelle
Bir satırı güncellemek için güncellenmiş bir ContentValues
nesnesi kullanın
değerleri ekleyin.
Kullandığınız istemci yöntemi
ContentResolver.update()
Yalnızca eklemeniz gereken
değerlerini, güncellediğiniz sütunlar için ContentValues
nesnesine ekleyin. Şu durumda:
bir sütunun içeriğini temizlemek istiyorsanız değeri null
olarak ayarlayın.
Aşağıdaki snippet, yerel ayarı "en"
diline sahip olan tüm satırları
yerel ayarı null
. 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 );
Telefon ettiğinizde kullanıcı girişini temizleyin
ContentResolver.update()
Şu 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. Satırlar için seçim ölçütlerini belirtirsiniz
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ı.
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 );
Telefon ettiğinizde kullanıcı girişini temizleyin
ContentResolver.delete()
Şu 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ısı yalnızca metinle beraber, 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 baytlık dizi.
Cursor
sınıfı "get" yöntemlerine göz atın.
Bir sağlayıcıdaki her sütunun veri türü genellikle sağlayıcının belgelerinde listelenir.
Kullanıcı Sözlük Sağlayıcısı'na ait veri türleri, referans dokümanlarda listelenmiştir
UserDictionary.Words
. Sözleşmeli sınıflar
Sözleşmeli sınıflar bölümünde açıklanmıştır.
Veri türünü, Cursor.getType()
işlevini ç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. Şunları yapabilirsiniz: uygulamanızın sağlayıcı tarafından sunulan veya MIME türüne göre işleme türü seçilebilir. Genellikle MIME türü: Karmaşık bir MIME türü olabilir.
Örneğin, ContactsContract.Data
Kişiler Sağlayıcısı tablosunda bulunan tablo, her bir sağlayıcıda depolanan kişi verilerinin türünü etiketlemek için MIME türlerini kullanır
satırı. İçerik URI'sine karşılık gelen MIME türünü almak için
ContentResolver.getType()
MIME türü referansı bölümünde hem standart hem de özel MIME türlerinin söz dizimini destekler.
Alternatif sağlayıcı erişimi biçimleri
Uygulama geliştirmede üç alternatif sağlayıcı erişimi biçimi önemlidir:
-
Toplu erişim: Aşağıdaki yöntemlerle bir grup erişim çağrısı oluşturabilirsiniz:
ContentProviderOperation
sınıfını kullanmak ve ardındanContentResolver.applyBatch()
. -
Eşzamansız sorgular: Sorguları ayrı bir iş parçacığında yapın. Şunları yapabilirsiniz:
CursorLoader
nesnesi kullanın. Bu bölümdeki örnekler Yükleyiciler kılavuzu gösterimi bunu nasıl yapacağınızı öğrenebilirsiniz. - Amaç kullanarak veri erişimi: Amaç gönderemeseniz bile doğrudan sağlayıcıya gönderirseniz sağlayıcının uygulamasına bir intent gönderebilirsiniz. verilerini değiştirmek için genellikle en iyi donanıma sahiptir.
Toplu erişim ve intent kullanarak değiştirme işlemi aşağıdaki bölümlerde açıklanmıştır.
Toplu erişim
Sağlayıcıya toplu erişim, çok sayıda satır eklemek için aynı yöntem çağrısında birden çok tablolarda yer alan satırlara ve genellikle İşlem olarak işlem sınırlarının ötesine geçen işlemler, atomik işlem olarak adlandırılır.
Bir sağlayıcıya toplu modda erişmek için
ContentProviderOperation
nesnelik bir dizi oluşturabilir ve ardından
bir içerik sağlayıcıya göndererek
ContentResolver.applyBatch()
. Geçerseniz
içerik sağlayıcının bu yöntem için yetkilendirmesi yapar.
Bu şekilde, dizideki her ContentProviderOperation
nesnesi çalışır
karşılaştırabilirsiniz. ContentResolver.applyBatch()
işlevine yapılan bir çağrı bir dizi sonuç 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. Kullanıcının erişmesine izin verebilirsiniz bir sağlayıcıdaki diğer verileri izinleri olan bir uygulamadan veya bir bir uygulamadır.
Geçici izinlerle erişim elde etme
Uygun erişiminiz olmasa bile bir içerik sağlayıcıdaki verilere erişebilirsiniz bu izinlere sahip olan bir uygulamaya intent göndererek URI izinleri içeren bir sonuç niyeti geri alma. Bunlar, alan adını alan etkinliğe kadar devam eden belirli bir içerik URI'sına yönelik izinlerdir. yardımcı olur. Kalıcı izinlere sahip olan uygulama geçici izin verir izinleri için sonuç amacında bir işaret ayarlayın:
-
Okuma izni:
FLAG_GRANT_READ_URI_PERMISSION
-
Yazma izni:
FLAG_GRANT_WRITE_URI_PERMISSION
Not: Bu flag'ler sağlayıcıya genel okuma veya yazma erişimi vermez yetkileri içerik URI'sinde bulunur. Erişim yalnızca URI'nın kendisi içindir.
Başka bir uygulamaya içerik URI'leri gönderirken aşağıdakilerden en az birini ekleyin işaretidir. İşaretler, alan adı alan tüm uygulamalara aşağıdaki özellikleri sağlar bir amaç türündeyse ve Android 11 (API düzeyi 30) veya sonraki sürümleri hedefliyorsa:
- İçerik URI'sinin temsil ettiği verilerden okuma veya yazma amaçlanan bayrağa göre değişir.
- Paketi kazan eşleşen içerik sağlayıcısını içeren uygulamanın görünürlüğünü URI yetkilisi. Amacı gönderen uygulama ve içerik sağlayıcı iki farklı uygulama olabilir.
Bir sağlayıcı,
android:grantUriPermissions
.
özelliğinin
<provider>
öğesinin yanı sıra
<grant-uri-permission>
alt öğesi
<provider>
öğesine dokunun. URI izinleri mekanizması bkz.
Android'de izinler rehberini inceleyin.
Örneğin, Kişi Sağlayıcı'da bir kişinin verilerini almasanız bile
READ_CONTACTS
iznine sahip olmanız gerekir. Şunu yapmak isteyebilirsiniz:
doğum günündeki kişiye e-selamlama gönderen bir uygulama içinde bunu yapabilirsiniz. Şunun yerine:
READ_CONTACTS
istiyor. Bu da size tüm
ve tüm bilgileri, kullanıcının hangi bilgileri
uygulamanızın kullandığı kişiler. Bunun için aşağıdaki işlemi uygulayın:
-
Uygulamanızda, işlemi içeren bir intent gönderin
ACTION_PICK
ve "kişiler" MIME türüCONTENT_ITEM_TYPE
, yöntemstartActivityForResult()
. - Bu intent, reklamverenin amaç filtresiyle eşleşir. Kişiler uygulamasının "seçimi" söz konusu etkinlik ön plana gelir.
-
Seçim etkinliğinde, kullanıcı bir
iletişim bilgilerini girin. Bu durumda seçim etkinliği
setResult(resultcode, intent)
. bir niyet oluşturabilirsiniz. Amaç, içerik URI'sini barındırır kullanıcının seçtiği kişi ve "ekstralar" bayraklarFLAG_GRANT_READ_URI_PERMISSION
Bu işaretler URI verir tarafından işaret edilen kişinin verilerini okuması için uygulama izninizin içerik URI'si. Ardından seçim etkinliği,finish()
öğesini çağırarak uygulamanıza dönün. -
Etkinliğiniz ön plana geri döner ve sistem, etkinliğinizin
onActivityResult()
. yöntemidir. Bu yöntem, uygulamasıdır. - Sonuç amacındaki içerik URI'si ile kişinin verilerini okuyabilirsiniz Kalıcı okuma erişimi izni istememiş olsanız bile Kişiler Sağlayıcısı'ndan manifest dosyanızdaki sağlayıcıya ekleyin. Ardından, kişinin doğum günü bilgilerini öğrenebilirsiniz veya e-posta adresine gidip e-selamlama mesajını gönderin.
Başka bir uygulama kullan
Kullanıcının erişim izninizin olmadığı verileri değiştirmesine olanak sağlamanın bir başka yolu da kullanıcının gerekli izinlere sahip bir uygulamayı etkinleştirmesini sağlar.
Örneğin, Takvim uygulaması
aşağıdakileri etkinleştirmenizi sağlayan ACTION_INSERT
intent'i içerir:
kullanıcı arayüzü ekleyin. "Ekstralar" uygulama bu amaca yönelik verileri
önceden doldurmak için kullanılır. Düzenli etkinlikler karmaşık bir söz dizimine sahip olduğundan tercih edilen
Etkinlikleri Takvim Sağlayıcısı'na eklemenin yolu, Takvim uygulamasını
ACTION_INSERT
'ı tıklayın ve kullanıcının etkinliği oraya eklemesine izin verin.
Yardımcı uygulama kullanarak verileri görüntüleyin
Uygulamanızın erişim izinleri varsa,
başka bir uygulamada veri görüntüleme niyetinde olmalıdır. Örneğin, Takvim uygulaması
Belirli bir tarihi veya etkinliği gösteren ACTION_VIEW
niyeti.
Bu, kendi kullanıcı arayüzünüzü oluşturmak zorunda kalmadan takvim bilgilerini görüntülemenizi sağlar.
Bu özellik hakkında daha fazla bilgi edinmek için
Takvim sağlayıcısına genel bakış.
Niyeti gönderdiğiniz uygulamanın, aynı uygulama tarafından
sağlayıcıyla ilişkilendirilebilir. Örneğin,
Sağlayıcı ile iletişime geçin, ardından bir ACTION_VIEW
niyeti gönderin
bir resim görüntüleyiciye kişinin resminin içerik URI'sını içerir.
Sözleşmeli sınıflar
Sözleşme sınıfı, uygulamaların içerik URI'leri ile çalışmasına yardımcı olan sabit değerleri tanımlar.
içerik sağlayıcının adları, amaç işlemleri ve diğer özellikleri. Sözleşmeli sınıflar
otomatik olarak eklenir. Bunları sağlayıcının geliştiricisi tanımlamalı ve daha sonra
diğer geliştiricilerin kullanımına sunun. Android'e dahil olan sağlayıcıların çoğu
platform için android.provider
paketinde ilgili sözleşme sınıfları bulunuyor.
Örneğin, Kullanıcı Sözlük Sağlayıcısı'nın bir sözleşme sınıfı vardır.
İçerik URI'si ve sütun adı sabitleri içeren UserDictionary
. İlgili içeriği oluşturmak için kullanılan
Words
tablosunun içerik URI'si sabit değerde tanımlanır
UserDictionary.Words.CONTENT_URI
.
UserDictionary.Words
sınıfı, sütun adı sabitlerini de içerir.
Bunlar bu kılavuzdaki örnek snippet'lerde kullanılır. Örneğin, bir sorgu projeksiyonu
şu şekilde tanımlanır:
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 };
Diğer bir sözleşme sınıfı ise Kişi Sağlayıcı için ContactsContract
.
Bu sınıfın referans belgeleri örnek kod snippet'lerini içerir. Bunlardan biri
alt sınıflar, ContactsContract.Intents.Insert
, bir sözleşmedir
amaç ve amaç verileri için sabit değerler içeren bir sınıftı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ünü seçin. Sağlayıcı, URI için bu türü döndürürse bu,
URI kullanılarak yapılan sorgu, HTML etiketleri içeren metni döndürür.
Sağlayıcıya özgü MIME türleri olarak da adlandırılan özel MIME türü dizelerinde daha fazla karmaşık type ve subtype değerleri. Birden fazla satır için tür değeri her zaman şu olur:
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 özeldir. Android yerleşik sağlayıcıları genellikle basit bir alt türdür. Ö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ştiriciler, sağlayıcının koduna bağlı olarak kendi alt tür kalıplarını oluşturabilirler.
yetki ve tablo adlarına yer verir. Örneğin, tren tarifeleri içeren bir sağlayıcı düşünün.
Sağlayıcının yetkisi com.example.trains
şeklindedir ve tabloları içerir
Satır1, Satır2 ve Satır3. Satır1 tablosunun 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ı sabitleri tanımlar. İlgili içeriği oluşturmak için kullanılan
Kişi Sağlayıcı sözleşme sınıfı ContactsContract.RawContacts
,
Örneğin,
Şu MIME türü için CONTENT_ITEM_TYPE
:
tek bir ham kişi satırı ekleyin.
Tek satırlar için İçerik URI'leri İçerik URI'leri bölümüne bakın.