針對自動填入功能最佳化應用程式

使用標準檢視的應用程式可與自動填入架構搭配使用,無須進行特殊設定。您也可以最佳化應用程式與該架構搭配使用的方式。

設定自動填入環境

本節說明如何為應用程式設定基本自動填入功能。

設定自動填入服務

您必須在裝置上設定自動填入服務,應用程式才能使用自動填入架構。雖然多數搭載 Android 8.0 (API 級別 26) 以上版本的手機和平板電腦皆隨附自動填入服務,但我們建議您在測試應用程式時使用測試服務,例如 Android 自動填入架構範例中的自動填入服務。使用模擬器時,請明確設定自動填入服務,因為模擬器可能沒有預設的服務。

從範例應用程式安裝測試自動填入服務後,請依序前往「Settings」>「System」>「Languages & input」>「Advanced」>「Input assistance」>「Autofill service」,啟用自動填入服務。

如要進一步瞭解如何設定模擬器並測試自動填入服務,請參閱「透過自動填入服務測試應用程式」。

為自動填入服務提供提示

自動填入服務會利用經驗法則判斷各檢視畫面的類型。不過,如果您的應用程式仰賴這些經驗法則,自動填入行為可能會在您更新應用程式時意外變更。為確保自動填入服務正確識別應用程式的板型規格,請提供自動填入提示。

您可以使用 android:autofillHints 屬性設定自動填入提示。以下範例是在 EditText 上設定 "password" 提示:

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:autofillHints="password" />

您也可以使用 setAutofillHints() 方法,以程式輔助方式設定提示,如以下範例所示:

Kotlin

val password = findViewById<EditText>(R.id.password)
password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD)

Java

EditText password = findViewById(R.id.password);
password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD);

加入預先定義的提示常數

自動填入架構不會驗證提示。提示將直接傳遞至自動填入服務,不會經過變更或驗證。您可以使用任何值,但 View 類別和 AndroidX HintConstants 類別會包含官方支援的提示常數清單。

透過這些常數組合,即可針對常見的自動填入情境建構版面配置:

帳戶憑證

您可以在登入表單中加入帳戶憑證提示,例如 AUTOFILL_HINT_USERNAMEAUTOFILL_HINT_PASSWORD

在建立新帳戶或使用者變更名稱和密碼時,您可以使用 AUTOFILL_HINT_NEW_USERNAMEAUTOFILL_HINT_NEW_PASSWORD

信用卡資訊

系統要求信用卡資訊時,您可以使用 AUTOFILL_HINT_CREDIT_CARD_NUMBERAUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE 等提示。

針對信用卡到期日,請執行下列任一操作:

實際地址

針對實際地址表單欄位,您可以使用以下提示:

使用者姓名

要求填入使用者姓名時,可以使用下列提示:

電話號碼

針對電話號碼,您可以使用下列提示:

動態密碼 (OTP)

針對單一檢視畫面中的動態密碼,您可以使用 AUTOFILL_HINT_SMS_OTP

如果使用多個檢視畫面,且每個檢視畫面各對應至動態密碼的一個數字,您可以使用 generateSmsOtpHintForCharacterPosition() 方法,按字元產生提示。

將欄位標示有必要使用自動填入服務

您可以在應用程式的檢視畫面結構中,為自動填入服務加入個別欄位。根據預設,檢視畫面會採用 IMPORTANT_FOR_AUTOFILL_AUTO 模式,讓 Android 利用經驗法則判斷檢視畫面是否有必要使用自動填入服務。

但如果是下列檢視畫面、檢視畫面結構或活動,則不必使用自動填入服務:

  • 登入活動中的 CAPTCHA 欄位
  • 使用者建立內容的檢視畫面,例如文字或試算表編輯器
  • 遊戲中部分活動的檢視畫面,例如呈現遊戲過程的畫面

您可以使用 android:importantForAutofill 屬性,設定檢視畫面是否有必要使用自動填入服務:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:importantForAutofill="no" />

importantForAutofill 的值可設為下列任一選項:

auto
讓 Android 系統利用經驗法則,判斷檢視畫面是否有必要使用自動填入服務。
no
檢視畫面不必使用自動填入服務。
noExcludeDescendants
此檢視畫面及其子項沒有必要自動填入。
yes
此檢視畫面有必要自動填入。
yesExcludeDescendants
檢視畫面有必要使用自動填入服務,其子項則不必。

