जानकारी ऑटोमैटिक भरने की सुविधा दें

पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा देने वाला ऐप्लिकेशन, उपयोगकर्ताओं के लिए फ़ॉर्म भरना आसान बनाता है. इसके लिए, यह अन्य ऐप्लिकेशन के व्यू में डेटा इंजेक्ट करता है. पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवाएं, किसी ऐप्लिकेशन के व्यू से उपयोगकर्ता का डेटा भी वापस पा सकती हैं. साथ ही, उसे बाद में इस्तेमाल करने के लिए सेव कर सकती हैं. पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवाएं, आम तौर पर उपयोगकर्ता का डेटा मैनेज करने वाले ऐप्लिकेशन उपलब्ध कराते हैं. जैसे, पासवर्ड मैनेजर.

Android 8.0 (एपीआई लेवल 26) और इसके बाद के वर्शन में उपलब्ध ऑटोफ़िल फ़्रेमवर्क की मदद से, Android पर फ़ॉर्म भरना आसान हो जाता है. उपयोगकर्ता, ऑटोमैटिक तरीके से भरने की सुविधा का फ़ायदा सिर्फ़ तब ले सकते हैं, जब उनके डिवाइस पर ऑटोमैटिक तरीके से भरने की सुविधा देने वाला कोई ऐप्लिकेशन मौजूद हो.

इस पेज पर, अपने ऐप्लिकेशन में पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा को लागू करने का तरीका बताया गया है. अगर आपको कोई ऐसा कोड सैंपल चाहिए जिससे यह पता चले कि इस सेवा को कैसे लागू किया जाता है, तो Java या Kotlin में AutofillFramework सैंपल देखें. पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवाएं कैसे काम करती हैं, इस बारे में ज़्यादा जानने के लिए, AutofillService और AutofillManager क्लास के रेफ़रंस पेज देखें.

मेनिफ़ेस्ट में एलान और अनुमतियां

पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवाएं देने वाले ऐप्लिकेशन के लिए, एलान वाला फ़ॉर्म भरना ज़रूरी है. इसमें सेवा को लागू करने के बारे में जानकारी होनी चाहिए. एलान करने के लिए, ऐप्लिकेशन मेनिफ़ेस्ट में <service> एलिमेंट शामिल करें. <service> एलिमेंट में ये एट्रिब्यूट और एलिमेंट शामिल होने चाहिए:

  • android:name एट्रिब्यूट, जो सेवा लागू करने वाले ऐप्लिकेशन में AutofillService की सबक्लास पर ले जाता है.
  • android:permission एट्रिब्यूट, जो BIND_AUTOFILL_SERVICE अनुमति का एलान करता है.
  • <intent-filter> एलिमेंट, जिसका ज़रूरी <action> चाइल्ड, android.service.autofill.AutofillService कार्रवाई के बारे में बताता है.
  • यह एक वैकल्पिक <meta-data> एलिमेंट है. इसका इस्तेमाल करके, सेवा के लिए अतिरिक्त कॉन्फ़िगरेशन पैरामीटर दिए जा सकते हैं.

यहां दिए गए उदाहरण में, पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा के एलान के बारे में बताया गया है:

<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> एलिमेंट में एक android:resource एट्रिब्यूट शामिल होता है. यह एट्रिब्यूट, एक्सएमएल रिसॉर्स पर ले जाता है. इस रिसॉर्स में सेवा के बारे में ज़्यादा जानकारी होती है. पिछले उदाहरण में मौजूद service_configuration रिसॉर्स, ऐसी गतिविधि के बारे में बताता है जिससे उपयोगकर्ता सेवा को कॉन्फ़िगर कर सकते हैं. यहां दिए गए उदाहरण में, service_configuration एक्सएमएल रिसॉर्स दिखाया गया है:

<autofill-service
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:settingsActivity="com.example.android.SettingsActivity" />

एक्सएमएल रिसॉर्स के बारे में ज़्यादा जानने के लिए, ऐप्लिकेशन के रिसॉर्स की खास जानकारी देखें.

सेवा चालू करने के लिए प्रॉम्प्ट

किसी ऐप्लिकेशन को पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा के तौर पर तब इस्तेमाल किया जाता है, जब वह BIND_AUTOFILL_SERVICE अनुमति का एलान करता है और उपयोगकर्ता उसे डिवाइस की सेटिंग में जाकर चालू करता है. कोई ऐप्लिकेशन, AutofillManager क्लास के hasEnabledAutofillServices() तरीके को कॉल करके, यह पुष्टि कर सकता है कि वह चालू की गई सेवा है या नहीं.

अगर ऐप्लिकेशन, फ़िलहाल जानकारी अपने-आप भरने की सेवा नहीं है, तो वह उपयोगकर्ता से जानकारी अपने-आप भरने की सेटिंग बदलने का अनुरोध कर सकता है. इसके लिए, उसे ACTION_REQUEST_SET_AUTOFILL_SERVICE इंटेंट का इस्तेमाल करना होगा. अगर उपयोगकर्ता, पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की ऐसी सेवा चुनता है जो कॉल करने वाले के पैकेज से मेल खाती है, तो इंटेंट RESULT_OK की वैल्यू दिखाता है.

