สร้างบริการป้อนข้อความอัตโนมัติ

บริการป้อนข้อความอัตโนมัติเป็นแอปที่ช่วยให้ผู้ใช้กรอกแบบฟอร์มได้ง่ายขึ้นด้วยการแทรกข้อมูลลงในมุมมองของแอปอื่นๆ บริการป้อนข้อความอัตโนมัติยังดึงข้อมูลผู้ใช้จากมุมมองในแอปและจัดเก็บไว้เพื่อใช้ในภายหลังได้ด้วย บริการป้อนข้อความอัตโนมัติมักให้บริการโดยแอปที่จัดการข้อมูลผู้ใช้ เช่น ในฐานะเครื่องมือจัดการรหัสผ่าน

Android ทำให้การกรอกแบบฟอร์มง่ายขึ้นด้วยเฟรมเวิร์กการป้อนข้อความอัตโนมัติที่มีอยู่ใน Android 8.0 (API ระดับ 26) ขึ้นไป ผู้ใช้สามารถใช้ประโยชน์จากการป้อนข้อความอัตโนมัติ เมื่อมีแอปที่ให้บริการป้อนข้อความอัตโนมัติบน อุปกรณ์

หน้านี้จะแสดงวิธีใช้บริการป้อนข้อความอัตโนมัติในแอปของคุณ หากคุณ หากต้องการดูตัวอย่างโค้ดที่แสดงวิธีนำบริการไปใช้ โปรดดู ตัวอย่าง AutofillFramework ใน Java หรือ Kotlin ดูรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการทำงานของบริการป้อนข้อความอัตโนมัติได้ที่หน้าข้อมูลอ้างอิงสำหรับคลาส AutofillService และ AutofillManager

การประกาศและสิทธิ์ของไฟล์ Manifest

แอปที่ให้บริการป้อนข้อความอัตโนมัติต้องมีการประกาศที่อธิบายถึง การใช้บริการ หากต้องการระบุประกาศ ให้ใส่องค์ประกอบ <service> ในไฟล์ Manifest ของแอป องค์ประกอบ <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 ที่ชี้ไปยังทรัพยากร XML พร้อมรายละเอียดเพิ่มเติมเกี่ยวกับบริการ ทรัพยากร service_configuration ในตัวอย่างก่อนหน้านี้ระบุกิจกรรมที่อนุญาตให้ผู้ใช้กําหนดค่าบริการ ตัวอย่างต่อไปนี้แสดงทรัพยากร XML service_configuration

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

โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับทรัพยากร XML ได้ที่ภาพรวมทรัพยากรของแอป

ข้อความแจ้งให้เปิดใช้บริการ

มีการใช้แอปเป็นบริการป้อนข้อความอัตโนมัติหลังจากที่ประกาศ สิทธิ์ BIND_AUTOFILL_SERVICE และผู้ใช้เปิดใช้ในอุปกรณ์ การตั้งค่า แอปสามารถตรวจสอบได้ว่าเป็นบริการที่เปิดใช้อยู่ในปัจจุบันหรือไม่โดยเรียกใช้เมธอด hasEnabledAutofillServices() ของคลาส AutofillManager

หากแอปไม่ใช่บริการป้อนข้อความอัตโนมัติปัจจุบัน แอปจะขอให้ผู้ใช้เปลี่ยนการตั้งค่าการป้อนข้อความอัตโนมัติได้โดยใช้ Intent ACTION_REQUEST_SET_AUTOFILL_SERVICE Intent จะแสดงผลค่า RESULT_OK หากผู้ใช้เลือกบริการป้อนข้อความอัตโนมัติที่ตรงกับแพ็กเกจของผู้เรียก

กรอกข้อมูลมุมมองของลูกค้า

บริการป้อนข้อความอัตโนมัติได้รับคำขอให้กรอกข้อมูลมุมมองของลูกค้าเมื่อผู้ใช้ โต้ตอบกับแอปอื่นๆ หากบริการป้อนข้อความอัตโนมัติมีข้อมูลผู้ใช้ที่ตรงกับคำขอ ระบบจะส่งข้อมูลในการตอบกลับ ระบบ Android แสดง UI ป้อนข้อความอัตโนมัติด้วยข้อมูลที่พร้อมใช้งาน ดังแสดงในรูปที่ 1:

UI การป้อนข้อความอัตโนมัติ

รูปที่ 1 UI การป้อนข้อความอัตโนมัติแสดงชุดข้อมูล

เฟรมเวิร์กการป้อนข้อความอัตโนมัติจะกำหนดเวิร์กโฟลว์ในการกรอกข้อมูลมุมมองที่ออกแบบมาเพื่อ ลดเวลาที่ระบบ Android ผูกกับบริการป้อนข้อความอัตโนมัติ ใน แต่ละคำขอ ระบบ Android จะส่งออบเจ็กต์ AssistStructure ไปยังบริการโดย กำลังโทรหา onFillRequest()

บริการป้อนข้อความอัตโนมัติจะตรวจสอบว่าสามารถตอบสนองคำขอด้วยข้อมูลผู้ใช้ที่ ที่จัดเก็บไว้ก่อนหน้านี้ ถ้าตอบสนองคำขอได้ แพ็กเกจบริการ ข้อมูลใน 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;
}

บริการหนึ่งอาจมีชุดข้อมูลมากกว่า 1 ชุดที่ตรงกับคำขอ ในกรณีนี้ ระบบ Android จะแสดงตัวเลือกหลายรายการ (1 รายการสำหรับชุดข้อมูลแต่ละชุด) ใน UI การป้อนข้อความอัตโนมัติ ตัวอย่างโค้ดต่อไปนี้จะแสดงวิธีการ ให้ชุดข้อมูลหลายชุดในการตอบกลับ:

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

บริการป้อนข้อความอัตโนมัติจะไปยังส่วนต่างๆ ของออบเจ็กต์ ViewNode ได้ใน AssistStructureเพื่อเรียกข้อมูลการป้อนข้อความอัตโนมัติ ที่จำเป็นต่อการดำเนินการตามคำขอ บริการสามารถเรียกข้อมูลการป้อนข้อความอัตโนมัติโดยใช้ วิธีการของ 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

UI การบันทึกการป้อนข้อความอัตโนมัติ

รูปที่ 2 UI บันทึกการป้อนข้อความอัตโนมัติ

ในการบันทึกข้อมูล บริการต้องระบุว่าตนสนใจที่จะจัดเก็บข้อมูล ไว้ใช้ในอนาคต ก่อนที่ระบบ 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();
}

บริการป้อนข้อความอัตโนมัติต้องเข้ารหัสข้อมูลที่ละเอียดอ่อนก่อนที่จะเก็บไว้ อย่างไรก็ตาม ข้อมูลผู้ใช้อาจรวมถึงป้ายกำกับหรือข้อมูลที่ไม่ใช่ข้อมูลที่ละเอียดอ่อน ตัวอย่างเช่น บัญชีผู้ใช้อาจมีป้ายกำกับที่ทําเครื่องหมายข้อมูลว่าเป็นบัญชีงานหรือส่วนตัว บริการต้องไม่เข้ารหัสป้ายกำกับ การไม่เข้ารหัสป้ายกำกับจะทำให้บริการต่างๆ ใช้ป้ายกำกับในมุมมองการนำเสนอได้หากผู้ใช้ไม่ได้ตรวจสอบสิทธิ์ จากนั้นบริการจะแทนที่ป้ายกำกับด้วยข้อมูลจริงได้หลังจากที่ผู้ใช้ตรวจสอบสิทธิ์แล้ว

เลื่อน UI การบันทึกการป้อนข้อความอัตโนมัติ

ใน Android 10 เป็นต้นไป หากคุณใช้หลายหน้าจอเพื่อใช้การป้อนข้อความอัตโนมัติ เช่น หน้าจอหนึ่งสำหรับช่องชื่อผู้ใช้ และอีกหน้าจอหนึ่งสำหรับ รหัสผ่าน คุณสามารถเลื่อน UI การบันทึกการป้อนข้อความอัตโนมัติได้โดยใช้ SaveInfo.FLAG_DELAY_SAVE แจ้ง