您也可以使用 setImportantForAutofill() 方法:

Kotlin

val captcha = findViewById<TextView>(R.id.captcha)
captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO)

Java

TextView captcha = findViewById(R.id.captcha);
captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);

您可以宣告前述範例用途不必使用自動填入服務,方法如下:

  • 登入活動中的 CAPTCHA 欄位:使用 android:importantForAutofill="no"IMPORTANT_FOR_AUTOFILL_NO,將檢視畫面標示為不必使用自動填入服務。
  • 使用者建立內容的檢視畫面:使用 android:importantForAutofill="noExcludeDescendants"IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,將整個檢視畫面結構標示為不必使用自動填入服務。
  • 遊戲中部分活動的檢視畫面:使用 android:importantForAutofill="noExcludeDescendants"IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,將整個檢視畫面結構標示為不必使用自動填入服務。

連結網站和行動應用程式資料

透過 Google 自動填入等自動填入服務,當應用程式與網站建立關聯後,就可在瀏覽器和 Android 裝置之間共用使用者登入資料。如果使用者在這兩個平台上選擇相同的自動填入服務,當他們登入網頁應用程式時,就可以在登入相對應的 Android 應用程式時自動填入登入憑證。

如要將 Android 應用程式與網站建立關聯,請在網站中代管具有 delegate_permission/common.get_login_creds 關係的 Digital Asset Links,然後在應用程式的 AndroidManifest.xml 檔案中宣告這個關聯。如需如何將網站與 Android 應用程式建立關聯的詳細操作說明,請參閱「啟用跨應用程式和網站的自動登入功能」。

完成自動填入工作流程

本節說明幾個特定情境,在這些情境下,您可以採取多個步驟,針對您應用程式的使用者改善自動填入功能。

判斷是否已啟用自動填入服務

使用者只要依序前往「Settings」>「System」>「Languages & input」>「Advanced」>「Input assistance」>「Autofill service」,即可啟用或停用自動填入服務,以及變更自動填入服務。應用程式無法覆寫使用者的自動填入設定,但如果使用者可使用自動填入服務,您可以在應用程式 (或應用程式的特定檢視畫面) 中,導入額外的自動填入功能。

舉例來說,如果已為使用者啟用自動填入服務,TextView 就會在溢位選單中顯示自動填入項目。如要檢查是否已為使用者啟用自動填入服務,請呼叫 AutofillManager 物件的 isEnabled() 方法。

如果使用者沒有可用的自動填入服務,為確保他們取得最佳註冊和登入體驗,請導入 One Tap 登入

強制執行自動填入要求

您有時可能需要強制執行自動填入要求,才能回應使用者動作。例如在使用者按住檢視畫面時,TextView 可提供自動填入選單項目。以下程式碼範例說明如何強制執行自動填入要求:

Kotlin

fun eventHandler(view: View) {
    val afm = requireContext().getSystemService(AutofillManager::class.java)
    afm?.requestAutofill(view)
}

Java

public void eventHandler(View view) {
    AutofillManager afm = context.getSystemService(AutofillManager.class);
    if (afm != null) {
        afm.requestAutofill(view);
    }
}

您也可以使用 cancel() 方法,取消目前的自動填入內容。如要在登入頁面上提供清除欄位的按鈕,這個方法就能派上用場。

針對挑選器控制項中的資料使用正確的自動填入類型

挑選器提供的 UI 可讓使用者變更用於儲存日期或時間資料該欄位的值,因此將挑選器與自動填入功能搭配使用時,可以發揮實用效益。例如在信用卡表單中,日期挑選器可讓使用者輸入或變更信用卡的到期日。不過在畫面上未出現挑選器的情況下,如要顯示資料,就必須使用另一個檢視畫面,例如 EditText

EditText 物件本身預期的自動填入資料類型為 AUTOFILL_TYPE_TEXT。如果您使用不同的資料類型,請建立沿用自 EditText 的自訂檢視畫面,並實作處理相對應資料類型所需的方法。舉例來說,如果是日期欄位,所實作的方法必須具備能正確處理 AUTOFILL_TYPE_DATE 類型值的邏輯。