क्लाइंट के व्यू भरना

जब उपयोगकर्ता अन्य ऐप्लिकेशन के साथ इंटरैक्ट करता है, तो पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा को क्लाइंट व्यू भरने के अनुरोध मिलते हैं. अगर पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा के पास उपयोगकर्ता का ऐसा डेटा है जो अनुरोध के मुताबिक है, तो वह जवाब में डेटा भेजती है. Android सिस्टम, उपलब्ध डेटा के साथ जानकारी अपने-आप भरने की सुविधा का यूज़र इंटरफ़ेस (यूआई) दिखाता है, जैसा कि इमेज 1 में दिखाया गया है:

जानकारी अपने-आप भरने की सुविधा के सुझाव वाले ड्रॉपडाउन में, उपलब्ध डेटासेट दिख रहा है
पहली इमेज. डेटासेट दिखाने वाला, ऑटोमैटिक भरने की सुविधा का यूज़र इंटरफ़ेस (यूआई).

ऑटोफ़िल फ़्रेमवर्क, व्यू भरने के लिए एक वर्कफ़्लो तय करता है. इसे इस तरह से डिज़ाइन किया गया है कि Android सिस्टम को ऑटोफ़िल सेवा से कम से कम समय के लिए जोड़ा जाए. हर अनुरोध में, Android सिस्टम onFillRequest() तरीके को कॉल करके, सेवा को AssistStructure ऑब्जेक्ट भेजता है.

पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा यह जांच करती है कि वह उपयोगकर्ता के पहले से सेव किए गए डेटा की मदद से, अनुरोध को पूरा कर सकती है या नहीं. अगर सेवा, अनुरोध को पूरा कर सकती है, तो वह डेटा को Dataset ऑब्जेक्ट में पैकेज करती है. सेवा, onSuccess() वाले तरीके को कॉल करती है. साथ ही, FillResponse ऑब्जेक्ट को पास करती है, जिसमें Dataset ऑब्जेक्ट होते हैं. अगर सेवा के पास अनुरोध को पूरा करने के लिए डेटा नहीं है, तो वह null को onSuccess() तरीके से पास करती है. अगर अनुरोध को प्रोसेस करने में कोई गड़बड़ी होती है, तो सेवा onFailure() तरीके को कॉल करती है. वर्कफ़्लो के बारे में ज़्यादा जानकारी के लिए, AutofillService रेफ़रंस पेज पर दिया गया ब्यौरा देखें.

यहां दिए गए कोड में, onFillRequest() तरीके का एक उदाहरण दिखाया गया है:

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;
}

किसी सेवा में एक से ज़्यादा ऐसे डेटासेट हो सकते हैं जो अनुरोध को पूरा करते हों. इस मामले में, Android सिस्टम, ऑटोमैटिक भरने की सुविधा के यूज़र इंटरफ़ेस (यूआई) में कई विकल्प दिखाता है. हर डेटासेट के लिए एक विकल्प होता है. यहां दिए गए कोड के उदाहरण में, जवाब में कई डेटासेट उपलब्ध कराने का तरीका बताया गया है:

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();

जानकारी अपने-आप भरने की सेवाएं, AssistStructure में मौजूद ViewNode ऑब्जेक्ट को नेविगेट कर सकती हैं. इससे, अनुरोध को पूरा करने के लिए ज़रूरी डेटा को अपने-आप भरने की सुविधा मिलती है. कोई सेवा, ViewNode क्लास के तरीकों का इस्तेमाल करके, ऑटोमैटिक तरीके से भरने की सुविधा का डेटा हासिल कर सकती है. जैसे, getAutofillId().

किसी सेवा को व्यू के कॉन्टेंट के बारे में जानकारी देनी चाहिए, ताकि यह पता चल सके कि वह अनुरोध को पूरा कर सकती है या नहीं. autofillHints एट्रिब्यूट का इस्तेमाल करना, किसी सेवा के लिए व्यू के कॉन्टेंट के बारे में बताने का पहला तरीका है. हालांकि, क्लाइंट ऐप्लिकेशन को अपने व्यू में एट्रिब्यूट को साफ़ तौर पर उपलब्ध कराना होगा. इसके बाद ही, यह सेवा के लिए उपलब्ध होगा.

अगर कोई क्लाइंट ऐप्लिकेशन autofillHints एट्रिब्यूट नहीं देता है, तो सेवा को कॉन्टेंट के बारे में बताने के लिए, अपने ह्यूरिस्टिक का इस्तेमाल करना चाहिए. व्यू के कॉन्टेंट के बारे में जानकारी पाने के लिए, सेवा अन्य क्लास के तरीकों का इस्तेमाल कर सकती है. जैसे, getText() या getHint(). ज़्यादा जानकारी के लिए, जानकारी ऑटोमैटिक भरने की सुविधा के लिए हिंट देना लेख पढ़ें.

यहां दिए गए उदाहरण में, AssistStructure को ट्रैवर्स करने और ViewNode ऑब्जेक्ट से, ऑटोमैटिक तरीके से भरने की सुविधा का डेटा वापस पाने का तरीका बताया गया है:

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);
    }
}

