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

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

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 ได้ คุณสามารถซ่อนข้อมูลไว้จนกว่าจะปลดล็อกชุดข้อมูลได้โดยแสดงข้อมูลสำเร็จรูป เช่น ชื่อธนาคารและตัวเลข 4 หลักสุดท้ายของหมายเลขบัตรเครดิต ตัวอย่างต่อไปนี้จะแสดงวิธีการ ต้องมีการตรวจสอบสิทธิ์สำหรับชุดข้อมูลและซ่อนข้อมูลจนกว่าผู้ใช้จะระบุ 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 เพิ่มเติมเป็น ออบเจ็กต์ 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_password
ชื่อผู้ใช้ส่วนตัว รหัสผ่านส่วนตัว
ที่อยู่ 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. ในกิจกรรมการตรวจสอบสิทธิ์แบบป้อนข้อความอัตโนมัติ ให้ใช้สิทธิ์ SmsRetriever.SEND_PERMISSION เพื่อลงทะเบียน BroadcastReceiver ที่รอรับ 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 จะถามรหัสผ่าน ในสถานการณ์เช่นนี้ บริการป้อนข้อความอัตโนมัติจะต้องรอจนกว่าผู้ใช้จะป้อนข้อมูล ก่อนที่จะแสดง 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_SAVE_ON_ALL_VIEWS_INVISIBLE หรือ setTrigger() เมธอด ระบบจะตั้งค่า FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE เป็นค่าเริ่มต้นเมื่อ โดยใช้โหมดความเข้ากันได้
  • ค่าข้อความของโหนดอาจไม่พร้อมใช้งานในวิธี onSaveRequest(SaveRequest, SaveCallback)

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