指定自動填入資料類型時,自動填入服務可以為檢視畫面中顯示的資料建立適當的呈現方式。詳情請參閱「使用具有自動填入功能的挑選器」。

完成自動填入內容

自動填入架構會在完成自動填入內容後顯示「要儲存自動填入內容嗎?」對話方塊,以儲存使用者輸入內容,供未來使用。一般而言,系統會在活動結束時完成自動填入內容。但在某些情況下,例如登入頁面和內容畫面使用相同的活動,卻採用不同的片段時,您必須明確通知架構。在這類情況下,您可以呼叫 AutofillManager.commit() 明確完成內容。

支援自訂檢視畫面

自訂檢視畫面可以使用自動填入 API 指定對自動填入架構公開的中繼資料。某些檢視畫面可做為虛擬子項的容器,例如包含 OpenGL 轉譯 UI 的檢視畫面。這些檢視畫面必須先使用 API 指定用於應用程式的資訊結構,才能與自動填入架構搭配使用。

如果您的應用程式使用自訂檢視畫面,請考慮下列情境:

  • 自訂檢視畫面會提供「標準檢視畫面結構」或預設檢視畫面結構。
  • 自訂檢視畫面具有「虛擬結構」,或自動填入架構無法使用的檢視畫面結構。

使用標準檢視結構的自訂檢視畫面

自訂檢視畫面可定義自動填入服務運作所需的中繼資料。請確認自訂檢視畫面可適當管理中繼資料,與自動填入架構搭配使用。自訂檢視畫面必須執行下列動作:

  • 處理架構傳送給應用程式的自動填入值。
  • 為架構提供自動填入類型和值。

自動填入功能遭觸發時,自動填入架構會在檢視畫面中呼叫 autofill(),並傳送檢視畫面須使用的值。請實作 autofill(),指定自訂檢視畫面處理自動填入值的方式。

檢視畫面須覆寫 getAutofillType()getAutofillValue() 方法,分別指定自動填入類型和值。

最後,如果在目前狀態下 (例如檢視畫面已停用),使用者無法為檢視畫面提供值,自動填入功能就不得為檢視畫面填入內容。在這種情況下,getAutofillType() 必須傳回 AUTOFILL_TYPE_NONEgetAutofillValue() 必須傳回 nullautofill() 則務必不執行任何動作。

在下列情況下,必須採取額外步驟,才能在架構中正確運作:

  • 自訂檢視畫面可以編輯。
  • 自訂檢視畫面含有機密資料。

自訂檢視畫面可供編輯

如果檢視畫面可供編輯,請呼叫 AutofillManager 物件上的 notifyValueChanged(),向自動填入架構通知變更內容。

自訂檢視畫面含有機密資料

如果檢視畫面含有電子郵件地址、信用卡號碼、密碼等個人識別資訊 (PII),就必須標示為含有機密資料。

一般而言,如果檢視畫面的內容是由靜態資源提供,就不會包含機密資料;若是透過動態方式設定,則可能包含機密資料。例如,含有「enter your username」的標籤不會包含機密資料,含有「Hello, John」的標籤則包含機密資料。

根據預設,自動填入架構會假設所有資料都屬於機密資料。您可以將資料標示為非機密資料。

如要標示檢視畫面是否含有機密資料,請實作 onProvideAutofillStructure(),並呼叫 ViewStructure 物件上的 setDataIsSensitive()

以下程式碼範例說明如何將檢視畫面結構中的資料標示為非機密資料:

Kotlin

override fun onProvideAutofillStructure(structure: ViewStructure, flags: Int) {
    super.onProvideAutofillStructure(structure, flags)

    structure.setDataIsSensitive(false)
}

Java

@Override
public void onProvideAutofillStructure(ViewStructure structure, int flags) {
    super.onProvideAutofillStructure(structure, flags);

    structure.setDataIsSensitive(false);
}

如果檢視畫面只接受預先定義的值,您可以使用 setAutofillOptions() 方法,設定可用來自動填入該檢視畫面的選項。請特別注意,自動填入類型為 AUTOFILL_TYPE_LIST 的檢視畫面必須使用此方法,因為如果自動填入服務知道可用來填入檢視畫面的選項,運作效果會更好。

如果檢視畫面使用轉接程式 (例如 Spinner),也會出現類似情況。舉例來說,如果用於信用卡到期欄位中的 Spinner 是根據目前年份提供動態建立的年份,可以透過實作 Adapter 介面的 getAutofillOptions() 方法提供年份清單。