उपयोगकर्ता का डेटा सेव करना

पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा को ऐप्लिकेशन में व्यू भरने के लिए, उपयोगकर्ता के डेटा की ज़रूरत होती है. जब उपयोगकर्ता मैन्युअल तरीके से कोई व्यू भरते हैं, तो उन्हें डेटा को मौजूदा ऑटोमैटिक भरने की सेवा में सेव करने के लिए कहा जाता है, जैसा कि इमेज 2 में दिखाया गया है.

सिस्टम डायलॉग, जो उपयोगकर्ता को सेवा में ऑटोमैटिक भरने की सुविधा का डेटा सेव करने के लिए कहता है
दूसरी इमेज. ऑटोमैटिक तरीके से भरने की सुविधा का यूज़र इंटरफ़ेस (यूआई) सेव करें.

डेटा सेव करने के लिए, सेवा को यह बताना होगा कि वह आने वाले समय में इस्तेमाल करने के लिए डेटा सेव करना चाहती है. Android सिस्टम, डेटा सेव करने का अनुरोध भेजने से पहले, फ़ॉर्म भरने का अनुरोध भेजता है. इसमें सेवा को व्यू भरने का मौका मिलता है. डेटा सेव करने में अपनी दिलचस्पी दिखाने के लिए, सेवा, फ़ॉर्म भरने के अनुरोध के जवाब में SaveInfo ऑब्जेक्ट शामिल करती है. SaveInfo ऑब्जेक्ट में कम से कम यह डेटा शामिल होता है:

  • सेव किए गए उपयोगकर्ता डेटा का टाइप. SAVE_DATA की उपलब्ध वैल्यू की सूची देखने के लिए, SaveInfo पर जाएं.
  • व्यू का वह कम से कम सेट जिसमें बदलाव करने पर, सेव करने का अनुरोध ट्रिगर होता है. उदाहरण के लिए, लॉगिन फ़ॉर्म में आम तौर पर उपयोगकर्ता को username और password व्यू अपडेट करने की ज़रूरत होती है, ताकि सेव करने का अनुरोध ट्रिगर किया जा सके.

SaveInfo ऑब्जेक्ट, FillResponse ऑब्जेक्ट से जुड़ा होता है, जैसा कि कोड के इस उदाहरण में दिखाया गया है:

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();
    // ...
}

पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा, onSaveRequest() तरीके में उपयोगकर्ता के डेटा को बनाए रखने के लिए लॉजिक लागू कर सकती है. आम तौर पर, इसे क्लाइंट की गतिविधि खत्म होने के बाद या क्लाइंट ऐप्लिकेशन के commit() को कॉल करने पर कॉल किया जाता है. यहां दिए गए कोड में, onSaveRequest() तरीके का एक उदाहरण दिया गया है:

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();
}

पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवाओं को संवेदनशील डेटा सेव करने से पहले, उसे एन्क्रिप्ट (सुरक्षित) करना होगा. हालांकि, उपयोगकर्ता के डेटा में ऐसे लेबल या डेटा शामिल हो सकता है जो संवेदनशील नहीं है. उदाहरण के लिए, किसी उपयोगकर्ता खाते में ऐसा लेबल शामिल हो सकता है जो डेटा को ऑफ़िस या निजी खाते के तौर पर मार्क करता है. सेवाओं को लेबल एन्क्रिप्ट नहीं करने चाहिए. लेबल को एन्क्रिप्ट (सुरक्षित) न करने पर, सेवाएं प्रज़ेंटेशन व्यू में लेबल का इस्तेमाल कर सकती हैं. ऐसा तब होता है, जब उपयोगकर्ता ने पुष्टि न की हो. इसके बाद, उपयोगकर्ता की पुष्टि होने पर, सेवाएं लेबल को असल डेटा से बदल सकती हैं.

जानकारी ऑटोमैटिक भरने की सुविधा के यूज़र इंटरफ़ेस (यूआई) को सेव करने की प्रोसेस को कुछ समय के लिए रोकना

Android 10 से, अगर जानकारी अपने-आप भरने की सुविधा को लागू करने के लिए कई स्क्रीन का इस्तेमाल किया जाता है, तो वर्कफ़्लो—उदाहरण के लिए, उपयोगकर्ता नाम वाले फ़ील्ड के लिए एक स्क्रीन और दूसरी स्क्रीन पासवर्ड—आप इसका इस्तेमाल करके, जानकारी अपने-आप भरने की सुविधा वाले यूज़र इंटरफ़ेस (यूआई) को सेव करने की प्रोसेस को बाद के लिए शेड्यूल कर सकते हैं SaveInfo.FLAG_DELAY_SAVE फ़्लैग.

अगर यह फ़्लैग सेट है, तो SaveInfo के जवाब से जुड़ा जानकारी अपने-आप भरने की सुविधा का कॉन्टेक्स्ट लागू होने पर, जानकारी अपने-आप भरने की सुविधा को सेव करने वाला यूज़र इंटरफ़ेस (यूआई) ट्रिगर नहीं होता. इसके बजाय, फ़ॉर्म भरने के अनुरोधों को पूरा करने के लिए, उसी टास्क में किसी दूसरी गतिविधि का इस्तेमाल किया जा सकता है. इसके बाद, सेव करने के अनुरोध का इस्तेमाल करके यूज़र इंटरफ़ेस (यूआई) दिखाया जा सकता है. ज़्यादा जानकारी के लिए, SaveInfo.FLAG_DELAY_SAVE देखें.