หากตั้งค่า Flag นี้ ระบบจะไม่ทริกเกอร์ UI บันทึกการป้อนข้อความอัตโนมัติเมื่อมีการบันทึกบริบทการป้อนข้อความอัตโนมัติที่เชื่อมโยงกับการตอบกลับ SaveInfo อย่างไรก็ตาม คุณสามารถ ใช้กิจกรรมแยกต่างหากภายในงานเดียวกันเพื่อส่งคำขอเติมเต็มในอนาคตและ จากนั้นแสดง UI ผ่านคำขอบันทึก สำหรับข้อมูลเพิ่มเติม โปรดดู SaveInfo.FLAG_DELAY_SAVE

ต้องมีการตรวจสอบสิทธิ์ผู้ใช้

บริการป้อนข้อความอัตโนมัติสามารถช่วยเพิ่มความปลอดภัยอีกขั้นโดย ผู้ใช้เพื่อตรวจสอบสิทธิ์ก่อนที่จะกรอกข้อมูลมุมมอง สถานการณ์ต่อไปนี้เหมาะที่จะใช้การตรวจสอบสิทธิ์ผู้ใช้

  • ข้อมูลผู้ใช้ในแอปต้องปลดล็อกโดยใช้รหัสผ่านหลักหรือการสแกนลายนิ้วมือ
  • คุณต้องปลดล็อกชุดข้อมูลที่ต้องการ เช่น รายละเอียดบัตรเครดิต โดยใช้รหัสยืนยันบัตร (CVC)

ในกรณีที่บริการกำหนดให้มีการตรวจสอบสิทธิ์ผู้ใช้ก่อนปลดล็อก ข้อมูล บริการก็สามารถนำเสนอข้อมูลสำเร็จรูปหรือป้ายกำกับและระบุ Intent ซึ่งดูแล การตรวจสอบสิทธิ์ หากต้องการข้อมูลเพิ่มเติมเพื่อประมวลผลคำขอหลังจากทำตามขั้นตอนการตรวจสอบสิทธิ์เสร็จแล้ว คุณสามารถเพิ่มข้อมูลดังกล่าวลงใน 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);

ในกรณีที่ต้องปลดล็อกชุดข้อมูลบัตรเครดิต บริการจะแสดง UI ที่ขอ CVC คุณจะซ่อนข้อมูลได้จนกว่าชุดข้อมูลจะ ปลดล็อกด้วยการนำเสนอข้อมูลสำเร็จรูป เช่น ชื่อธนาคารและ ตัวเลขสี่หลักสุดท้ายของหมายเลขบัตรเครดิต ตัวอย่างต่อไปนี้จะแสดงวิธีการ ต้องมีการตรวจสอบสิทธิ์สำหรับชุดข้อมูลและซ่อนข้อมูลจนกว่าผู้ใช้จะระบุ CVC:

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

เมื่อกิจกรรมตรวจสอบ CVC แล้ว ก็ควรเรียกใช้เมธอด setResult() โดยส่งค่า RESULT_OK และตั้งค่า EXTRA_AUTHENTICATION_RESULT extra เป็นออบเจ็กต์ Dataset ที่มีหมายเลขบัตรเครดิตและวันที่หมดอายุ ชุดข้อมูลใหม่จะแทนที่ชุดข้อมูลที่ต้องตรวจสอบสิทธิ์ และระบบจะป้อนข้อมูลพร็อพเพอร์ตี้ทันที โค้ดต่อไปนี้แสดงตัวอย่างวิธีแสดงผลชุดข้อมูลเมื่อผู้ใช้ระบุ CVC

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 พาร์ติชันใน ชุดข้อมูล เช่น ชุดข้อมูลที่มีข้อมูลเข้าสู่ระบบไม่จำเป็นต้องมีข้อมูลการชำระเงิน การจัดระเบียบข้อมูลในพาร์ติชันช่วยให้ เพื่อแสดงข้อมูลที่เกี่ยวข้องในปริมาณขั้นต่ำที่จำเป็นต่อการ ทำตามคำขอ

การจัดระเบียบข้อมูลในพาร์ติชันช่วยให้บริการสามารถป้อนข้อมูลในกิจกรรมที่มีมุมมองจากหลายพาร์ติชันขณะส่งข้อมูลที่เกี่ยวข้องไปยังแอปไคลเอ็นต์ในปริมาณที่น้อยที่สุดได้ ตัวอย่างเช่น พิจารณากิจกรรมที่มีมุมมองสำหรับชื่อผู้ใช้ รหัสผ่าน ถนน และเมือง รวมถึงบริการป้อนข้อความอัตโนมัติที่มีข้อมูลต่อไปนี้