若是使用 ArrayAdapter 的檢視畫面,也可以提供值的清單。ArrayAdapter 會自動為靜態資源設定自動填入選項。如果您以動態方式提供值,請覆寫 getAutofillOptions()

使用虛擬結構的自訂檢視畫面

自動填入架構需要檢視畫面結構,才能在應用程式 UI 中編輯和儲存資訊。在下列情況中,自動填入架構無法使用檢視畫面結構:

  • 應用程式算繪 UI 時使用的是低階算繪引擎,例如 OpenGL
  • 應用程式使用 Canvas 的執行個體繪製 UI。

在這些情況下,只要實作 onProvideAutofillVirtualStructure() 並按照下列步驟操作,即可指定檢視畫面結構:

  1. 呼叫 addChildCount(),增加檢視畫面結構的子項數量。
  2. 呼叫 newChild(),新增子項。
  3. 呼叫 setAutofillId(),為子項設定自動填入 ID。
  4. 設定相關屬性,例如自動填入值和類型。
  5. 如果虛擬子項中的資料具機密性,請將 true 傳遞至 setDataIsSensitive();若不具機密性,則請傳遞 false

以下程式碼片段說明如何在虛擬結構中建立新子項:

Kotlin

override fun onProvideAutofillVirtualStructure(structure: ViewStructure, flags: Int) {

    super.onProvideAutofillVirtualStructure(structure, flags)

    // Create a new child in the virtual structure.
    structure.addChildCount(1)
    val child = structure.newChild(childIndex)

    // Set the autofill ID for the child.
    child.setAutofillId(structure.autofillId!!, childVirtualId)

    // Populate the child by providing properties such as value and type.
    child.setAutofillValue(childAutofillValue)
    child.setAutofillType(childAutofillType)

    // Some children can provide a list of values, such as when the child is
    // a spinner.
    val childAutofillOptions = arrayOf<CharSequence>("option1", "option2")
    child.setAutofillOptions(childAutofillOptions)

    // Just like other types of views, mark the data as sensitive when
    // appropriate.
    val sensitive = !contentIsSetFromResources()
    child.setDataIsSensitive(sensitive)
}

Java

@Override
public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {

    super.onProvideAutofillVirtualStructure(structure, flags);

    // Create a new child in the virtual structure.
    structure.addChildCount(1);
    ViewStructure child =
            structure.newChild(childIndex);

    // Set the autofill ID for the child.
    child.setAutofillId(structure.getAutofillId(), childVirtualId);

    // Populate the child by providing properties such as value and type.
    child.setAutofillValue(childAutofillValue);
    child.setAutofillType(childAutofillType);

    // Some children can provide a list of values, such as when the child is
    // a spinner.
    CharSequence childAutofillOptions[] = { "option1", "option2" };
    child.setAutofillOptions(childAutofillOptions);

    // Just like other types of views, mark the data as sensitive when
    // appropriate.
    boolean sensitive = !contentIsSetFromResources();
    child.setDataIsSensitive(sensitive);
}

當虛擬結構中的元素有所變更,請執行以下工作通知架構:

  • 如果變更的是子項中的焦點,請在 AutofillManager 物件上呼叫 notifyViewEntered()notifyViewExited()
  • 如果變更的是子項的值,請在 AutofillManager 物件上呼叫 notifyValueChanged()
  • 如果因使用者已完成工作流程中的某個步驟 (例如使用登入表單登入),導致檢視區塊階層無法再供使用,請在 AutofillManager 物件上呼叫 commit()
  • 如果因使用者已取消工作流程中的某個步驟 (例如輕觸會清除登入表單的按鈕),導致檢視區塊階層無效,請在 AutofillManager 物件上呼叫 cancel()

在自動填入事件中使用回呼

如果您的應用程式提供專屬的自動完成檢視畫面,您必須利用某項機制,讓應用程式根據 UI 自動填入服務能供性的變化,啟用或停用檢視畫面。自動填入架構會以 AutofillCallback 的形式提供這項機制。