उपयोगकर्ता की पुष्टि करना ज़रूरी है

पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवाएं, सुरक्षा का एक और लेवल उपलब्ध करा सकती हैं. इसके लिए, उपयोगकर्ता को व्यू भरने से पहले अपनी पहचान की पुष्टि करनी होगी. उपयोगकर्ता की पुष्टि करने की सुविधा को लागू करने के लिए, ये स्थितियां सही हैं:

  • ऐप्लिकेशन में मौजूद उपयोगकर्ता के डेटा को अनलॉक करने के लिए, प्राइमरी पासवर्ड या फ़िंगरप्रिंट स्कैन की ज़रूरत होती है.
  • किसी खास डेटासेट को अनलॉक करना ज़रूरी हो. जैसे, कार्ड पुष्टि कोड (सीवीसी) का इस्तेमाल करके क्रेडिट कार्ड की जानकारी को अनलॉक करना.

अगर डेटा अनलॉक करने से पहले, सेवा को उपयोगकर्ता की पुष्टि करनी ज़रूरी है, तो सेवा बॉयलरप्लेट डेटा या लेबल दिखा सकती है. साथ ही, पुष्टि करने वाले Intent के बारे में बता सकती है. अगर पुष्टि करने की प्रोसेस पूरी होने के बाद, अनुरोध को प्रोसेस करने के लिए आपको अतिरिक्त डेटा की ज़रूरत है, तो इंटेंट में ऐसा डेटा जोड़ा जा सकता है. इसके बाद, पुष्टि करने की गतिविधि, आपके ऐप्लिकेशन में AutofillService क्लास को डेटा वापस भेज सकती है.

यहां दिए गए कोड के उदाहरण में, यह बताने का तरीका बताया गया है कि अनुरोध के लिए पुष्टि करना ज़रूरी है:

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();

गतिविधि की पुष्टि होने के बाद, उसे setResult() तरीके को कॉल करना होगा. साथ ही, RESULT_OK वैल्यू को पास करना होगा और EXTRA_AUTHENTICATION_RESULT को FillResponse ऑब्जेक्ट पर सेट करना होगा. इसमें, भरा हुआ डेटासेट शामिल होता है. यहां दिए गए कोड के उदाहरण से पता चलता है कि पुष्टि करने की प्रोसेस पूरी होने के बाद, नतीजा कैसे दिखाया जाता है:

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);

अगर क्रेडिट कार्ड के डेटासेट को अनलॉक करना है, तो सेवा एक यूज़र इंटरफ़ेस (यूआई) दिखा सकती है. इसमें सीवीसी मांगा जाता है. डेटासेट के अनलॉक होने तक, डेटा को छिपाया जा सकता है. इसके लिए, बॉयलरप्लेट डेटा दिखाया जा सकता है. जैसे, बैंक का नाम और क्रेडिट कार्ड नंबर के आखिरी चार अंक. यहां दिए गए उदाहरण में, डेटासेट के लिए पुष्टि करने की ज़रूरी शर्त जोड़ने और उपयोगकर्ता के सीवीसी डालने तक डेटा छिपाने का तरीका बताया गया है:

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();

गतिविधि से सीवीसी की पुष्टि होने के बाद, उसे setResult() तरीके को कॉल करना चाहिए. साथ ही, RESULT_OK वैल्यू पास करनी चाहिए और EXTRA_AUTHENTICATION_RESULT अतिरिक्त को Dataset ऑब्जेक्ट पर सेट करना चाहिए. इस ऑब्जेक्ट में क्रेडिट कार्ड नंबर और उसकी समयसीमा खत्म होने की तारीख शामिल होती है. नया डेटासेट, उस डेटासेट की जगह ले लेता है जिसकी पुष्टि करनी ज़रूरी है. साथ ही, व्यू तुरंत भर जाते हैं. यहां दिए गए कोड में, उपयोगकर्ता से सीवीसी मिलने के बाद डेटासेट को वापस करने का उदाहरण दिखाया गया है:

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);

डेटा को लॉजिकल ग्रुप में व्यवस्थित करें

पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवाएं, डेटा को लॉजिकल ग्रुप में व्यवस्थित करती हैं. इससे अलग-अलग डोमेन के कॉन्सेप्ट को अलग-अलग रखा जाता है. इस पेज पर, इन लॉजिकल ग्रुप को पार्टिशन कहा जाता है. यहां दी गई सूची में, पार्टिशन और फ़ील्ड के सामान्य उदाहरण दिए गए हैं:

  • क्रेडेंशियल, जिसमें उपयोगकर्ता नाम और पासवर्ड फ़ील्ड शामिल हैं.
  • पता, जिसमें सड़क, शहर, राज्य, और पिन कोड फ़ील्ड शामिल हैं.
  • पेमेंट की जानकारी, जिसमें क्रेडिट कार्ड नंबर, समयसीमा खत्म होने की तारीख, और पुष्टि करने के लिए कोड वाले फ़ील्ड शामिल हैं.

