Otomatik doldurma hizmeti, diğer uygulamaların görünümlerine veri ekleyerek kullanıcıların form doldurmasını kolaylaştıran bir uygulamadır. Otomatik doldurma hizmetleri, bir uygulamadaki görünümlerden kullanıcı verilerini alıp daha sonra kullanmak üzere saklayabilir. Otomatik doldurma hizmetleri genellikle şifre yöneticileri gibi kullanıcı verilerini yöneten uygulamalar tarafından sağlanır.
Android, Android 8.0 (API düzeyi 26) ve sonraki sürümlerde bulunan otomatik doldurma çerçevesiyle form doldurmayı kolaylaştırır. Kullanıcılar, otomatik doldurma özelliklerinden yalnızca cihazlarında otomatik doldurma hizmetleri sağlayan bir uygulama varsa yararlanabilir.
Bu sayfada, uygulamanızda otomatik doldurma hizmetinin nasıl uygulanacağı gösterilmektedir. Bir hizmetin nasıl uygulanacağını gösteren bir kod örneği arıyorsanız Java veya Kotlin dilindeki AutofillFramework örneğine bakın. Otomatik doldurma hizmetlerinin işleyiş şekli hakkında daha fazla bilgi için AutofillService ve AutofillManager sınıflarının referans sayfalarına bakın.
Manifest beyanları ve izinler
Otomatik doldurma hizmetleri sunan uygulamalar, hizmetin uygulanış şeklini açıklayan bir beyan içermelidir. Beyanı belirtmek için uygulama manifestine bir <service> öğesi ekleyin. <service> öğesi aşağıdaki özellikleri ve öğeleri içermelidir:
- Hizmeti uygulayan uygulamada
AutofillServicealt sınıfını işaret edenandroid:nameözelliği. BIND_AUTOFILL_SERVICEiznini beyan edenandroid:permissionözelliği.- Zorunlu
<action>alt öğesiandroid.service.autofill.AutofillServiceişlemini belirten<intent-filter>öğesi. - Hizmet için ek yapılandırma parametreleri sağlamak amacıyla kullanabileceğiniz isteğe bağlı
<meta-data>öğesi.
Aşağıdaki örnekte bir otomatik doldurma hizmeti beyanı gösterilmektedir:
<service
android:name=".MyAutofillService"
android:label="My Autofill Service"
android:permission="android.permissi>on.BI<ND_AUTOFILL_S>ERVICE&qu<ot;
intent-filter
action android:name="android.>servi<ce.autofill.Au>tofil<lService" /
/intent-filter
meta-data
android:name="android.autofill"
> < android:resource="@xml/service_configuration" /
/service
<meta-data> öğesi, hizmetle ilgili daha fazla ayrıntı içeren bir XML kaynağına işaret eden bir android:resource özelliği içerir. Önceki örnekteki service_configuration kaynağı, kullanıcıların hizmeti yapılandırmasına olanak tanıyan bir etkinliği belirtir. Aşağıdaki örnekte service_configuration XML kaynağı gösterilmektedir:
<autofill-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:settingsActivity="com.example.android.Sett>ingsActivity" /
XML kaynakları hakkında daha fazla bilgi için Uygulama kaynaklarına genel bakış başlıklı makaleyi inceleyin.
Hizmeti etkinleştirme istemi
Bir uygulama, BIND_AUTOFILL_SERVICE iznini beyan ettikten ve kullanıcı cihaz ayarlarında bu izni etkinleştirdikten sonra otomatik doldurma hizmeti olarak kullanılır. Bir uygulama, AutofillManager sınıfının hasEnabledAutofillServices() yöntemini çağırarak etkinleştirilmiş hizmet olup olmadığını doğrulayabilir.
Uygulama mevcut otomatik doldurma hizmeti değilse ACTION_REQUEST_SET_AUTOFILL_SERVICE intent'ini kullanarak kullanıcıdan otomatik doldurma ayarlarını değiştirmesini isteyebilir. Kullanıcı, arayanın paketiyle eşleşen bir otomatik doldurma hizmeti seçerse intent RESULT_OK değerini döndürür.
Müşteri görünümlerini doldurma
Otomatik doldurma hizmeti, kullanıcı diğer uygulamalarla etkileşimde bulunduğunda istemci görünümlerini doldurma istekleri alır. Otomatik doldurma hizmetinde isteği karşılayan kullanıcı verileri varsa bu veriler yanıtta gönderilir. Android sistemi, Şekil 1'de gösterildiği gibi mevcut verileri içeren bir otomatik doldurma kullanıcı arayüzü gösterir:
Otomatik doldurma çerçevesi, Android sisteminin otomatik doldurma hizmetine bağlı olduğu süreyi en aza indirecek şekilde tasarlanmış görünümleri doldurmak için bir iş akışı tanımlar. Her istekte Android sistemi, onFillRequest() yöntemini çağırarak hizmete bir AssistStructure nesnesi gönderir.
Otomatik doldurma hizmeti, isteği daha önce depoladığı kullanıcı verileriyle karşılayıp karşılayamayacağını kontrol eder. İsteği karşılayabiliyorsa hizmet, verileri Dataset nesneleri halinde paketler. Hizmet, Dataset nesnelerini içeren bir FillResponse nesnesi ileterek onSuccess() yöntemini çağırır. Hizmette isteği karşılayacak veri yoksa onSuccess() yöntemine null değerini iletir. İsteğin işlenmesi sırasında bir hata oluşursa hizmet, bunun yerine onFailure() yöntemini çağırır.
İş akışıyla ilgili ayrıntılı açıklama için AutofillService referans sayfasındaki açıklamaya bakın.
Aşağıdaki kodda onFillRequest() yöntemine dair bir örnek verilmiştir:
Kotlin
override fun onFillRequest(
request: FillRequest,
cancellationSignal: CancellationSignal,
callback: FillCallback
) {
// Get the structure from the request
val context: List<FillContext> = request.fillContexts
val structure: AssistStructure = context[context.size - 1].structure
// Traverse the structure looking for nodes to fill out
val parsedStructure: ParsedStructure = parseStructure(structure)
// Fetch user data that matches the fields
val (username: String, password: String) = fetchUserData(parsedStructure)
// Build the presentation of the datasets
val usernamePresentation = RemoteViews(packageName, android.R.layout.simple_list_item_1)
usernamePresentation.setTextViewText(android.R.id.text1, "my_username")
val passwordPresentation = RemoteViews(packageName, android.R.layout.simple_list_item_1)
passwordPresentation.setTextViewText(android.R.id.text1, "Password for my_username")
// Add a dataset to the response
val fillResponse: FillResponse = FillResponse.Builder()
.addDataset(Dataset.Builder()
.setValue(
parsedStructure.usernameId,
AutofillValue.forText(username),
usernamePresentation
)
.setValue(
parsedStructure.passwordId,
AutofillValue.forText(password),
passwordPresentation
)
.build())
.build()
// If there are no errors, call onSuccess() and pass the response
callback.onSuccess(fillResponse)
}
data class ParsedStructure(var usernameId: AutofillId, var passwordId: AutofillId)
data class UserData(var username: String, var password: String)
Java
@Override
public void onFillRequest(FillRequest request, CancellationSignal cancellationSignal, FillCallback callback) {
// Get the structure from the request
List<FillContext> context = request.getFillContexts();
AssistStructure structure = context.get(context.size() - 1).getStructure();
// Traverse the structure looking for nodes to fill out
ParsedStructure parsedStructure = parseStructure(structure);
// Fetch user data that matches the fields
UserData userData = fetchUserData(parsedStructure);
// Build the presentation of the datasets
RemoteViews usernamePresentation = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
usernamePresentation.setTextViewText(android.R.id.text1, "my_username");
RemoteViews passwordPresentation = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
passwordPresentation.setTextViewText(android.R.id.text1, "Password for my_username");
// Add a dataset to the response
FillResponse fillResponse = new FillResponse.Builder()
.addDataset(new Dataset.Builder()
.setValue(parsedStructure.usernameId,
AutofillValue.forText(userData.username), usernamePresentation)
.setValue(parsedStructure.passwordId,
AutofillValue.forText(userData.password), passwordPresentation)
.build())
.build();
// If there are no errors, call onSuccess() and pass the response
callback.onSuccess(fillResponse);
}
class ParsedStructure {
AutofillId usernameId;
AutofillId passwordId;
}
class UserData {
String username;
String password;
}
Bir hizmette, isteği karşılayan birden fazla veri kümesi olabilir. Bu durumda Android sistemi, otomatik doldurma kullanıcı arayüzünde her veri kümesi için bir tane olmak üzere birden fazla seçenek gösterir. Aşağıdaki kod örneğinde, bir yanıtta birden fazla veri kümesinin nasıl sağlanacağı gösterilmektedir:
Kotlin
// Add multiple datasets to the response
val fillResponse: FillResponse = FillResponse.Builder()
.addDataset(Dataset.Builder()
.setValue(parsedStructure.usernameId,
AutofillValue.forText(user1Data.username), username1Presentation)
.setValue(parsedStructure.passwordId,
AutofillValue.forText(user1Data.password), password1Presentation)
.build())
.addDataset(Dataset.Builder()
.setValue(parsedStructure.usernameId,
AutofillValue.forText(user2Data.username), username2Presentation)
.setValue(parsedStructure.passwordId,
AutofillValue.forText(user2Data.password), password2Presentation)
.build())
.build()
Java
// Add multiple datasets to the response
FillResponse fillResponse = new FillResponse.Builder()
.addDataset(new Dataset.Builder()
.setValue(parsedStructure.usernameId,
AutofillValue.forText(user1Data.username), username1Presentation)
.setValue(parsedStructure.passwordId,
AutofillValue.forText(user1Data.password), password1Presentation)
.build())
.addDataset(new Dataset.Builder()
.setValue(parsedStructure.usernameId,
AutofillValue.forText(user2Data.username), username2Presentation)
.setValue(parsedStructure.passwordId,
AutofillValue.forText(user2Data.password), password2Presentation)
.build())
.build();
Otomatik doldurma hizmetleri, isteği yerine getirmek için gereken otomatik doldurma verilerini almak üzere AssistStructure içindeki ViewNode nesnelerinde gezinebilir.
Bir hizmet, ViewNode sınıfının yöntemlerini (ör. getAutofillId()) kullanarak otomatik doldurma verilerini alabilir.
Bir hizmet, isteği karşılayıp karşılayamayacağını kontrol etmek için bir görünümün içeriğini açıklayabilmelidir. autofillHints özelliğini kullanmak, bir hizmetin görünümün içeriğini açıklamak için kullanması gereken ilk yaklaşımdır. Ancak istemci uygulamalarının, özelliğin hizmet tarafından kullanılabilmesi için özelliği görünümlerinde açıkça sağlaması gerekir.
İstemci uygulaması autofillHints özelliğini sağlamıyorsa hizmet, içeriği açıklamak için kendi buluşsal yöntemlerini kullanmalıdır. Hizmet, görünümün içeriği hakkında bilgi edinmek için getText() veya getHint() gibi diğer sınıflardaki yöntemleri kullanabilir. Daha fazla bilgi için Otomatik doldurma için ipuçları sağlama başlıklı makaleyi inceleyin.
Aşağıdaki örnekte, AssistStructure öğesinin nasıl taranacağı ve bir ViewNode nesnesinden otomatik doldurma verilerinin nasıl alınacağı gösterilmektedir:
Kotlin
fun traverseStructure(structure: AssistStructure) {
val windowNodes: List<AssistStructure.WindowNode> =
structure.run {
(0 until windowNodeCount).map { getWindowNodeAt(it) }
}
windowNodes.forEach { windowNode: AssistStructure.WindowNode ->
val viewNode: ViewNode? = windowNode.rootViewNode
traverseNode(viewNode)
}
}
fun traverseNode(viewNode: ViewNode?) {
if (viewNode?.autofillHints?.isNotEmpty() == true) {
// If the client app provides autofill hints, you can obtain them using
// viewNode.getAutofillHints();
} else {
// Or use your own heuristics to describe the contents of a view
// using methods such as getText() or getHint()
}
val children: List<ViewNode>? =
viewNode?.run {
(0 until childCount).map { getChildAt(it) }
}
children?.forEach { childNode: ViewNode ->
traverseNode(childNode)
}
}
Java
public void traverseStructure(AssistStructure structure) {
int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
WindowNode windowNode = structure.getWindowNodeAt(i);
ViewNode viewNode = windowNode.getRootViewNode();
traverseNode(viewNode);
}
}
public void traverseNode(ViewNode viewNode) {
if(viewNode.getAutofillHints() != null && viewNode.getAutofillHints().length > 0) {
// If the client app provides autofill hints, you can obtain them using
// viewNode.getAutofillHints();
} else {
// Or use your own heuristics to describe the contents of a view
// using methods such as getText() or getHint()
}
for(int i = 0; i < viewNode.getChildCount(); i++) {
ViewNode childNode = viewNode.getChildAt(i);
traverseNode(childNode);
}
}
Kullanıcı verilerini kaydedin
Otomatik doldurma hizmetinin, uygulamalardaki görünümleri doldurmak için kullanıcı verilerine ihtiyacı vardır. Kullanıcılar bir görünümü manuel olarak doldurduğunda, Şekil 2'de gösterildiği gibi verileri mevcut otomatik doldurma hizmetine kaydetmeleri istenir.
Verileri kaydetmek için hizmetin, verileri gelecekte kullanmak üzere depolamak istediğini belirtmesi gerekir. Android sistemi verileri kaydetme isteği göndermeden önce, hizmetin görünümleri doldurma fırsatına sahip olduğu bir doldurma isteği vardır. Hizmet, verileri kaydetmek istediğini belirtmek için doldurma isteğine verilen yanıta bir SaveInfo nesnesi ekler. SaveInfo nesnesi en azından aşağıdaki verileri içerir:
- Kaydedilen kullanıcı verilerinin türü. Kullanılabilir
SAVE_DATAdeğerlerinin listesi içinSaveInfosayfasına bakın. - Kaydetme isteğini tetiklemek için değiştirilmesi gereken minimum görünüm sayısı.
Örneğin, bir giriş formunda genellikle kullanıcının kaydetme isteğini tetiklemek için
usernamevepasswordgörünümlerini güncellemesi gerekir.
Aşağıdaki kod örneğinde gösterildiği gibi, bir SaveInfo nesnesi bir FillResponse nesnesiyle ilişkilendirilir:
Kotlin
override fun onFillRequest(
request: FillRequest,
cancellationSignal: CancellationSignal,
callback: FillCallback
) {
// ...
// Builder object requires a non-null presentation
val notUsed = RemoteViews(packageName, android.R.layout.simple_list_item_1)
val fillResponse: FillResponse = FillResponse.Builder()
.addDataset(
Dataset.Builder()
.setValue(parsedStructure.usernameId, null, notUsed)
.setValue(parsedStructure.passwordId, null, notUsed)
.build()
)
.setSaveInfo(
SaveInfo.Builder(
SaveInfo.SAVE_DATA_TYPE_USERNAME or SaveInfo.SAVE_DATA_TYPE_PASSWORD,
arrayOf(parsedStructure.usernameId, parsedStructure.passwordId)
).build()
)
.build()
// ...
}
Java
@Override
public void onFillRequest(FillRequest request, CancellationSignal cancellationSignal, FillCallback callback) {
// ...
// Builder object requires a non-null presentation
RemoteViews notUsed = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
FillResponse fillResponse = new FillResponse.Builder()
.addDataset(new Dataset.Builder()
.setValue(parsedStructure.usernameId, null, notUsed)
.setValue(parsedStructure.passwordId, null, notUsed)
.build())
.setSaveInfo(new SaveInfo.Builder(
SaveInfo.SAVE_DATA_TYPE_USERNAME | SaveInfo.SAVE_DATA_TYPE_PASSWORD,
new AutofillId[] {parsedStructure.usernameId, parsedStructure.passwordId})
.build())
.build();
// ...
}
Otomatik doldurma hizmeti, kullanıcı verilerini onSaveRequest() yönteminde kalıcı hale getirmek için mantık uygulayabilir. Bu yöntem genellikle istemci etkinliği bittikten sonra veya istemci uygulaması commit() yöntemini çağırdığında çağrılır. Aşağıdaki kodda onSaveRequest() yönteminin bir örneği gösterilmektedir:
Kotlin
override fun onSaveRequest(request: SaveRequest, callback: SaveCallback) {
// Get the structure from the request
val context: List<FillContext> = request.fillContexts
val structure: AssistStructure = context[context.size - 1].structure
// Traverse the structure looking for data to save
traverseStructure(structure)
// Persist the data - if there are no errors, call onSuccess()
callback.onSuccess()
}
Java
@Override
public void onSaveRequest(SaveRequest request, SaveCallback callback) {
// Get the structure from the request
List<FillContext> context = request.getFillContexts();
AssistStructure structure = context.get(context.size() - 1).getStructure();
// Traverse the structure looking for data to save
traverseStructure(structure);
// Persist the data - if there are no errors, call onSuccess()
callback.onSuccess();
}
Otomatik doldurma hizmetleri, hassas verileri kalıcı hale getirmeden önce şifrelemelidir. Ancak kullanıcı verileri, hassas olmayan etiketler veya veriler içerebilir. Örneğin, bir kullanıcı hesabı, verileri iş veya kişisel hesap olarak işaretleyen bir etiket içerebilir. Hizmetler, etiketleri şifrelememelidir. Etiketler şifrelenmediğinde, kullanıcı kimlik doğrulaması yapmamışsa hizmetler etiketleri sunu görünümlerinde kullanabilir. Ardından, hizmetler, kullanıcı kimliğini doğruladıktan sonra etiketleri gerçek verilerle değiştirebilir.
Otomatik doldurma kaydetme kullanıcı arayüzünü erteleme
Android 10'dan itibaren, otomatik doldurma iş akışını uygulamak için birden fazla ekran kullanıyorsanız (örneğin, kullanıcı adı alanı için bir ekran ve şifre için başka bir ekran) SaveInfo.FLAG_DELAY_SAVE işaretini kullanarak otomatik doldurma kaydetme kullanıcı arayüzünü erteleyebilirsiniz.
Bu işaret ayarlanırsa SaveInfo yanıtıyla ilişkili otomatik doldurma bağlamı uygulandığında otomatik doldurma kaydetme kullanıcı arayüzü tetiklenmez. Bunun yerine, gelecekteki doldurma isteklerini iletmek için aynı görevde ayrı bir etkinlik kullanabilir ve ardından kaydetme isteği kullanarak kullanıcı arayüzünü gösterebilirsiniz. Daha fazla bilgi için SaveInfo.FLAG_DELAY_SAVE konusuna bakın.
Kullanıcı kimlik doğrulamasını zorunlu kılma
Otomatik doldurma hizmetleri, görünümleri doldurmadan önce kullanıcının kimliğini doğrulamasını zorunlu kılarak ek bir güvenlik düzeyi sağlayabilir. Aşağıdaki senaryolar, kullanıcı kimlik doğrulamasını uygulamak için iyi adaylardır:
- Uygulamadaki kullanıcı verilerinin kilidinin birincil şifre veya parmak izi taraması kullanılarak açılması gerekir.
- Kart doğrulama kodu (CVC) kullanılarak kredi kartı bilgileri gibi belirli bir veri kümesinin kilidinin açılması gerekir.
Hizmetin, verilerin kilidini açmadan önce kullanıcı kimlik doğrulaması gerektirdiği bir senaryoda, hizmet standart veriler veya bir etiket sunabilir ve kimlik doğrulama işlemini gerçekleştiren Intent öğesini belirtebilir. Kimlik doğrulama akışı tamamlandıktan sonra isteği işlemek için ek verilere ihtiyacınız varsa bu verileri intent'e ekleyebilirsiniz. Ardından, kimlik doğrulama etkinliğiniz verileri uygulamanızdaki AutofillService sınıfına döndürebilir.
Aşağıdaki kod örneğinde, isteğin kimlik doğrulama gerektirdiğinin nasıl belirtileceği gösterilmektedir:
Kotlin
val authPresentation = RemoteViews(packageName, android.R.layout.simple_list_item_1).apply {
setTextViewText(android.R.id.text1, "requires authentication")
}
val authIntent = Intent(this, AuthActivity::class.java).apply {
// Send any additional data required to complete the request
putExtra(MY_EXTRA_DATASET_NAME, "my_dataset")
}
val intentSender: IntentSender = PendingIntent.getActivity(
this,
1001,
authIntent,
PendingIntent.FLAG_CANCEL_CURRENT
).intentSender
// Build a FillResponse object that requires authentication
val fillResponse: FillResponse = FillResponse.Builder()
.setAuthentication(autofillIds, intentSender, authPresentation)
.build()
Java
RemoteViews authPresentation = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
authPresentation.setTextViewText(android.R.id.text1, "requires authentication");
Intent authIntent = new Intent(this, AuthActivity.class);
// Send any additional data required to complete the request
authIntent.putExtra(MY_EXTRA_DATASET_NAME, "my_dataset");
IntentSender intentSender = PendingIntent.getActivity(
this,
1001,
authIntent,
PendingIntent.FLAG_CANCEL_CURRENT
).getIntentSender();
// Build a FillResponse object that requires authentication
FillResponse fillResponse = new FillResponse.Builder()
.setAuthentication(autofillIds, intentSender, authPresentation)
.build();
Etkinlik, kimlik doğrulama akışını tamamladıktan sonra setResult() yöntemini çağırarak RESULT_OK değerini iletmeli ve EXTRA_AUTHENTICATION_RESULT ek değerini, doldurulmuş veri kümesini içeren FillResponse nesnesine ayarlamalıdır. Aşağıdaki kodda, kimlik doğrulama akışı tamamlandıktan sonra sonucun nasıl döndürüleceğine dair bir örnek gösterilmektedir:
Kotlin
// The data sent by the service and the structure are included in the intent
val datasetName: String? = intent.getStringExtra(MY_EXTRA_DATASET_NAME)
val structure: AssistStructure = intent.getParcelableExtra(EXTRA_ASSIST_STRUCTURE)
val parsedStructure: ParsedStructure = parseStructure(structure)
val (username, password) = fetchUserData(parsedStructure)
// Build the presentation of the datasets
val usernamePresentation =
RemoteViews(packageName, android.R.layout.simple_list_item_1).apply {
setTextViewText(android.R.id.text1, "my_username")
}
val passwordPresentation =
RemoteViews(packageName, android.R.layout.simple_list_item_1).apply {
setTextViewText(android.R.id.text1, "Password for my_username")
}
// Add the dataset to the response
val fillResponse: FillResponse = FillResponse.Builder()
.addDataset(Dataset.Builder()
.setValue(
parsedStructure.usernameId,
AutofillValue.forText(username),
usernamePresentation
)
.setValue(
parsedStructure.passwordId,
AutofillValue.forText(password),
passwordPresentation
)
.build()
).build()
val replyIntent = Intent().apply {
// Send the data back to the service
putExtra(MY_EXTRA_DATASET_NAME, datasetName)
putExtra(EXTRA_AUTHENTICATION_RESULT, fillResponse)
}
setResult(Activity.RESULT_OK, replyIntent)
Java
Intent intent = getIntent();
// The data sent by the service and the structure are included in the intent
String datasetName = intent.getStringExtra(MY_EXTRA_DATASET_NAME);
AssistStructure structure = intent.getParcelableExtra(EXTRA_ASSIST_STRUCTURE);
ParsedStructure parsedStructure = parseStructure(structure);
UserData userData = fetchUserData(parsedStructure);
// Build the presentation of the datasets
RemoteViews usernamePresentation = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
usernamePresentation.setTextViewText(android.R.id.text1, "my_username");
RemoteViews passwordPresentation = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
passwordPresentation.setTextViewText(android.R.id.text1, "Password for my_username");
// Add the dataset to the response
FillResponse fillResponse = new FillResponse.Builder()
.addDataset(new Dataset.Builder()
.setValue(parsedStructure.usernameId,
AutofillValue.forText(userData.username), usernamePresentation)
.setValue(parsedStructure.passwordId,
AutofillValue.forText(userData.password), passwordPresentation)
.build())
.build();
Intent replyIntent = new Intent();
// Send the data back to the service
replyIntent.putExtra(MY_EXTRA_DATASET_NAME, datasetName);
replyIntent.putExtra(EXTRA_AUTHENTICATION_RESULT, fillResponse);
setResult(RESULT_OK, replyIntent);
Kredi kartı veri kümesinin kilidinin açılması gerektiğinde hizmet, CVC isteyen bir kullanıcı arayüzü gösterebilir. Veri kümesinin kilidi açılana kadar verileri gizleyebilirsiniz. Bunun için bankanın adı ve kredi kartı numarasının son dört hanesi gibi standart verileri gösterebilirsiniz. Aşağıdaki örnekte, bir veri kümesi için kimlik doğrulamanın nasıl zorunlu kılınacağı ve kullanıcı CVC'yi girene kadar verilerin nasıl gizleneceği gösterilmektedir:
Kotlin
// Parse the structure and fetch payment data
val parsedStructure: ParsedStructure = parseStructure(structure)
val paymentData: Payment = fetchPaymentData(parsedStructure)
// Build the presentation that shows the bank and the last four digits of the
// credit card number, such as 'Bank-1234'
val maskedPresentation: String = "${paymentData.bank}-" +
paymentData.creditCardNumber.substring(paymentData.creditCardNumber.length - 4)
val authPresentation = RemoteViews(packageName, android.R.layout.simple_list_item_1).apply {
setTextViewText(android.R.id.text1, maskedPresentation)
}
// Prepare an intent that displays the UI that asks for the CVC
val cvcIntent = Intent(this, CvcActivity::class.java)
val cvcIntentSender: IntentSender = PendingIntent.getActivity(
this,
1001,
cvcIntent,
PendingIntent.FLAG_CANCEL_CURRENT
).intentSender
// Build a FillResponse object that includes a Dataset that requires authentication
val fillResponse: FillResponse = FillResponse.Builder()
.addDataset(
Dataset.Builder()
// The values in the dataset are replaced by the actual
// data once the user provides the CVC
.setValue(parsedStructure.creditCardId, null, authPresentation)
.setValue(parsedStructure.expDateId, null, authPresentation)
.setAuthentication(cvcIntentSender)
.build()
).build()
Java
// Parse the structure and fetch payment data
ParsedStructure parsedStructure = parseStructure(structure);
Payment paymentData = fetchPaymentData(parsedStructure);
// Build the presentation that shows the bank and the last four digits of the
// credit card number, such as 'Bank-1234'
String maskedPresentation = paymentData.bank + "-" +
paymentData.creditCardNumber.subString(paymentData.creditCardNumber.length - 4);
RemoteViews authPresentation = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
authPresentation.setTextViewText(android.R.id.text1, maskedPresentation);
// Prepare an intent that displays the UI that asks for the CVC
Intent cvcIntent = new Intent(this, CvcActivity.class);
IntentSender cvcIntentSender = PendingIntent.getActivity(
this,
1001,
cvcIntent,
PendingIntent.FLAG_CANCEL_CURRENT
).getIntentSender();
// Build a FillResponse object that includes a Dataset that requires authentication
FillResponse fillResponse = new FillResponse.Builder()
.addDataset(new Dataset.Builder()
// The values in the dataset are replaced by the actual
// data once the user provides the CVC
.setValue(parsedStructure.creditCardId, null, authPresentation)
.setValue(parsedStructure.expDateId, null, authPresentation)
.setAuthentication(cvcIntentSender)
.build())
.build();
Etkinlik, CVC'yi doğruladıktan sonra RESULT_OK değerini ileterek setResult() yöntemini çağırmalı ve EXTRA_AUTHENTICATION_RESULT ek değerini, kredi kartı numarasını ve son kullanma tarihini içeren bir Dataset nesnesine ayarlamalıdır. Yeni veri kümesi, kimlik doğrulama gerektiren veri kümesinin yerini alır ve görünümler hemen doldurulur. Aşağıdaki kodda, kullanıcı CVC'yi sağladıktan sonra veri kümesinin nasıl döndürüleceğine dair bir örnek gösterilmektedir:
Kotlin
// Parse the structure and fetch payment data.
val parsedStructure: ParsedStructure = parseStructure(structure)
val paymentData: Payment = fetchPaymentData(parsedStructure)
// Build a non-null RemoteViews object to use as the presentation when
// creating the Dataset object. This presentation isn't actually used, but the
// Builder object requires a non-null presentation.
val notUsed = RemoteViews(packageName, android.R.layout.simple_list_item_1)
// Create a dataset with the credit card number and expiration date.
val responseDataset: Dataset = Dataset.Builder()
.setValue(
parsedStructure.creditCardId,
AutofillValue.forText(paymentData.creditCardNumber),
notUsed
)
.setValue(
parsedStructure.expDateId,
AutofillValue.forText(paymentData.expirationDate),
notUsed
)
.build()
val replyIntent = Intent().apply {
putExtra(EXTRA_AUTHENTICATION_RESULT, responseDataset)
}
Java
// Parse the structure and fetch payment data.
ParsedStructure parsedStructure = parseStructure(structure);
Payment paymentData = fetchPaymentData(parsedStructure);
// Build a non-null RemoteViews object to use as the presentation when
// creating the Dataset object. This presentation isn't actually used, but the
// Builder object requires a non-null presentation.
RemoteViews notUsed = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
// Create a dataset with the credit card number and expiration date.
Dataset responseDataset = new Dataset.Builder()
.setValue(parsedStructure.creditCardId,
AutofillValue.forText(paymentData.creditCardNumber), notUsed)
.setValue(parsedStructure.expDateId,
AutofillValue.forText(paymentData.expirationDate), notUsed)
.build();
Intent replyIntent = new Intent();
replyIntent.putExtra(EXTRA_AUTHENTICATION_RESULT, responseDataset);
Verileri mantıksal gruplar halinde düzenleme
Otomatik doldurma hizmetleri, verileri farklı alanlardaki kavramları ayıran mantıksal gruplar halinde düzenlemelidir. Bu sayfada, bu mantıksal gruplar bölümler olarak adlandırılır. Aşağıdaki listede, bölümler ve alanlarla ilgili tipik örnekler gösterilmektedir:
- Kullanıcı adı ve şifre alanlarını içeren kimlik bilgileri.
- Sokak, şehir, eyalet ve posta kodu alanlarını içeren adres.
- Kredi kartı numarası, son kullanma tarihi ve doğrulama kodu alanlarını içeren ödeme bilgileri.
Verileri doğru şekilde bölümlere ayıran bir otomatik doldurma hizmeti, bir veri kümesindeki birden fazla bölümden veri göstermeyerek kullanıcılarının verilerini daha iyi koruyabilir. Örneğin, kimlik bilgilerini içeren bir veri kümesinin ödeme bilgilerini içermesi gerekmez. Verileri bölümlere ayırarak düzenlemek, hizmetinizin bir isteği karşılamak için gereken minimum miktarda alakalı bilgiyi göstermesini sağlar.
Verileri bölümler halinde düzenlemek, hizmetlerin birden fazla bölümden görüntüleme alan etkinlikleri doldurmasına olanak tanırken istemci uygulamasına minimum miktarda alakalı veri gönderir. Örneğin, kullanıcı adı, şifre, sokak ve şehir için görüntülemeler içeren bir etkinliği ve aşağıdaki verilere sahip bir otomatik doldurma hizmetini ele alalım:
| Bölüm | 1. alan | 2. alan |
|---|---|---|
| Kimlik Bilgileri | work_username | work_password |
| personal_username | personal_password | |
| Adres | work_street | work_city |
| personal_street | personal_city |
Hizmet, hem iş hem de kişisel hesaplar için kimlik bilgileri bölümünü içeren bir veri kümesi hazırlayabilir. Kullanıcı bir veri kümesi seçtiğinde, sonraki otomatik doldurma yanıtı kullanıcının ilk seçimine bağlı olarak iş veya kişisel adresi sağlayabilir.
Bir hizmet, AssistStructure nesnesini incelerken isFocused() yöntemini çağırarak isteği başlatan alanı tanımlayabilir.
Bu sayede hizmet, uygun bölüm verileriyle bir FillResponse hazırlayabilir.
SMS ile gönderilen tek seferlik kodları otomatik doldurma
Otomatik doldurma hizmetiniz, kullanıcının SMS Retriever API kullanılarak gönderilen tek seferlik kodları doldurmasına yardımcı olabilir.
Bu özelliği kullanmak için aşağıdaki koşulların karşılanması gerekir:
- Otomatik doldurma hizmeti Android 9 (API düzeyi 28) veya sonraki sürümlerde çalışıyor olmalıdır.
- Kullanıcı, otomatik doldurma hizmetinizin SMS'ten tek seferlik kodları okumasına izin verir.
- Otomatik doldurma hizmeti sağladığınız uygulama, tek kullanımlık kodları okumak için SMS Retriever API'yi kullanmıyor.
Otomatik doldurma hizmetiniz, Google Play Hizmetleri 19.0.56 veya sonraki sürümlerden SmsCodeRetriever.getAutofillClient() çağrılarak kullanılabilen SmsCodeAutofillClient özelliğini kullanabilir.
Bu API'yi bir otomatik doldurma hizmetinde kullanmanın temel adımları şunlardır:
- Otomatik doldurma hizmetinde, otomatik doldurma işlemi yaptığınız uygulamanın paket adı için etkin istek olup olmadığını belirlemek üzere
SmsCodeAutofillClientiçindekihasOngoingSmsRequestyöntemini kullanın. Otomatik doldurma hizmetiniz yalnızca bu değerfalseise öneri istemi göstermelidir. - Otomatik doldurma hizmetinde, otomatik doldurma hizmetinin tek seferlik kodları otomatik doldurma izni olup olmadığını kontrol etmek için
SmsCodeAutofillClientsınıfındakicheckPermissionStateyöntemini kullanın. Bu izin durumuNONE,GRANTEDveyaDENIEDolabilir. Otomatik doldurma hizmeti,NONEveGRANTEDdurumları için bir öneri istemi göstermelidir. - Otomatik doldurma kimlik doğrulama etkinliğinde, SMS kodu sonucu kullanılabilir olduğunda sonucu almak için
SmsCodeRetriever.SMS_CODE_RETRIEVED_ACTIONöğesini dinleyen birBroadcastReceiverkaydetmek üzereSmsRetriever.SEND_PERMISSIONiznini kullanın. SMS ile gönderilen tek seferlik kodları dinlemeye başlamak için
SmsCodeAutofillClientüzerindestartSmsCodeRetrieveryöntemini çağırın. Kullanıcı, otomatik doldurma hizmetinizin SMS'ten tek seferlik kodları almasına izin verirse son bir ila beş dakika içinde alınan SMS mesajları aranır.Otomatik doldurma hizmetinizin tek kullanımlık kodları okumak için kullanıcı izni istemesi gerekiyorsa
startSmsCodeRetrievertarafından döndürülenTask,ResolvableApiExceptiondöndürülerek başarısız olabilir. Bu durumda, izin isteği için bir izin iletişim kutusu görüntülemek üzereResolvableApiException.startResolutionForResult()yöntemini çağırmanız gerekir.Intent'ten SMS kodu sonucunu alın ve ardından SMS kodunu otomatik doldurma yanıtı olarak döndürün.
Chrome'da otomatik doldurmayı etkinleştirme
Chrome, üçüncü taraf otomatik doldurma hizmetlerinin formları yerel olarak otomatik doldurmasına izin vererek kullanıcılara daha sorunsuz ve basit bir kullanıcı deneyimi sunar. Şifreleri, geçiş anahtarlarını ve adresler ile ödeme verileri gibi diğer bilgileri otomatik doldurmak için üçüncü taraf otomatik doldurma hizmetlerini kullanmak isteyen kullanıcıların Chrome ayarlarında Başka bir hizmet kullanarak otomatik doldur'u seçmesi gerekir.
Kullanıcıların, hizmetiniz ve Android'deki Chrome ile mümkün olan en iyi otomatik doldurma hizmeti deneyimini yaşaması için otomatik doldurma hizmeti sağlayıcıları, kullanıcılarını Chrome ayarlarında tercih ettikleri hizmet sağlayıcıyı belirtmeye teşvik etmelidir.
Geliştiriciler, kullanıcıların açma/kapatma düğmesini etkinleştirmesine yardımcı olmak için şunları yapabilir:
- Chrome ayarlarını sorgulayıp kullanıcının üçüncü taraf otomatik doldurma hizmeti kullanmak isteyip istemediğini öğrenin.
- Kullanıcıların üçüncü taraf otomatik doldurma hizmetlerini etkinleştirebileceği Chrome ayarları sayfasının derin bağlantısı.
Uyumluluk modu için maksimum Chrome sürümlerini belirtin
Chrome, 137 sürümünden itibaren uyumluluk modunu desteklemeyi bıraktı ve Android otomatik doldurma özelliğini kullanmaya başladı. Uyumluluk modunu etkin tutmak kararlılık sorunlarına neden olabilir. Kararlılık için uyumluluk modunu destekleyen Chrome paketlerinin maksimum sürümünü aşağıdaki gibi belirtin.
<autofill-service>
...
<compatibility-package android:name="com.android.chrome" android:maxLongVersionCode=&qu>ot;<711900039" /
compatibility-package android:name="com.chrome.beta" android:ma>xLo<ngVersionCode="711900039" /
compatibility-package android:name="com.chrome.>dev<" android:maxLongVersionCode="711900039" /
compatibility-package android:name=>"c<om.chrome.canary&>quot; android:maxLongVersionCode="711900039" /
...
/autofill-service
Chrome ayarlarını okuma
Tüm uygulamalar, Chrome'un Android Otomatik Doldurma özelliğini kullanmasına olanak tanıyan 3. taraf otomatik doldurma modunu kullanıp kullanmadığını okuyabilir. Chrome, bu bilgileri iletmek için Android'in ContentProvider özelliğini kullanır. Android manifest dosyanızda, ayarlarını okumak istediğiniz kanalları beyan edin:
<uses-permission android:name="android.permission.READ_USER_DICTION>A<RY">;/<
queries
!-- To Query Chrom>e <Beta: --
package android:name="com>.ch<rome.beta" /
!-- To Que>ry< Chrome Stable: --
package android:name=&q>u<ot;com.a>ndroid.chrome" /
/queries
Ardından, içerik URI'sini oluşturarak bu bilgileri istemek için Android'in ContentResolver özelliğini kullanın:
Kotlin
val CHROME_CHANNEL_PACKAGE = "com.android.chrome" // Chrome Stable.
val CONTENT_PROVIDER_NAME = ".AutofillThirdPartyModeContentProvider"
val THIRD_PARTY_MODE_COLUMN = "autofill_third_party_state"
val THIRD_PARTY_MODE_ACTIONS_URI_PATH = "autofill_third_party_mode"
val uri = Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(CHROME_CHANNEL_PACKAGE + CONTENT_PROVIDER_NAME)
.path(THIRD_PARTY_MODE_ACTIONS_URI_PATH)
.build()
val cursor = contentResolver.query(
uri,
arrayOf(THIRD_PARTY_MODE_COLUMN), // projection
null, // selection
null, // selectionArgs
null // sortOrder
)
if (cursor == null) {
// Terminate now! Chromium versions older than this don't provide this information.
}
cursor?.use { // Use the safe call operator and the use function for auto-closing
if (it.moveToFirst()) { // Check if the cursor has any rows
val index = it.getColumnIndex(THIRD_PARTY_MODE_COLUMN)
if (index != -1) { // Check if the column exists
val value = it.getInt(index)
if (0 == value) {
// 0 means that the third party mode is turned off. Chrome uses its built-in
// password manager. This is the default for new users.
} else {
// 1 means that the third party mode is turned on. Chrome forwards all
// autofill requests to Android Autofill. Users have to opt-in for this.
}
} else {
// Handle the case where the column doesn't exist. Log a warning, perhaps.
Log.w("Autofill", "Column $THIRD_PARTY_MODE_COLUMN not found in cursor")
}
}
} // The cursor is automatically closed here
Java
final String CHROME_CHANNEL_PACKAGE = "com.android.chrome"; // Chrome Stable.
final String CONTENT_PROVIDER_NAME = ".AutofillThirdPartyModeContentProvider";
final String THIRD_PARTY_MODE_COLUMN = "autofill_third_party_state";
final String THIRD_PARTY_MODE_ACTIONS_URI_PATH = "autofill_third_party_mode";
final Uri uri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(CHROME_CHANNEL_PACKAGE + CONTENT_PROVIDER_NAME)
.path(THIRD_PARTY_MODE_ACTIONS_URI_PATH)
.build();
final Cursor cursor = getContentResolver().query(
uri,
/*projection=*/new String[] {THIRD_PARTY_MODE_COLUMN},
/*selection=*/ null,
/*selectionArgs=*/ null,
/*sortOrder=*/ null);
if (cursor == null) {
// Terminate now! Chromium versions older than this don't provide this information.
}
cursor.moveToFirst(); // Retrieve the result;
int index = cursor.getColumnIndex(THIRD_PARTY_MODE_COLUMN);
if (0 == cursor.getInt(index)) {
// 0 means that the third party mode is turned off. Chrome uses its built-in
// password manager. This is the default for new users.
} else {
// 1 means that the third party mode is turned on. Chrome forwards all
// autofill requests to Android Autofill. Users have to opt-in for this.
}
Chrome ayarlarına derin bağlantı
Kullanıcıların üçüncü taraf otomatik doldurma hizmetlerini etkinleştirebileceği Chrome ayarları sayfasına derin bağlantı oluşturmak için Android Intent kullanın. İşlemi ve kategorileri bu örnekte gösterildiği gibi yapılandırdığınızdan emin olun:
Kotlin
val autofillSettingsIntent = Intent(Intent.ACTION_APPLICATION_PREFERENCES)
autofillSettingsIntent.addCategory(Intent.CATEGORY_DEFAULT)
autofillSettingsIntent.addCategory(Intent.CATEGORY_APP_BROWSER)
autofillSettingsIntent.addCategory(Intent.CATEGORY_PREFERENCE)
// Invoking the intent with a chooser allows users to select the channel they
// want to configure. If only one browser reacts to the intent, the chooser is
// skipped.
val chooser = Intent.createChooser(autofillSettingsIntent, "Pick Chrome Channel")
startActivity(chooser)
// If the caller knows which Chrome channel they want to configure,
// they can instead add a package hint to the intent, e.g.
val specificChromeIntent = Intent(Intent.ACTION_APPLICATION_PREFERENCES) // Create a *new* intent
specificChromeIntent.addCategory(Intent.CATEGORY_DEFAULT)
specificChromeIntent.addCategory(Intent.CATEGORY_APP_BROWSER)
specificChromeIntent.addCategory(Intent.CATEGORY_PREFERENCE)
specificChromeIntent.setPackage("com.android.chrome") // Set the package on the *new* intent
startActivity(specificChromeIntent) // Start the *new* intent
Java
Intent autofillSettingsIntent = new Intent(Intent.ACTION_APPLICATION_PREFERENCES);
autofillSettingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
autofillSettingsIntent.addCategory(Intent.CATEGORY_APP_BROWSER);
autofillSettingsIntent.addCategory(Intent.CATEGORY_PREFERENCE);
// Invoking the intent with a chooser allows users to select the channel they
// want to configure. If only one browser reacts to the intent, the chooser is
// skipped.
Intent chooser = Intent.createChooser(autofillSettingsIntent, "Pick Chrome Channel");
startActivity(chooser);
// If the caller knows which Chrome channel they want to configure,
// they can instead add a package hint to the intent, e.g.
autofillSettingsIntent.setPackage("com.android.chrome");
startActivity(autofillSettingsIntent);
Gelişmiş otomatik doldurma senaryoları
Otomatik doldurma özelliğini aşağıdaki senaryolarda kullanabilirsiniz:
Klavyeyle entegrasyon
Android 11'den itibaren platform, klavyelerin ve diğer giriş yöntemi düzenleyicilerinin (IME'ler) otomatik doldurma önerilerini açılır menü yerine satır içi olarak göstermesine olanak tanır. Otomatik doldurma hizmetinizin bu işlevi nasıl destekleyebileceği hakkında daha fazla bilgi için Otomatik doldurmayı klavyelerle entegre etme başlıklı makaleyi inceleyin.
Veri kümelerini sayfalandırma
Büyük bir otomatik doldurma yanıtı, isteği işlemek için gereken uzaktan erişilebilir nesneyi temsil eden Binder nesnesinin izin verilen işlem boyutunu aşabilir. Android sisteminin bu senaryolarda istisna oluşturmasını önlemek için tek seferde en fazla 20 Dataset nesnesi ekleyerek FillResponse boyutunu küçük tutabilirsiniz. Yanıtınız için daha fazla veri kümesi gerekiyorsa kullanıcılara daha fazla bilgi olduğunu bildiren ve seçildiğinde bir sonraki veri kümesi grubunu alan bir veri kümesi ekleyebilirsiniz. Daha fazla bilgi için addDataset(Dataset) konusuna bakın.
Birden fazla ekrana bölünmüş verileri kaydetme
Uygulamalar, kullanıcı verilerini genellikle aynı etkinlikteki birden fazla ekrana böler (ör. yeni kullanıcı hesapları oluşturmak için). Örneğin, ilk ekranda kullanıcı adı, ikinci ekranda ise şifre istenebilir. Bu gibi durumlarda, otomatik doldurma hizmetiniz, otomatik doldurma kaydetme kullanıcı arayüzünü görüntülemeden önce kullanıcının tüm ilgili alanlara veri girmesini beklemelidir. Bu tür senaryoları yönetmek için aşağıdaki adımları uygulayın:
- İlk doldurma isteğinde, yanıta ekranda bulunan kısmi alanların otomatik doldurma kimliklerini içeren bir istemci durumu paketi ekleyin.
- İkinci doldurma isteğinde istemci durumu paketini alın, önceki istekte istemci durumundan ayarlanan otomatik doldurma kimliklerini alın ve bu kimlikleri ve
FLAG_SAVE_ON_ALL_VIEWS_INVISIBLEişaretini ikinci yanıtta kullanılanSaveInfonesnesine ekleyin. Kaydetme isteğinde, her alanın değerini almak için uygun
FillContextnesnelerini kullanın. Her doldurma isteği için bir doldurma bağlamı vardır.Daha fazla bilgi için Veriler birden fazla ekrana bölündüğünde kaydetme bölümüne bakın.
Her istek için başlatma ve kaldırma mantığı sağlama
Her otomatik doldurma isteği olduğunda Android sistemi hizmete bağlanır ve onConnected() yöntemini çağırır. Hizmet isteği işledikten sonra Android sistemi onDisconnected() yöntemini çağırır ve hizmetle olan bağlantıyı kaldırır. Bir isteği işlemeden önce çalıştırılacak kodu sağlamak için onConnected(), bir isteği işledikten sonra çalıştırılacak kodu sağlamak için ise onDisconnected() kullanabilirsiniz.
Otomatik doldurma kaydetme kullanıcı arayüzünü özelleştirme
Otomatik doldurma hizmetleri, kullanıcıların verilerini hizmete kaydetmek isteyip istemediklerine karar vermelerine yardımcı olmak için otomatik doldurma kaydetme kullanıcı arayüzünü özelleştirebilir. Hizmetler, kaydedilenler hakkında metin veya özelleştirilmiş bir görünüm aracılığıyla ek bilgi sağlayabilir. Hizmetler, kaydetme isteğini iptal eden düğmenin görünümünü de değiştirebilir ve kullanıcı bu düğmeye dokunduğunda bildirim alabilir.
Daka fazla bilgi için SaveInfo referans sayfasına bakın.
Uyumluluk modu
Uyumluluk modu, otomatik doldurma hizmetlerinin otomatik doldurma amacıyla erişilebilirlik sanal yapısını kullanmasına olanak tanır. Özellikle otomatik doldurma API'lerini açıkça uygulamayan tarayıcılarda otomatik doldurma işlevi sağlamak için kullanışlıdır.
Otomatik doldurma hizmetinizi uyumluluk modunu kullanarak test etmek için tarayıcıyı veya uygulamayı uyumluluk modu gerektiren izin verilenler listesine açıkça ekleyin. Aşağıdaki komutu çalıştırarak izin verilenler listesinde hangi paketlerin bulunduğunu kontrol edebilirsiniz:
$ adb shell settings get global autofill_compat_mode_allowed_packages
Test ettiğiniz paket listede yoksa aşağıdaki komutu çalıştırarak paketi ekleyin. pkgX, uygulamanın paketidir:
$ adb shell settings put global autofill_compat_mode_allowed_packages pkg1[resId1]:pkg2[resId1,resId2]
Uygulama bir tarayıcıysa oluşturulan sayfanın URL'sini içeren giriş alanının kaynak kimliğini belirtmek için resIdx kullanın.
Uyumluluk modunda aşağıdaki sınırlamalar vardır:
- Hizmet,
FLAG_SAVE_ON_ALL_VIEWS_INVISIBLEişaretini kullandığında veyasetTrigger()yöntemi çağrıldığında bir kaydetme isteği tetiklenir. Uyumluluk modu kullanılırken varsayılan olarakFLAG_SAVE_ON_ALL_VIEWS_INVISIBLEayarlanır. - Düğümlerin metin değeri
onSaveRequest(SaveRequest, SaveCallback)yönteminde kullanılamayabilir.
Uyumluluk modu ve bununla ilişkili sınırlamalar hakkında daha fazla bilgi için AutofillService sınıf referansını inceleyin.