這個類別提供 onAutofillEvent(View, int) 方法,每當與檢視畫面相關聯的自動填入服務狀態有所變更,應用程式就會呼叫此方法。此方法另有一個包含 childId 參數的超載版本,應用程式可將該參數與虛擬檢視畫面搭配使用。在回呼中,可用的狀態會以常數的格式定義。

您可以使用 AutofillManager 類別的 registerCallback() 方法註冊回呼。以下程式碼範例說明如何為自動填入事件宣告回呼:

Kotlin

val afm = context.getSystemService(AutofillManager::class.java)

afm?.registerCallback(object : AutofillManager.AutofillCallback() {
    // For virtual structures, override
    // onAutofillEvent(View view, int childId, int event) instead.
    override fun onAutofillEvent(view: View, event: Int) {
        super.onAutofillEvent(view, event)
        when (event) {
            EVENT_INPUT_HIDDEN -> {
                // The autofill affordance associated with the view was hidden.
            }
            EVENT_INPUT_SHOWN -> {
                // The autofill affordance associated with the view was shown.
            }
            EVENT_INPUT_UNAVAILABLE -> {
                // Autofill isn't available.
            }
        }

    }
})

Java

AutofillManager afm = getContext().getSystemService(AutofillManager.class);

afm.registerCallback(new AutofillManager.AutofillCallback() {
    // For virtual structures, override
    // onAutofillEvent(View view, int childId, int event) instead.
    @Override
    public void onAutofillEvent(@NonNull View view, int event) {
        super.onAutofillEvent(view, event);
        switch (event) {
            case EVENT_INPUT_HIDDEN:
                // The autofill affordance associated with the view was hidden.
                break;
            case EVENT_INPUT_SHOWN:
                // The autofill affordance associated with the view was shown.
                break;
            case EVENT_INPUT_UNAVAILABLE:
                // Autofill isn't available.
                break;
        }
    }
});

如要移除回呼,請使用 unregisterCallback() 方法。

自訂自動填入醒目顯示的可繪項目

檢視畫面執行自動填入作業時,平台會在該檢視畫面算繪 Drawable,用來表示已自動填入檢視畫面內容。根據預設,此可繪項目為半透明的實心矩形,其中的顏色會比背景主題色深一點。您不必變更可繪項目。不過,透過覆寫應用程式或活動所使用主題android:autofilledHighlight 項目,可以自訂可繪項目,如以下範例所示:

res/values/styles.xml

<resources>
    <style name="MyAutofilledHighlight" parent="...">
        <item name="android:autofilledHighlight">@drawable/my_drawable</item>
    </style>
</resources>

res/drawable/my_drawable.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#4DFF0000" />
</shape>

AndroidManifest.xml

<application ...
    android:theme="@style/MyAutofilledHighlight">
<!-- or -->
<activity ...
    android:theme="@style/MyAutofilledHighlight">

驗證以自動填入

自動填入服務可能會先要求使用者完成驗證,才將資料填入應用程式欄位。在這種情況下,Android 系統會啟動服務的驗證活動,並將這項活動納入堆疊。

應用程式不必更新即可支援驗證功能,因為驗證程序是在服務中進行。不過,您必須確保活動重新啟動時,系統會保留活動的檢視畫面結構,方法包括在 onCreate() 中建立檢視畫面結構,而非在 onStart()onResume() 中建立。

透過使用 AutofillFramework 範例中的 HeuristicsService,並將其設為需要進行填入回應驗證,您可以確認應用程式在自動填入服務要求驗證時的行為。您也可以使用 BadViewArchitectureCreationSignInActivity 範例模擬這個問題。

將自動填入 ID 指派至回收檢視畫面

如果應用程式需要根據大型資料集顯示元素的捲動清單,採用會回收檢視畫面的容器就非常實用,例如 RecyclerView 類別。容器捲動時,系統會重複使用版面配置中的檢視畫面,但檢視畫面會包含新的內容。

如果回收的檢視畫面已填入初始內容,自動填入服務會使用這類畫面的自動填入 ID,保留畫面的邏輯意義。當系統重複使用版面配置中的檢視畫面,而檢視畫面的邏輯 ID 保持不變,導致錯誤的自動填入使用者資料與自動填入 ID 建立關聯時,會發生問題。