डेटा को सही तरीके से बांटने वाली, पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा, अपने उपयोगकर्ताओं के डेटा को बेहतर तरीके से सुरक्षित रख पाती है. इसके लिए, वह डेटासेट में एक से ज़्यादा पार्टिशन का डेटा ज़ाहिर नहीं करती. उदाहरण के लिए, क्रेडेंशियल वाले डेटासेट में क्रेडिट/डेबिट कार्ड की जानकारी शामिल करने की ज़रूरत नहीं है. डेटा को अलग-अलग हिस्सों में व्यवस्थित करने से, आपकी सेवा किसी अनुरोध को पूरा करने के लिए ज़रूरी जानकारी का कम से कम हिस्सा दिखा पाती है.

डेटा को अलग-अलग हिस्सों में व्यवस्थित करने से, सेवाएं उन गतिविधियों को भर पाती हैं जिनमें कई हिस्सों के व्यू होते हैं. साथ ही, क्लाइंट ऐप्लिकेशन को कम से कम काम का डेटा भेजा जाता है. उदाहरण के लिए, ऐसी गतिविधि पर विचार करें जिसमें उपयोगकर्ता नाम, पासवर्ड, सड़क, और शहर के व्यू शामिल हों. साथ ही, ऑटोमैटिक भरने की ऐसी सेवा जिसमें यह डेटा शामिल हो:

विभाजन फ़ील्ड 1 फ़ील्ड 2
क्रेडेंशियल work_username work_password
personal_username personal_password
पता work_street work_city
personal_street personal_city

यह सेवा, एक ऐसा डेटासेट तैयार कर सकती है जिसमें ऑफ़िस और निजी, दोनों खातों के क्रेडेंशियल का पार्टिशन शामिल हो. जब उपयोगकर्ता कोई डेटासेट चुनता है, तो ऑटोमैटिक तरीके से भरने की सुविधा, उपयोगकर्ता की पहली पसंद के आधार पर, ऑफ़िस या निजी पता उपलब्ध करा सकती है.

कोई सेवा, अनुरोध करने वाले फ़ील्ड की पहचान कर सकती है. इसके लिए, उसे AssistStructure ऑब्जेक्ट को ट्रैवर्स करते समय, isFocused() तरीके को कॉल करना होगा. इससे सेवा, सही पार्टिशन डेटा के साथ FillResponse तैयार कर पाती है.

एसएमएस से मिलने वाले वन-टाइम कोड को ऑटोमैटिक तरीके से भरने की सुविधा

पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा, उपयोगकर्ता को SMS Retriever API का इस्तेमाल करके भेजे गए वन-टाइम कोड भरने में मदद कर सकती है.

इस सुविधा का इस्तेमाल करने के लिए, इन शर्तों को पूरा करना ज़रूरी है:

  • पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा, Android 9 (एपीआई लेवल 28) या इसके बाद के वर्शन पर चल रही हो.
  • उपयोगकर्ता, ऑटोमैटिक तरीके से भरने वाली सेवा को मैसेज से, एक बार इस्तेमाल किए जाने वाले कोड पढ़ने की अनुमति देता है.
  • जिस ऐप्लिकेशन के लिए ऑटोमैटिक भरने की सुविधा दी जा रही है वह पहले से ही वन-टाइम कोड पढ़ने के लिए, एसएमएस रिट्रीवर एपीआई का इस्तेमाल नहीं कर रहा है.

पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा, SmsCodeAutofillClient का इस्तेमाल कर सकती है. यह सेवा, Google Play services के 19.0.56 या इसके बाद के वर्शन से SmsCodeRetriever.getAutofillClient() को कॉल करके उपलब्ध होती है.