พาร์ติชัน ฟิลด์ 1 ฟิลด์ 2
ข้อมูลรับรอง ชื่อผู้ใช้งาน รหัสผ่านที่ทำงาน
ชื่อผู้ใช้ส่วนตัว รหัสผ่านส่วนตัว
ที่อยู่ work_street work_city
personal_street personal_city

บริการนี้สามารถเตรียมชุดข้อมูลที่มีพาร์ติชันข้อมูลเข้าสู่ระบบสำหรับทั้งบัญชีงานและบัญชีส่วนตัว เมื่อผู้ใช้เลือกชุดข้อมูลแล้ว การตอบกลับที่ป้อนข้อความอัตโนมัติครั้งถัดไปอาจแสดงที่อยู่งานหรือที่อยู่ส่วนตัว ทั้งนี้ขึ้นอยู่กับตัวเลือกแรกของผู้ใช้

บริการจะระบุช่องที่เป็นต้นทางของคําขอได้โดยเรียกใช้เมธอด isFocused()ขณะที่ไปยังออบเจ็กต์ AssistStructure ซึ่งช่วยให้ เพื่อเตรียม FillResponse ด้วยข้อมูลพาร์ติชันที่เหมาะสม

ป้อนรหัสแบบใช้ครั้งเดียวทาง SMS โดยอัตโนมัติ

บริการป้อนข้อความอัตโนมัติช่วยผู้ใช้ในการป้อนรหัสแบบครั้งเดียวที่ส่งผ่าน SMS โดยใช้ SMS Retriever API

คุณต้องมีคุณสมบัติตรงตามข้อกำหนดต่อไปนี้จึงจะใช้ฟีเจอร์นี้ได้

  • บริการป้อนข้อความอัตโนมัติกำลังทำงานใน Android 9 (API ระดับ 28) ขึ้นไป
  • ผู้ใช้ให้ความยินยอมให้บริการป้อนข้อความอัตโนมัติอ่านรหัสแบบครั้งเดียวจาก SMS
  • แอปพลิเคชันที่คุณให้การป้อนข้อความอัตโนมัติยังไม่ได้ใช้ SMS Retriever API เพื่ออ่านรหัสแบบใช้ครั้งเดียว

บริการป้อนข้อความอัตโนมัติสามารถใช้ SmsCodeAutofillClient พร้อมให้บริการเมื่อโทรไปที่ SmsCodeRetriever.getAutofillClient() จาก Google Play บริการ 19.0.56 ขึ้นไป

ขั้นตอนหลักในการใช้ API นี้ในบริการป้อนข้อความอัตโนมัติมีดังนี้

  1. ในบริการป้อนข้อความอัตโนมัติ ให้ใช้ hasOngoingSmsRequest จาก SmsCodeAutofillClient เพื่อดูว่ามีคำขอที่ใช้งานอยู่สำหรับชื่อแพ็กเกจของแอปพลิเคชันที่คุณกรอกข้อความอัตโนมัติอยู่หรือไม่ การป้อนข้อความอัตโนมัติของคุณ บริการต้องแสดงพรอมต์คำแนะนำก็ต่อเมื่อแสดง false เท่านั้น
  2. ในบริการป้อนข้อความอัตโนมัติ ให้ใช้ checkPermissionState จาก SmsCodeAutofillClient เพื่อตรวจสอบว่าบริการป้อนข้อความอัตโนมัติมีสิทธิ์ป้อนรหัสแบบครั้งเดียวโดยอัตโนมัติหรือไม่ สถานะสิทธิ์นี้อาจเป็น NONE, GRANTED หรือ DENIED บริการป้อนข้อความอัตโนมัติต้องแสดงข้อความแจ้งคำแนะนำ สำหรับ NONE และ GRANTED รัฐ
  3. ในกิจกรรมการตรวจสอบสิทธิ์การป้อนข้อความอัตโนมัติ ให้ใช้ สิทธิ์ในการจดทะเบียน BroadcastReceiver ของ SmsRetriever.SEND_PERMISSION กำลังฟัง SmsCodeRetriever.SMS_CODE_RETRIEVED_ACTION เพื่อรับ SMS โค้ดเมื่อพร้อมใช้งาน
  4. โทร startSmsCodeRetriever ในวันที่ SmsCodeAutofillClient เพื่อเริ่มฟังรหัสแบบใช้ครั้งเดียวที่ส่งทาง SMS หากผู้ใช้ให้สิทธิ์บริการป้อนข้อความอัตโนมัติในการดึงข้อมูลแบบครั้งเดียว รหัสจาก SMS ซึ่งจะมองหาข้อความ SMS ที่ได้รับในช่วงหนึ่งถึงห้าครั้งล่าสุด นาทีนับจากนี้

    หากบริการป้อนข้อความอัตโนมัติต้องขอสิทธิ์จากผู้ใช้ในการอ่านแบบครั้งเดียว Task ที่แสดงผลโดย startSmsCodeRetriever อาจล้มเหลวโดยมี ResolvableApiException ส่งคืนแล้ว ในกรณีนี้ คุณต้องเรียกใช้เมธอด ResolvableApiException.startResolutionForResult() เพื่อแสดงกล่องโต้ตอบความยินยอมสําหรับคําขอสิทธิ์

  5. รับผลลัพธ์รหัส SMS จาก Intent แล้วแสดงรหัส SMS เป็นการตอบกลับแบบป้อนข้อความอัตโนมัติ