如要在搭載 Android 9 (API 級別 28) 以上版本的裝置上解決這個問題,請使用以下方法,明確管理 RecyclerView 使用的檢視畫面自動填入 ID:

  • getNextAutofillId() 方法可取得活動專屬的新自動填入 ID。
  • setAutofillId() 方法可在活動中設定此檢視畫面的專屬邏輯自動填入 ID。

解決已知問題

本節介紹自動填入架構中已知問題的解決方法。

Android 8.0、8.1 的自動填入功能導致應用程式當機

在 Android 8.0 (API 級別 26) 和 Android 8.1 (API 級別 27) 中,自動填入服務可能會導致應用程式在某些情境下停止運作。為解決潛在問題,請使用 importantForAutofill=no 標記所有不需自動填入服務的檢視畫面。您也可以使用 importantForAutofill=noExcludeDescendants 標記整個活動。

調整大小後的對話方塊無法使用自動填入服務

在 Android 8.1 (API 等級 27) 以下版本中,如果對話方塊中檢視畫面的大小在顯示後經過了調整,該檢視畫面會無法使用自動填入服務。這類檢視畫面不包含在 Android 系統傳送至自動填入服務的 AssistStructure 物件中,因此該服務無法為檢視畫面填入內容。

如要解決這個問題,請找出建立該對話方塊的活動,使用該活動的 token 屬性取代對話方塊視窗參數的 token 屬性。確認自動填入服務已啟用後,請找出沿用自 Dialog 的類別,將視窗參數儲存在該類別的 onWindowAttributesChanged() 方法中。接著,請將所儲存參數的 token 屬性,替換為 onAttachedToWindow() 方法中父項活動的 token 屬性。

以下程式碼片段說明實作此解決方法的類別:

Kotlin

class MyDialog(context: Context) : Dialog(context) {

    // Used to store the dialog window parameters.
    private var token: IBinder? = null

    private val isDialogResizedWorkaroundRequired: Boolean
        get() {
            if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) {
                return false
            }
            val autofillManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                context.getSystemService(AutofillManager::class.java)
            } else {
                null
            }
            return autofillManager?.isEnabled ?: false
        }

    override fun onWindowAttributesChanged(params: WindowManager.LayoutParams) {
        if (params.token == null && token != null) {
            params.token = token
        }

        super.onWindowAttributesChanged(params)
    }

    override fun onAttachedToWindow() {
        if (isDialogResizedWorkaroundRequired) {
            token = ownerActivity!!.window.attributes.token
        }

        super.onAttachedToWindow()
    }

}

Java

public class MyDialog extends Dialog {

    public MyDialog(Context context) {
        super(context);
    }

    // Used to store the dialog window parameters.
    private IBinder token;

    @Override
    public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
        if (params.token == null && token != null) {
            params.token = token;
        }

        super.onWindowAttributesChanged(params);
    }

    @Override
    public void onAttachedToWindow() {
        if (isDialogResizedWorkaroundRequired()) {
            token = getOwnerActivity().getWindow().getAttributes().token;
        }

        super.onAttachedToWindow();
    }

    private boolean isDialogResizedWorkaroundRequired() {
        if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O
                || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) {
            return false;
        }
        AutofillManager autofillManager =
                null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            autofillManager = getContext().getSystemService(AutofillManager.class);
        }
        return autofillManager != null && autofillManager.isEnabled();
    }

}

為避免執行不必要的作業,以下程式碼片段說明如何檢查裝置是否支援自動填入服務、是否已為目前使用者啟用這項服務,以及是否需要此解決方法:

Kotlin

// AutofillExtensions.kt

fun Context.isDialogResizedWorkaroundRequired(): Boolean {
    // After the issue is resolved on Android, check whether the
    // workaround is still required for the current device.
    return isAutofillAvailable()
}

fun Context.isAutofillAvailable(): Boolean {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        // The autofill framework is available on Android 8.0
        // or higher.
        return false
    }

    val afm = getSystemService(AutofillManager::class.java)
    // Return true if autofill is supported by the device and enabled
    // for the current user.
    return afm != null && afm.isEnabled
}

Java

public class AutofillHelper {

    public static boolean isDialogResizedWorkaroundRequired(Context context) {
        // After the issue is resolved on Android, check whether the
        // workaround is still required for the current device.
        return isAutofillAvailable(context);
    }

    public static boolean isAutofillAvailable(Context context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            // The autofill framework is available on Android 8.0
            // or higher.
            return false;
        }

