Otomatik doldurma hizmeti, kullanıcıların diğer uygulamaların görünümlerine veri ekleyerek form doldurmalarını kolaylaştıran bir uygulamadır. Otomatik doldurma hizmetleri ayrıca bir uygulamanın görünümlerinden 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 seviyesi 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 bir otomatik doldurma hizmetinin nasıl uygulanacağı açıklanmaktadır. Bir hizmetin nasıl uygulanacağını gösteren bir kod örneği arıyorsanız Java veya Kotlin'deki AutofillFramework örneğine bakın.
Otomatik doldurma hizmetlerinin işleyiş şekli hakkında daha fazla ayrıntı için AutofillService
ve AutofillManager
sınıflarının referans sayfalarına bakın.
Manifest beyanları ve izinler
Otomatik doldurma hizmetleri sağlayan uygulamalar, hizmetin uygulanma şeklini açıklayan bir beyan içermelidir. Bildirimi belirtmek için uygulama manifest dosyasına bir <service>
öğesi ekleyin. <service>
öğesi aşağıdaki özellikleri ve öğeleri içermelidir:
android:name
özniteliği, hizmeti uygulayan uygulamadaAutofillService
alt sınıfına işaret eder.BIND_AUTOFILL_SERVICE
iznini açıklayanandroid:permission
özelliği.- Zorunlu
<action>
alt öğesininandroid.service.autofill.AutofillService
işlemini belirttiği<intent-filter>
öğesi. - Hizmete ek yapılandırma parametreleri sağlamak için kullanabileceğiniz isteğe bağlı
<meta-data>
öğesidir.
Aşağıdaki örnekte bir otomatik doldurma hizmeti beyanı gösterilmektedir:
<service
android:name=".MyAutofillService"
android:label="My Autofill Service"
android:permission="android.permission.BIND_AUTOFILL_SERVICE">
<intent-filter>
<action android:name="android.service.autofill.AutofillService" />
</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 android:resource
özelliği içerir.
Önceki örnekteki service_configuration
kaynağı, kullanıcıların hizmeti yapılandırmasına izin veren 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.SettingsActivity" />
XML kaynakları hakkında daha fazla bilgi için Uygulama kaynaklarına genel bakış başlıklı makaleyi inceleyin.
Hizmeti etkinleştirme istemi
Uygulama, BIND_AUTOFILL_SERVICE
iznini tanımladıktan ve kullanıcı bu izni cihaz ayarlarında etkinleştirdikten sonra otomatik doldurma hizmeti olarak kullanılır. Bir uygulama, AutofillManager
sınıfının hasEnabledAutofillServices()
yöntemini çağırarak hizmetin o anda etkinleştirilmiş olan hizmet olup olmadığını doğrulayabilir.
Uygulama geçerli otomatik doldurma hizmeti değilse ACTION_REQUEST_SET_AUTOFILL_SERVICE
amacını 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 niyet RESULT_OK
değerini döndürür.
Müşteri görünümlerini doldurma
Kullanıcı diğer uygulamalarla etkileşimde bulunduğunda otomatik doldurma hizmeti, istemci görünümlerini doldurma istekleri alır. Otomatik doldurma hizmeti, isteği karşılayan kullanıcı verilerine sahipse verileri yanıtta gönderir. Android sistemi, Şekil 1'de gösterildiği gibi mevcut verilerle 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 indirmek için 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, daha önce depoladığı kullanıcı verileriyle isteği karşılayıp karşılayamayacağını kontrol eder. İsteği karşılayabilirse hizmet, verileri Dataset
nesnelerinde paketler. Hizmet, Dataset
nesnelerini içeren bir FillResponse
nesnesi ileterek onSuccess()
yöntemini çağırır. Hizmet, isteği karşılayacak veriye sahip değilse null
öğesini onSuccess()
yöntemine geçirir.
İstek işlenirken bir hata oluşursa hizmet, bunun yerine onFailure()
yöntemini çağırır. İş akışının ayrıntılı açıklaması için AutofillService
referans sayfasındaki açıklamaya bakın.
Aşağıdaki kodda onFillRequest()
yönteminin bir örneği gösterilmektedir:
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 hizmet, isteği karşılayan birden fazla veri kümesine sahip 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
öğesindeki ViewNode
nesnelerine gidebilir. Bir hizmet, getAutofillId()
gibi ViewNode
sınıfı yöntemlerini kullanarak otomatik doldurma verilerini alabilir.
Bir hizmetin, isteği karşılayıp karşılayamayacağını kontrol etmek için görünümün içeriğini açıklayabilmesi gerekir. Bir hizmetin, bir görünümün içeriğini açıklamak için kullanması gereken ilk yaklaşım autofillHints
özelliğini kullanmaktır. Ancak istemci uygulamaları, özelliği hizmette kullanıma sunulmadan önce kendi görünümlerinde açıkça sağlamalıdır.
İstemci uygulaması autofillHints
özelliğini sağlamıyorsa hizmetin içeriği açıklamak için kendi bulgularını kullanması gerekir.
Hizmet, görünümün içeriği hakkında bilgi almak 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 bölümüne bakın.
Aşağıdaki örnekte, AssistStructure
verisinden nasıl yararlanılacağı 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 hizmetlerinin, uygulamalardaki görünümleri doldurmak için kullanıcı verilerine ihtiyacı vardır. Kullanıcılar bir görünümü manuel olarak doldurduklarında, onlardan Şekil 2'de gösterildiği gibi verileri geçerli otomatik doldurma hizmetine kaydetmeleri istenir.
Verileri kaydetmek için hizmet, verileri gelecekte kullanmak üzere saklamak istediğini belirtmelidir. Android sistemi verileri kaydetmek için bir istek göndermeden önce, hizmetin görünümleri doldurma fırsatı bulduğu bir doldurma isteği olur. Hizmet, verileri kaydetmek istediğini belirtmek için doldurma isteğine bir SaveInfo
nesnesi ekler. SaveInfo
nesnesi en azından şu verileri içerir:
- Kaydedilen kullanıcı verilerinin türü. Kullanılabilir
SAVE_DATA
değerlerinin listesi içinSaveInfo
bölümüne bakın. - Kaydetme isteğini tetiklemek için değiştirilmesi gereken minimum görünüm grubu.
Örneğin, bir giriş formu genellikle bir kaydetme isteğini tetiklemek için kullanıcının
username
vepassword
görünümlerini güncellemesini gerektirir.
SaveInfo
nesnesi, aşağıdaki kod örneğinde gösterildiği gibi 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 tutmak için bir 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ı verilerinde hassas olmayan etiketler veya veriler bulunabilir. Örneğin, bir kullanıcı hesabı, verileri iş veya kişisel hesap olarak işaretleyen bir etiket içerebilir. Hizmetler, etiketleri şifrelememelidir. Kullanıcı kimlik doğrulaması yapmamışsa hizmetler, etiketleri şifrelemeyerek sunum görünümlerinde etiketleri kullanabilir. Bunun ardından hizmetler, kullanıcı kimlik doğrulaması yaptıktan sonra etiketleri gerçek verilerle değiştirebilir.
Otomatik doldurma kaydetme kullanıcı arayüzünü ertele
Android 10'dan itibaren, otomatik doldurma iş akışı uygulamak için birden fazla ekran kullanıyorsanız (ör. kullanıcı adı alanı için bir ekran ve şifre için başka bir ekran) SaveInfo.FLAG_DELAY_SAVE
işaretini kullanarak otomatik doldurmanın kaydetme kullanıcı arayüzünü erteleyebilirsiniz.
Bu işaret ayarlanırsa SaveInfo
yanıtıyla ilişkili otomatik doldurma içeriği kaydedildiğinde otomatik doldurma kaydetme kullanıcı arayüzü tetiklenmez. Bunun yerine, gelecekteki doldurma isteklerini göndermek ve ardından kaydetme isteği ile kullanıcı arayüzünü göstermek için aynı görev içinde ayrı bir etkinlik kullanabilirsiniz. Daha fazla bilgi için SaveInfo.FLAG_DELAY_SAVE
adresini inceleyin.
Kullanıcı kimlik doğrulamasını zorunlu kıl
Otomatik doldurma hizmetleri, görünümleri doldurmadan önce kullanıcının kimlik 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 uygun 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, ortak veriler veya bir etiket sunabilir ve kimlik doğrulama işlemini yapan Intent
'ı belirtebilir. Kimlik doğrulama akışı tamamlandıktan sonra isteği işlemek için ek verilere ihtiyaç duyarsanız bu tür verileri amaca ekleyebilirsiniz. Böylece 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
ekstra değerini doldurulan veri kümesini içeren FillResponse
nesnesine ayarlamalıdır. Aşağıdaki kod, kimlik doğrulama akışı tamamlandığında sonucun nasıl döndürüleceğine dair bir örnek gösterir:
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);
Bir kredi kartı veri kümesinin kilidinin açılması gereken senaryoda, hizmet, CVC'yi isteyen bir kullanıcı arayüzü görüntüleyebilir. Banka adı ve kredi kartı numarasının son dört hanesi gibi ortak verileri sunarak veri kümesinin kilidi açılana kadar verileri gizleyebilirsiniz. Aşağıdaki örnekte, bir veri kümesi için kimlik doğrulamasının nasıl zorunlu tutulacağı ve kullanıcı CVC sağlayana 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 setResult()
yöntemini çağırarak RESULT_OK
değerini iletmeli ve ekstra EXTRA_AUTHENTICATION_RESULT
öğesini kredi kartı numarası ile 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 anında doldurulur. Aşağıdaki kod, kullanıcı CVC'yi sağladıktan sonra veri kümesinin nasıl döndürüleceğine dair bir örnek gösterir:
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ı alanlardan gelen kavramları birbirinden ayıran mantıksal gruplar halinde düzenlemelidir. Bu sayfada, bu mantıksal gruplara bölümler adı verilir. Aşağıdaki listede bölüm ve alanlarla ilgili tipik örnekler gösterilmektedir:
- Kullanıcı adı ve şifre alanlarını içeren kimlik bilgileri.
- Cadde, ş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ümleyen bir otomatik doldurma hizmeti, bir veri kümesinde birden fazla bölümde yer alan verileri göstermeyerek kullanıcılarının verilerini daha iyi koruyabilir. Örneğin, kimlik bilgilerini içeren bir veri kümesinin ödeme bilgilerini içermesine gerek yoktur. Verilerin bölümler halinde düzenlenmesi, hizmetinizin bir isteği karşılamak için gereken minimum miktarda ilgili bilgiyi açığa çıkarmasına olanak tanır.
Verilerin bölümler halinde düzenlenmesi, istemci uygulamasına minimum miktarda alakalı veri gönderirken hizmetlerin birden fazla bölümden görüntülemeleri olan etkinlikleri doldurmasına olanak tanır. Örneğin, kullanıcı adı, şifre, sokak ve şehir görünümleri içeren bir etkinlik ve aşağıdaki verileri içeren bir otomatik doldurma hizmeti düşünün:
Bölüm | Alan 1 | Alan 2 |
---|---|---|
Kimlik Bilgisi | iş_kullanıcı_adı | iş_şifresi |
kişisel_kullanıcı_adı | kişisel_şifre | |
Adres | iş_sokağı | iş_şehir |
kişisel_sokak | kişisel_şehir |
Bu hizmet, hem iş hesapları hem de kişisel hesaplar için kimlik bilgisi bölümünü içeren bir veri kümesi hazırlayabilir. Kullanıcı bir veri kümesi seçtiğinde, sonraki bir otomatik doldurma yanıtı kullanıcının ilk tercihine bağlı olarak iş adresini veya kişisel adresi sağlayabilir.
Bir hizmet, AssistStructure
nesnesinden geçiş yaparken isFocused()
yöntemini çağırarak isteğin geldiği alanı tanımlayabilir. Bu, hizmetin uygun bölümlendirme verileriyle bir FillResponse
hazırlamasına olanak tanır.
Tek seferlik SMS kodunu otomatik doldurma
Otomatik doldurma hizmetiniz, SMS Retriever API'yi kullanarak SMS ile gönderilen tek seferlik kodları doldurma konusunda kullanıcıya yardımcı olabilir.
Bu özelliği kullanmak için aşağıdaki şartların karşılanması gerekir:
- Otomatik doldurma hizmeti, Android 9 (API düzeyi 28) veya sonraki sürümlerde çalışıyor.
- Kullanıcı, otomatik doldurma hizmetinizin SMS'teki tek seferlik kodları okumasına izin verdiğinde.
- Otomatik doldurma özelliğini sağladığınız uygulama, tek kullanımlık kodları okumak için halihazırda SMS Retriever API'sini kullanmıyor.
Otomatik doldurma hizmetiniz SmsCodeAutofillClient
kullanabilir. Bu hizmet, Google Play Hizmetleri 19.0.56 veya sonraki bir sürümden SmsCodeRetriever.getAutofillClient()
çağrısı yapılarak kullanılabilir.
Bu API'yi bir otomatik doldurma hizmetinde kullanmanın başlıca adımları şunlardır:
- Otomatik doldurma hizmetinde, otomatik olarak doldurduğunuz uygulamanın paket adı için etkin bir istek olup olmadığını belirlemek amacıyla
SmsCodeAutofillClient
kaynağındanhasOngoingSmsRequest
değerini kullanın. Otomatik doldurma hizmetiniz yalnızca bu,false
sonucunu döndürürse bir öneri istemi görüntülemelidir. - Otomatik doldurma hizmetinde, otomatik doldurma hizmetinin tek seferlik kodları otomatik doldurma izni olup olmadığını kontrol etmek için
SmsCodeAutofillClient
tarihinden itibarencheckPermissionState
değerini kullanın. Bu izin durumuNONE
,GRANTED
veyaDENIED
olabilir. Otomatik doldurma hizmeti,NONE
veGRANTED
durumları için bir öneri istemi görüntülemelidir. - Otomatik doldurma kimlik doğrulama etkinliğinde, SMS kodu sonucu mümkün olduğunda
SmsCodeRetriever.SMS_CODE_RETRIEVED_ACTION
tarafından dinlenecek birBroadcastReceiver
içinSmsRetriever.SEND_PERMISSION
iznini kullanın. SMS ile gönderilen tek seferlik kodları dinlemeye başlamak için
SmsCodeAutofillClient
numaralı telefondanstartSmsCodeRetriever
numaralı telefonu arayın. Kullanıcı, SMS'ten bir kullanımlık kodlar almak için otomatik doldurma hizmetinize izin verirse bu mesaj, son bir ila beş dakika içinde alınan SMS mesajlarını arar.Otomatik doldurma hizmetinizin tek seferlik kodları okumak için kullanıcı izni istemesi gerekiyorsa
startSmsCodeRetriever
tarafından döndürülenTask
, birResolvableApiException
hatası vererek başarısız olabilir. Bu durumda, izin isteği için izin iletişim kutusunu görüntülemek üzereResolvableApiException.startResolutionForResult()
yöntemini çağırmanız gerekir.Niyetten SMS kodu sonucunu alın ve ardından SMS kodunu otomatik doldurma yanıtı olarak döndürün.
Gelişmiş otomatik doldurma senaryoları
- Klavyeyle entegre et
- Android 11'den itibaren platform, klavyelerin ve diğer giriş yöntemi düzenleyicilerinin (IME'ler) otomatik doldurma önerilerini bir açılır menü kullanmak yerine satır içinde göstermesine olanak tanıyor. Otomatik doldurma hizmetinizin bu işlevi nasıl destekleyebileceği hakkında daha fazla bilgi için Otomatik doldurmayı klavyelerle entegre etme bölümüne bakın.
- Sayfalara ayırma veri kümeleri
- Büyük bir otomatik doldurma yanıtı, isteğin işlenmesi için gereken yeniden taşınabilir nesneyi temsil eden
Binder
nesnesinin izin verilen işlem boyutunu aşabilir. Android sisteminin bu senaryolarda istisna oluşturmasını önlemek için aynı anda 20'den fazlaDataset
nesne ekleyerekFillResponse
değerini 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 getiren bir veri kümesi ekleyebilirsiniz. Daha fazla bilgi içinaddDataset(Dataset)
sayfasına bakın. - Verileri birden çok ekrana bölünmüş olarak kaydedin
Uygulamalar, özellikle yeni bir kullanıcı hesabı oluşturmak için kullanılan etkinliklerde genellikle aynı etkinlikte birden fazla ekranda kullanıcı verilerini böler. Örneğin, ilk ekranda bir kullanıcı adı, kullanıcı adı varsa ikinci ekranda şifre sorulur. Bu tür durumlarda, otomatik doldurma kaydetme arayüzünün gösterilmesi için otomatik doldurma hizmetinin, kullanıcı her iki alana da girene kadar beklemesi gerekir. Bu tür senaryoları ele almak için şu adımları izleyin:
- İlk doldurma isteğinde, ekrandaki kısmi alanların otomatik doldurma kimliklerini içeren yanıta bir istemci durumu paketi ekleyin.
- İkinci doldurma isteğinde istemci durumu paketini alın, önceki istekte ayarlanan otomatik doldurma kimliklerini istemci durumundan alın ve bu kimliklerle
FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE
işaretini ikinci yanıtta kullanılanSaveInfo
nesnesine ekleyin. - Kaydetme isteğinde her bir alanın değerini almak için uygun
FillContext
nesnelerini kullanın. Her doldurma isteği için bir dolgu 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 sökme mantığı sağlayın
Her otomatik doldurma isteği olduğunda Android sistemi hizmete bağlanır ve ilgili
onConnected()
yöntemini çağırır. Hizmet, isteği işledikten sonra Android sistemionDisconnected()
yöntemini çağırır ve hizmet ile bağlantısını kaldırır. Bir isteği işlemeden önce çalışan kod sağlamak içinonConnected()
, isteği işledikten sonra çalışan kod sağlamak için deonDisconnected()
uygulayabilirsiniz.- Otomatik doldurma için kaydetme kullanıcı arayüzünü özelleştirme
Otomatik doldurma hizmetleri, kullanıcıların, hizmetin verilerini kaydetmesine izin vermek isteyip istemediklerine karar vermelerine yardımcı olmak için otomatik doldurma kaydetme kullanıcı arayüzünü özelleştirebilir. Hizmetler, basit bir metin veya özelleştirilmiş görünüm aracılığıyla nelerin kaydedildiği hakkında 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. Daha fazla bilgi için
SaveInfo
referans sayfasını inceleyin.- Uyumluluk modu
Uyumluluk modu, otomatik doldurma hizmetlerinin otomatik doldurma amacıyla erişilebilirlik sanal yapısını kullanmasına olanak tanır. Bu, özellikle otomatik doldurma API'lerini açıkça uygulamayan tarayıcılarda otomatik doldurma işlevi sağlamak için kullanışlıdır.
Uyumluluk modunu kullanarak otomatik doldurma hizmetinizi test etmek için uyumluluk modu gerektiren tarayıcıyı veya uygulamayı açıkça izin verilenler listesine ekleyin. Aşağıdaki komutu çalıştırarak hangi paketlerin izin verilenler listesine eklenmiş olduğ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 ekleyin. Burada
pkgX
, uygulama 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 geçerlidir:
- Kayıt isteği, hizmet
FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE
işaretini kullandığında veyasetTrigger()
yöntemi çağrıldığında tetiklenir. Uyumluluk modu kullanılırkenFLAG_SAVE_ON_ALL_VIEWS_INVISIBLE
varsayılan olarak ayarlanır. - Düğümlerin metin değeri
onSaveRequest(SaveRequest, SaveCallback)
yönteminde kullanılamayabilir.
Uyumluluk moduyla ilişkili sınırlamalar da dahil olmak üzere uyumluluk modu hakkında daha fazla bilgi için AutofillService
sınıf referansına bakın.