जानकारी ऑटोमैटिक भरने वाली सेवा में इस एपीआई का इस्तेमाल करने के लिए, ये मुख्य चरण अपनाएं:

  1. जानकारी ऑटोमैटिक भरने की सेवा में, SmsCodeAutofillClient से hasOngoingSmsRequest का इस्तेमाल करें. इससे यह पता लगाया जा सकता है कि जिस ऐप्लिकेशन के पैकेज के नाम के लिए जानकारी ऑटोमैटिक भरी जा रही है उसके लिए कोई अनुरोध चालू है या नहीं. अगर false मिलता है, तो पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा को सिर्फ़ सुझाव का प्रॉम्प्ट दिखाना चाहिए.
  2. ऑटोमैटिक तरीके से भरने की सेवा में, SmsCodeAutofillClient से checkPermissionState का इस्तेमाल करके देखें कि ऑटोमैटिक तरीके से भरने की सेवा को, एक बार इस्तेमाल होने वाले कोड ऑटोमैटिक तरीके से भरने की अनुमति है या नहीं. अनुमति की यह स्थिति NONE, GRANTED या DENIED हो सकती है. पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा को NONE और GRANTED स्टेटस के लिए, सुझाव का प्रॉम्प्ट दिखाना चाहिए.
  3. ऑटोमैटिक तरीके से भरने की सुविधा की पुष्टि करने की गतिविधि में, SmsRetriever.SEND_PERMISSION अनुमति का इस्तेमाल करके BroadcastReceiver को रजिस्टर करें. इससे, एसएमएस कोड उपलब्ध होने पर, SmsCodeRetriever.SMS_CODE_RETRIEVED_ACTION को कोड का नतीजा मिल सकेगा.
  4. एसएमएस से भेजे गए वन-टाइम कोड को सुनने के लिए, SmsCodeAutofillClient पर startSmsCodeRetriever को कॉल करें. अगर उपयोगकर्ता, ऑटोमैटिक तरीके से भरने वाली सेवा को एसएमएस से वन-टाइम कोड पाने की अनुमति देता है, तो यह सेवा पिछले एक से पांच मिनट में मिले एसएमएस मैसेज खोजती है.

    अगर पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा को वन-टाइम कोड पढ़ने के लिए उपयोगकर्ता की अनुमति का अनुरोध करना है, तो हो सकता है कि startSmsCodeRetriever से मिले Task को ResolvableApiException के साथ फ़ेल कर दिया जाए. अगर ऐसा होता है, तो आपको ResolvableApiException.startResolutionForResult() तरीके को कॉल करना होगा, ताकि अनुमति के अनुरोध के लिए सहमति वाला डायलॉग बॉक्स दिखाया जा सके.

  5. इंटेंट से एसएमएस कोड का नतीजा पाएं. इसके बाद, ऑटोमैटिक भरने के रिस्पॉन्स के तौर पर एसएमएस कोड दिखाएं.

Chrome पर ऑटोमैटिक तरीके से भरने की सुविधा चालू करना

Chrome, तीसरे पक्ष की ऑटोमैटिक भरने की सेवाओं को फ़ॉर्म ऑटोमैटिक भरने की अनुमति देता है. इससे उपयोगकर्ताओं को बेहतर और आसान अनुभव मिलता है. पासवर्ड, पासकी, और पते और पेमेंट डेटा जैसी अन्य जानकारी को ऑटोमैटिक तरीके से भरने के लिए, तीसरे पक्ष की सेवाओं का इस्तेमाल किया जा सकता है. इसके लिए, उपयोगकर्ताओं को Chrome की सेटिंग में जाकर, जानकारी ऑटोमैटिक तरीके से भरने की कोई दूसरी सेवा को चुनना होगा.

Chrome की सेटिंग में, 'जानकारी ऑटोमैटिक भरने की कोई दूसरी सेवा' टॉगल चालू दिख रहा है
तीसरी इमेज. Chrome की सेटिंग में, "जानकारी ऑटोमैटिक भरने की कोई दूसरी सेवा" टॉगल चालू है.

Android पर Chrome और आपकी सेवा के साथ, उपयोगकर्ताओं को जानकारी अपने-आप भरने की सुविधा का सबसे अच्छा अनुभव देने के लिए, सेवा देने वाले व्यक्ति या कंपनियों को अपने उपयोगकर्ताओं को Chrome की सेटिंग में जाकर, सेवा देने वाली अपनी पसंदीदा कंपनी की जानकारी देने के लिए बढ़ावा देना चाहिए.

उपयोगकर्ताओं को टॉगल चालू करने में मदद करने के लिए, डेवलपर ये काम कर सकते हैं:

  • Chrome की सेटिंग के बारे में क्वेरी करना और यह जानना कि उपयोगकर्ता, पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की तीसरे पक्ष की सेवा का इस्तेमाल करना चाहता है या नहीं.
  • Chrome के सेटिंग पेज का डीप लिंक, जहां उपयोगकर्ता तीसरे पक्ष की जानकारी ऑटोमैटिक भरने की सेवाएं चालू कर सकते हैं.

कंपैटबिलिटी मोड के लिए, Chrome के ज़्यादा से ज़्यादा वर्शन तय करें

Chrome ने वर्शन 137 से, कंपैटिबिलिटी मोड के साथ काम करना बंद कर दिया है. इसकी जगह, Android पर ऑटोमैटिक तरीके से भरने की सुविधा का इस्तेमाल किया जा रहा है. कंपैटिबिलिटी मोड चालू रखने से, ऐप्लिकेशन के हैंग या क्रैश होने से जुड़ी समस्याएं हो सकती हैं. Chrome पैकेज के उन वर्शन की जानकारी दें जो स्थिरता के लिए, साथ काम करने वाले मोड के साथ काम करते हैं.

<autofill-service>
  ...
  <compatibility-package android:name="com.android.chrome" android:maxLongVersionCode="711900039" />
  <compatibility-package android:name="com.chrome.beta" android:maxLongVersionCode="711900039" />
  <compatibility-package android:name="com.chrome.dev" android:maxLongVersionCode="711900039" />
  <compatibility-package android:name="com.chrome.canary" android:maxLongVersionCode="711900039" />
  ...
</autofill-service>

Chrome की सेटिंग पढ़ें