        AutofillManager afm = context.getSystemService(AutofillManager.class);
        // Return true if autofill is supported by the device and enabled
        // for the current user.
        return afm != null && afm.isEnabled();
    }
}

透過自動填入服務測試應用程式

針對自動填入服務將應用程式最佳化後,請測試應用程式能否搭配自動填入服務正常運作。

測試應用程式時,建議使用模擬器或搭載 Android 8.0 (API 級別 26) 以上版本的實體裝置。如需進一步瞭解如何建立模擬器,請參閱「建立及管理虛擬裝置」。

安裝自動填入服務

您必須先安裝其他提供自動填入服務的應用程式,才能使用自動填入功能測試應用程式。您可以為此使用第三方應用程式,但使用範例自動填入服務是較輕鬆的做法,您也不必註冊任何第三方服務。

您可以在 Java 中使用 Android 自動填入架構範例,透過自動填入服務測試應用程式。範例應用程式提供自動填入服務和用戶端 Activity 類別,可讓您先用於測試工作流程,再與您的應用程式搭配使用。本頁面採用 android-AutoFillFramework 範例應用程式供您參考。

安裝應用程式後,請依序點選「Settings」>「System」>「Languages & input」>「Advanced」>「Input assistance」>「Autofill service」,在模擬器的系統設定中啟用自動填入服務。

分析資料需求

如要使用自動填入服務測試應用程式,這項服務會需要可用來填入應用程式的資料,且必須瞭解會在應用程式檢視畫面上顯示的資料類型。舉例來說,如果應用程式檢視畫面上會顯示使用者名稱,則服務應具有包含使用者名稱的資料集,以及用來瞭解檢視畫面需要這類資料的機制。

請設定 android:autofillHints 屬性,讓服務瞭解檢視畫面上會顯示的資料類型。某些服務會利用複雜的經驗法則判斷資料類型,但範例應用程式等其他服務則仰賴開發人員提供這類資訊。如果您在與自動填入服務相關的檢視畫面中設定 android:autofillHints 屬性,應用程式與自動填入服務搭配運作的效果會更好。

執行測試

分析資料需求後,您可以執行測試,包括將測試資料儲存在自動填入服務,並在應用程式中觸發自動填入功能。

在服務中儲存資料

如要將資料儲存在目前使用的自動填入服務中,請按照下列步驟操作:

  1. 開啟含有檢視畫面的應用程式,該檢視畫面應含有您想在測試期間使用的資料類型。android-AutoFillFramework 範例應用程式會為使用者介面提供需要多種資料類型 (例如信用卡號碼和使用者名稱) 的檢視畫面。
  2. 輕觸包含所需資料類型的檢視畫面。
  3. 在檢視畫面中輸入值。
  4. 輕觸確認按鈕,例如「Sign in」或「Submit」。通常必須先提交表單,服務才會儲存資料。
  5. 透過系統對話方塊驗證權限要求。系統對話方塊會顯示目前所使用服務的名稱,並詢問是否要在測試中使用該服務。如要使用該服務,請輕觸「Save」

如果 Android 未顯示權限對話方塊,或是該服務並非測試時要使用的服務,請在系統設定中檢查目前是否正在使用該服務。

觸發應用程式的自動填入功能

如要觸發應用程式的自動填入功能,請按照下列步驟操作:

  1. 開啟應用程式,前往含有測試所需檢視畫面的活動。
  2. 輕觸要填入內容的檢視畫面。
  3. 系統會顯示自動填入 UI,其中包含可填入檢視畫面的資料集,如圖 1 所示。
  4. 輕觸含有所需資料的資料集。檢視畫面會顯示先前儲存在服務中的資料。
顯示「dataset-2」為可用資料集的自動填入 UI
圖 1. 顯示可用資料集的自動填入 UI。

如果 Android 未顯示自動填入 UI,您可以嘗試下列疑難排解選項:

  • 檢查應用程式檢視畫面是否使用 android:autofillHints 屬性中正確的值。如需屬性可能值的清單,請查看 View 類別中前面加上 AUTOFILL_HINT 的常數。
  • 在須填入資料的檢視畫面上,檢查 android:importantForAutofill 屬性是否設為 no 以外的值,或是設為該檢視畫面上 noExcludeDescendants 或其父項值以外的值。