สถานการณ์การป้อนข้อความอัตโนมัติขั้นสูง

ผสานรวมกับแป้นพิมพ์
สำหรับ Android 11 เป็นต้นไป แพลตฟอร์มนี้จะอนุญาตให้แป้นพิมพ์ และตัวแก้ไขวิธีการป้อนข้อมูลอื่นๆ (IME) เพื่อแสดงคำแนะนำการป้อนข้อความอัตโนมัติในบรรทัด แทนการใช้เมนูแบบเลื่อนลง ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่บริการป้อนข้อความอัตโนมัติรองรับฟังก์ชันการทำงานนี้ได้ที่หัวข้อผสานรวมการป้อนข้อความอัตโนมัติกับแป้นพิมพ์
จัดชุดข้อมูลเป็นหน้า
คำตอบการเติมข้อความอัตโนมัติขนาดใหญ่อาจเกินขนาดธุรกรรมที่อนุญาตของออบเจ็กต์ Binder ที่แสดงถึงออบเจ็กต์ระยะไกลที่จําเป็นสําหรับประมวลผลคําขอ หากต้องการป้องกันไม่ให้ระบบ Android แสดงข้อยกเว้นในสถานการณ์เหล่านี้ คุณสามารถทำให้ FillResponse มีขนาดไม่ใหญ่โดยการเพิ่มออบเจ็กต์ Dataset ไม่เกิน 20 รายการในแต่ละครั้ง หากคำตอบต้องใช้ชุดข้อมูลเพิ่ม คุณสามารถเพิ่มชุดข้อมูลที่จะแจ้งให้ผู้ใช้ทราบว่ามีข้อมูลเพิ่มเติมและดึงชุดข้อมูลกลุ่มถัดไปเมื่อเลือก ดูข้อมูลเพิ่มเติมได้ที่ addDataset(Dataset)
บันทึกข้อมูลที่แยกออกเป็นหลายหน้าจอ

แอปมักแยกข้อมูลผู้ใช้ในหลายหน้าจอในกิจกรรมเดียวกัน โดยเฉพาะในกิจกรรมที่ใช้สร้างบัญชีผู้ใช้ใหม่ เช่น หน้าจอแรกจะขอชื่อผู้ใช้ และหากชื่อผู้ใช้นั้นใช้ได้ หน้าจอที่ 2 จะขอรหัสผ่าน ในกรณีเหล่านี้ บริการป้อนข้อความอัตโนมัติต้องรอจนกว่าผู้ใช้จะป้อนข้อมูลในทั้ง 2 ช่องก่อนจึงจะแสดง UI บันทึกการป้อนข้อความอัตโนมัติได้ ทำตาม ในการรับมือกับสถานการณ์ดังกล่าว

  1. ในคำขอกรอกข้อมูลแรก ให้เพิ่มกลุ่มสถานะไคลเอ็นต์ในการตอบกลับซึ่งมีรหัสป้อนข้อความอัตโนมัติของฟิลด์บางส่วนที่แสดงในหน้าจอ
  2. ในคำขอที่ 2 ดึงข้อมูลกลุ่มสถานะไคลเอ็นต์ รับชุดรหัสป้อนข้อความอัตโนมัติ ในคำขอก่อนหน้าจากสถานะไคลเอ็นต์ แล้วเพิ่มรหัสเหล่านี้รวมถึง FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE ไปยังออบเจ็กต์ SaveInfo ที่ใช้ในคำตอบที่ 2
  3. ในคำขอบันทึก ใช้ FillContext ที่เหมาะสม เพื่อหาค่าของแต่ละช่อง บริบทการโฆษณาจะอยู่ที่ 1 รายการต่อคำขอ