कोई भी ऐप्लिकेशन यह पता लगा सकता है कि Chrome, 3P ऑटोमैटिक तरीके से भरने की सुविधा का इस्तेमाल करता है या नहीं. इस सुविधा की मदद से, Chrome को Android पर जानकारी अपने-आप भरने की सुविधा इस्तेमाल करने की अनुमति मिलती है. Chrome, Android के ContentProvider का इस्तेमाल करके, यह जानकारी देता है. अपने Android मेनिफ़ेस्ट में बताएं कि आपको किन चैनलों की सेटिंग पढ़नी हैं:

<uses-permission android:name="android.permission.READ_USER_DICTIONARY"/>
<queries>
 <!-- To Query Chrome Beta: -->
 <package android:name="com.chrome.beta" />

 <!-- To Query Chrome Stable: -->
 <package android:name="com.android.chrome" />
</queries>

इसके बाद, कॉन्टेंट यूआरआई बनाकर उस जानकारी का अनुरोध करने के लिए, Android के ContentResolver का इस्तेमाल करें:

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 के सेटिंग पेज पर डीप लिंक करने के लिए, Android Intent का इस्तेमाल करें. इस पेज पर जाकर, उपयोगकर्ता तीसरे पक्ष की, फ़ॉर्म ऑटोमैटिक तरीके से भरने की सुविधा चालू कर सकते हैं. इस उदाहरण में दिखाए गए तरीके से, कार्रवाई और कैटगरी को कॉन्फ़िगर करना न भूलें:

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);

ऑटोमैटिक तरीके से जानकारी भरने की बेहतर सुविधा के लिए स्थितियां

ऑटोमैटिक तरीके से भरने की सुविधा का इस्तेमाल इन स्थितियों में करें:

कीबोर्ड के साथ इंटिग्रेट करना

Android 11 से, यह प्लैटफ़ॉर्म कीबोर्ड और अन्य इनपुट-मेथड एडिटर (आईएमई) को, पुलडाउन मेन्यू का इस्तेमाल करने के बजाय, इनलाइन में जानकारी अपने-आप भरने के सुझाव दिखाने की अनुमति देता है. जानकारी ऑटोमैटिक भरने की सेवा इस सुविधा के साथ कैसे काम कर सकती है, इस बारे में ज़्यादा जानने के लिए, कीबोर्ड के साथ जानकारी ऑटोमैटिक भरने की सुविधा को इंटिग्रेट करना लेख पढ़ें.

डेटासेट को पेज के हिसाब से बांटना

जानकारी ऑटोमैटिक भरने की सुविधा का बड़ा रिस्पॉन्स, Binder ऑब्जेक्ट के लिए तय किए गए लेन-देन के साइज़ से ज़्यादा हो सकता है. यह ऑब्जेक्ट, अनुरोध को प्रोसेस करने के लिए ज़रूरी रिमोट ऑब्जेक्ट को दिखाता है. इन स्थितियों में Android सिस्टम को अपवाद दिखाने से रोकने के लिए, FillResponse को छोटा रखा जा सकता है. इसके लिए, एक बार में 20 से ज़्यादा Dataset ऑब्जेक्ट न जोड़ें. अगर आपके जवाब के लिए ज़्यादा डेटासेट की ज़रूरत है, तो ऐसा डेटासेट जोड़ा जा सकता है जिससे उपयोगकर्ताओं को पता चले कि ज़्यादा जानकारी मौजूद है. साथ ही, चुने जाने पर डेटासेट का अगला ग्रुप वापस लाया जा सकता है. ज़्यादा जानकारी के लिए, addDataset(Dataset) देखें.

एक से ज़्यादा स्क्रीन पर डेटा सेव करना

ऐप्लिकेशन अक्सर एक ही गतिविधि के दौरान, उपयोगकर्ता के डेटा को कई स्क्रीन पर बांटते हैं. जैसे, नए उपयोगकर्ता खाते बनाने के लिए. उदाहरण के लिए, हो सकता है कि पहली स्क्रीन पर उपयोगकर्ता नाम और दूसरी स्क्रीन पर पासवर्ड मांगा जाए. इन स्थितियों में, जानकारी अपने-आप भरने की सेवा को तब तक इंतज़ार करना चाहिए, जब तक उपयोगकर्ता सभी ज़रूरी फ़ील्ड में डेटा नहीं डाल देता. इसके बाद ही, जानकारी अपने-आप भरने की सेवा को सेव करने का यूज़र इंटरफ़ेस (यूआई) दिखाना चाहिए. इस तरह की स्थितियों से निपटने के लिए, यह तरीका अपनाएं:

  1. जानकारी ऑटोमैटिक भरने के पहले अनुरोध में, जवाब में क्लाइंट स्टेट बंडल जोड़ें. इसमें स्क्रीन पर मौजूद अधूरे फ़ील्ड के लिए, जानकारी ऑटोमैटिक भरने की सुविधा के आईडी शामिल होते हैं.
  2. फ़ॉर्म भरने के दूसरे अनुरोध में, क्लाइंट स्टेट बंडल को वापस पाएं. साथ ही, क्लाइंट स्टेट से पिछले अनुरोध में सेट किए गए, ऑटोमैटिक तरीके से भरने की सुविधा वाले आईडी पाएं. इसके बाद, इन आईडी और FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE फ़्लैग को, दूसरे जवाब में इस्तेमाल किए गए SaveInfo ऑब्जेक्ट में जोड़ें.
  3. सेव करने के अनुरोध में, हर फ़ील्ड की वैल्यू पाने के लिए, सही FillContext ऑब्जेक्ट का इस्तेमाल करें. हर फ़िल रिक्वेस्ट के लिए एक फ़िल कॉन्टेक्स्ट होता है.

    ज़्यादा जानकारी के लिए, डेटा को कई स्क्रीन में बांटकर सेव करना लेख पढ़ें.