ดูข้อมูลเพิ่มเติมได้ที่บันทึกเมื่อข้อมูลมีการแยกออกเป็นหลายหน้าจอ

ระบุตรรกะการเริ่มต้นและการเลิกใช้งานสำหรับคำขอแต่ละรายการ

ทุกครั้งที่มีคำขอป้อนข้อความอัตโนมัติ ระบบ Android จะเชื่อมโยงกับบริการและเรียกใช้เมธอด onConnected() เมื่อบริการประมวลผลคําขอแล้ว ระบบ Android จะเรียกใช้เมธอด onDisconnected() และยกเลิกการเชื่อมโยงกับบริการ คุณสามารถใช้ onConnected() เพื่อระบุโค้ดที่จะทำงานก่อนประมวลผลคำขอ และ onDisconnected() เพื่อระบุโค้ดที่จะทำงานหลังจากประมวลผลคำขอ

ปรับแต่ง UI การบันทึกการป้อนข้อความอัตโนมัติ

บริการป้อนข้อความอัตโนมัติสามารถปรับแต่ง UI บันทึกการป้อนข้อความอัตโนมัติเพื่อช่วยผู้ใช้ตัดสินใจว่าต้องการอนุญาตให้บริการบันทึกข้อมูลหรือไม่ บริการต่างๆ ข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่บันทึกผ่านข้อความธรรมดาหรือ ผ่านมุมมองที่กำหนดเอง บริการต่างๆ ยังเปลี่ยนรูปลักษณ์ของปุ่มด้วย ที่ยกเลิกคำขอบันทึกและรับการแจ้งเตือนเมื่อผู้ใช้แตะ โปรดดูข้อมูลเพิ่มเติมที่หน้าข้อมูลอ้างอิง SaveInfo

โหมดความเข้ากันได้

โหมดความเข้ากันได้จะช่วยให้บริการป้อนข้อความอัตโนมัติใช้การช่วยเหลือพิเศษได้ โครงสร้างเสมือน เพื่อการป้อนข้อความอัตโนมัติ มีประโยชน์อย่างยิ่งสำหรับการให้บริการฟังก์ชันป้อนข้อความอัตโนมัติในเบราว์เซอร์ที่ ไม่ใช้ API สำหรับการป้อนข้อความอัตโนมัติอย่างชัดเจน

หากต้องการทดสอบบริการป้อนข้อความอัตโนมัติโดยใช้โหมดความเข้ากันได้ อนุญาตเบราว์เซอร์หรือแอปที่ต้องใช้โหมดความเข้ากันได้ คุณสามารถดู แพ็กเกจที่อยู่ในรายการที่อนุญาตอยู่แล้วโดยเรียกใช้คำสั่งต่อไปนี้

$ 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 เพื่อระบุรหัสทรัพยากรของช่องป้อนข้อมูลที่มี URL ของหน้าที่แสดงผล

โหมดความเข้ากันได้มีข้อจำกัดต่อไปนี้

  • คำขอบันทึกจะทริกเกอร์เมื่อบริการใช้ Flag FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE หรือเรียกใช้เมธอด setTrigger() ระบบจะตั้งค่า FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE เป็นค่าเริ่มต้นเมื่อ โดยใช้โหมดความเข้ากันได้
  • ค่าข้อความของโหนดอาจไม่พร้อมใช้งานในวิธี onSaveRequest(SaveRequest, SaveCallback)

โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับโหมดความเข้ากันได้ รวมถึงข้อจำกัด ที่เกี่ยวข้อง โปรดดูที่ AutofillService ข้อมูลอ้างอิงของชั้นเรียน