हर अनुरोध के लिए, शुरू करने और बंद करने का लॉजिक उपलब्ध कराना

जब भी जानकारी अपने-आप भरने की सुविधा का अनुरोध किया जाता है, तब Android सिस्टम सेवा से बाइंड हो जाता है और उसके onConnected() तरीके को कॉल करता है. सेवा के अनुरोध को प्रोसेस करने के बाद, Android सिस्टम onDisconnected() तरीके को कॉल करता है और सेवा से अनबाइंड हो जाता है. अनुरोध को प्रोसेस करने से पहले चलने वाला कोड देने के लिए, onConnected() को लागू किया जा सकता है. साथ ही, अनुरोध को प्रोसेस करने के बाद चलने वाला कोड देने के लिए, onDisconnected() को लागू किया जा सकता है.

ऑटोमैटिक तरीके से भरने की सुविधा के यूज़र इंटरफ़ेस (यूआई) को पसंद के मुताबिक बनाना

जानकारी अपने-आप भरने की सेवाएं, ऑटोमैटिक तरीके से सेव होने वाले यूज़र इंटरफ़ेस (यूआई) को पसंद के मुताबिक बना सकती हैं. इससे उपयोगकर्ताओं को यह तय करने में मदद मिलती है कि उन्हें सेवा को अपना डेटा सेव करने की अनुमति देनी है या नहीं. सेवाएं, टेक्स्ट या पसंद के मुताबिक बनाए गए व्यू के ज़रिए, सेव की गई जानकारी के बारे में ज़्यादा जानकारी दे सकती हैं. सेवाएं, सेव करने के अनुरोध को रद्द करने वाले बटन का लुक भी बदल सकती हैं. साथ ही, जब उपयोगकर्ता उस बटन पर टैप करता है, तो उन्हें इसकी सूचना मिलती है. ज़्यादा जानकारी के लिए, SaveInfo रेफ़रंस पेज देखें.

कंपैटबिलिटी मोड

कंपैटबिलिटी मोड की मदद से, जानकारी अपने-आप भरने की सेवाएं, सुलभता वर्चुअल स्ट्रक्चर का इस्तेमाल कर सकती हैं. इससे, जानकारी अपने-आप भरने की सुविधा का इस्तेमाल किया जा सकता है. यह खास तौर पर उन ब्राउज़र में ऑटोमैटिक भरने की सुविधा देने के लिए मददगार है जो ऑटोमैटिक भरने वाले एपीआई को साफ़ तौर पर लागू नहीं करते हैं.

कंपैटबिलिटी मोड का इस्तेमाल करके, पासवर्ड अपने-आप भरने, मैनेज करने, और सेव करने की सेवा को टेस्ट करने के लिए, उस ब्राउज़र या ऐप्लिकेशन को अनुमति वाली सूची में जोड़ें जिसके लिए कंपैटबिलिटी मोड की ज़रूरत है. यह देखने के लिए कि अनुमति वाली सूची में पहले से कौनसे पैकेज मौजूद हैं, यह कमांड चलाएं:

$ adb shell settings get global autofill_compat_mode_allowed_packages

अगर आपको जिस पैकेज की जांच करनी है वह सूची में नहीं है, तो यह कमांड चलाकर उसे जोड़ें. यहां pkgX, ऐप्लिकेशन का पैकेज है:

$ adb shell settings put global autofill_compat_mode_allowed_packages pkg1[resId1]:pkg2[resId1,resId2]

अगर ऐप्लिकेशन एक ब्राउज़र है, तो resIdx का इस्तेमाल करके, उस इनपुट फ़ील्ड का रिसॉर्स आईडी बताएं जिसमें रेंडर किए गए पेज का यूआरएल शामिल है.

कंपैटबिलिटी मोड की ये सीमाएं हैं:

  • सेव करने का अनुरोध तब ट्रिगर होता है, जब सेवा FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE फ़्लैग का इस्तेमाल करती है या setTrigger() तरीके को कॉल किया जाता है. कंपैटिबिलिटी मोड का इस्तेमाल करने पर, FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE को डिफ़ॉल्ट रूप से सेट किया जाता है.
  • ऐसा हो सकता है कि नोड की टेक्स्ट वैल्यू, onSaveRequest(SaveRequest, SaveCallback) तरीके में उपलब्ध न हो.

कंपैटिबिलिटी मोड के बारे में ज़्यादा जानने के लिए, AutofillService क्लास रेफ़रंस देखें. इसमें इससे जुड़ी सीमाओं के बारे में भी बताया गया है.