Google is committed to advancing racial equity for Black communities. See how.
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

Quick Access Wallet

Android 11提供了快速訪問錢包功能,允許用戶直接從電源菜單訪問支付卡和相關通行證。主要用例包括在NFC終端執行交易之前選擇適當的付款方式,並為即將發生的事件快速訪問航班和其他通行證。

電源菜單中的快速訪問錢包功能
圖1.電源菜單中的快速訪問錢包功能

要求

您的設備必須具有NFC才能使用快速訪問錢包功能。該功能綁定到默認NFC支付應用程序的QuickAccessWalletService ,這意味著設備還必須支持基於NFC主機的卡模擬(HCE)

功能概述

快速訪問錢包包含兩個部分:快速訪問錢包UI和快速訪問錢包卡提供商。

電子錢包用戶界面在系統用戶界面中運行,並在platform/packages/apps/QuickAccessWallet 。除了將軟件包包括在內並將其列入白名單並安裝快速訪問電子錢包卡提供商之外,無需進行其他任何更改即可使電子錢包UI顯示在電源菜單中。

快速訪問錢包卡提供商是默認的NFC付款應用。用戶可以同時安裝多個NFC付款應用程序,但是只有默認NFC付款應用程序才能在電源菜單上顯示卡。您可以指定最初將哪個NFC支付應用程序設置為默認應用程序,但用戶可以在“設置”中選擇其他應用程序。如果僅安裝了一個NFC支付應用程序,它將自動成為默認應用程序(請參閱CardEmulationManager )。

實作

要將QuickAccessWalletService Quick Access Wallet UI,NFC支付應用必須實現QuickAccessWalletService 。支付應用程序必須包含宣傳該服務的清單條目。

為了確保只有系統UI可以綁定到QuickAccessWalletService ,NFC支付應用程序必須要求android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE權限。要求此權限可確保只有系統UI可以綁定到QuickAccessWalletService

<service
     android:name=".MyQuickAccessWalletService"
     android:label="@string/my_default_tile_label"
     android:icon="@drawable/my_default_icon_label"
     android:logo="@drawable/my_wallet_logo"
     android:permission="android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE">
     <intent-filter>
         <action android:name="android.service.quickaccesswallet.QuickAccessWalletService" />
         <category android:name="android.intent.category.DEFAULT"/>
     </intent-filter>
     <meta-data android:name="android.quickaccesswallet"
          android:resource="@xml/quickaccesswallet_configuration" />;
 </service>

有關錢包的其他信息包含在鏈接的XML文件中:

<quickaccesswallet-service
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:settingsActivity="com.example.android.SettingsActivity"
   android:shortcutLongLabel="@string/my_wallet_empty_state_text"
   android:shortcutShortLabel="@string/my_wallet_button_text"
   android:targetActivity="com.example.android.WalletActivity"/>

接下來,支付應用必須實現QuickAccessWalletService

public class MyQuickAccessWalletService extends QuickAccessWalletService {

    @Override
    public void onWalletCardsRequested(
            GetWalletCardsRequest request,
            GetWalletCardsCallback callback) {
        GetWalletCardsResponse response = // generate response
        callback.onSuccess(response);
    }

    @Override
    public void onWalletCardSelected(SelectWalletCardRequest request) {
        // selecting a card should ensure that it is used when making an NFC payment
    }

    @Override
    public void onWalletDismissed() {
        // May un-select card if the wallet app has the concept of a 'default'
        // payment method
    }
}

如果HostApduService開始處理NFC交易並因此開始顯示付款進度和結果的活動,則它還應嘗試獲取對綁定的QuickAccessWalletService的引用,並以事件類型TYPE_NFC_PAYMENT_STARTED調用QuickAccessWalletService#sendEvent 。 。這將導致快速訪問電子錢包UI被關閉,從而使用戶可以無障礙地查看付款活動。

有關實現QuickAccessWalletService其他文檔,請參閱QuickAccessWalletServiceTestQuickAccessWalletService CTS測試。

啟用快速訪問電子錢包用戶界面

要配置可從電源菜單使用的快速訪問錢包,請在構建中包括QuickAccessWallet目標,並通過將下面代碼示例中的粗體行添加到overlay/frameworks/base/packages/SystemUI/res/values/config.xml來啟用globalactions.wallet插件。 overlay/frameworks/base/packages/SystemUI/res/values/config.xml文件。

<resources>
    ...
    <!-- SystemUI Plugins that can be loaded on user builds. -->
    <string-array name="config_pluginWhitelist" translatable="false">
        <item>com.android.systemui</item>
        <item>com.android.systemui.plugin.globalactions.wallet</item>
    </string-array>
</resources>

使用def_nfc_payment_component設置配置文件中指定默認的NFC支付應用程序。

默認NFC支付應用程序必須公開QuickAccessWalletService才能向快速訪問錢包提供卡。如果默認的NFC支付應用未導出此服務,則錢包UI將被隱藏。

QuickAccessWalletService實施細節

QuickAccessWalletService具有三個必須實現的抽象方法: onWalletCardsRequestedonWalletCardSelectedonWalletDismissed 。下面的序列圖說明了在NFC付款之前立即查看快速訪問錢包時的呼叫序列。

快速訪問錢包序列圖

查看快速訪問錢包時的呼叫順序示例
圖2.查看快速訪問錢包時的呼叫順序示例

並非快速訪問錢包的所有視圖都帶有NFC付款,但是上面的圖2展示了QuickAccessWalletService所有功能。在此示例中,快速訪問錢包卡提供程序實​​現了以藍色概述的元素。假定支付卡存儲在設備的數據庫中,並且可以通過名為PaymentCardManager的接口進行訪問。進一步假設一個名為PaymentActivity的活動顯示了NFC付款的結果。流程如下:

  1. 用戶執行手勢以調出快速訪問錢包。
  2. 快速訪問電子錢包UI(系統UI的一部分)檢查程序包管理器,以查看默認NFC支付應用程序是否導出QuickAccessWalletService

    • 如果未導出服務,則不會顯示“快速訪問錢包”。
  3. 快速訪問錢包UI綁定到QuickAccessWalletService並調用onWalletCardsRequested 。此方法採用一個請求對象,該對象包含有關可以提供的卡的數量和大小以及回調的數據。可以從後台線程調用該回調。

  4. QuickAccessWalletService計算要顯示的卡,然後在提供的回調中調用onSuccess方法。建議該服務在後台線程上執行這些操作。

  5. 顯示卡後,系統UI會通過調用onWalletCardSelected通知QuickAccessWalletService已選擇了第一張卡。

    • onWalletCardSelected用戶選擇新卡時,都會調用onWalletCardSelected
    • 即使當前選定的卡未更改,也可能會調用onWalletCardSelected
  6. 當用戶退出快速訪問錢包,系統UI通知QuickAccessWalletService通過調用onWalletDismissed

在以上示例中,用戶在顯示錢包的同時將電話帶入NFC支付終端的範圍內。處理NFC支付的關鍵組件是HostApduService ,必須實現該組件才能處理NFC讀取器提供的APDU(有關更多信息,請參閱基於主機的卡模擬)。假定支付應用程序啟動了一項活動,以顯示與NFC終端進行交互的進度和結果。但是,快速訪問電子錢包UI顯示在應用程序窗口的頂部,這意味著快速訪問電子錢包UI掩蓋了付款活動。為了解決這個問題,該應用必須通知系統用戶界面應刪除快速訪問電子錢包用戶界面。它可以通過獲取到綁定的引用這樣做QuickAccessWalletService並調用sendWalletServiceEvent與事件類型TYPE_NFC_PAYMENT_STARTED

QuickAccessWalletService示例實現

/** Sample implementation of {@link QuickAccessWalletService} */
@RequiresApi(VERSION_CODES.R)
public class MyQuickAccessWalletService extends QuickAccessWalletService {

  private static final String TAG = "QAWalletSvc";
  private ExecutorService executor;
  private PaymentCardManager paymentCardManager;

  @Override
  public void onCreate() {
    super.onCreate();
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
      Log.w(TAG, "Should not run on pre-R devices");
      stopSelf();
      return;
    }
    executor = Executors.newSingleThreadExecutor();
    paymentCardManager = new PaymentCardManager();
  }

  @Override
  public void onDestroy() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
      return;
    }
    executor.shutdownNow();
  }

  @Override
  public void onWalletCardsRequested(
      @NonNull GetWalletCardsRequest request, @NonNull GetWalletCardsCallback callback) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
      return;
    }
    executor.submit(
        () -> {
          List<PaymentCard> paymentCards = paymentCardManager.getCards();
          int maxCards = Math.min(paymentCards.size(), request.getMaxCards());
          List<WalletCard> walletCards = new ArrayList<>(maxCards);
          int selectedIndex = 0;
          int cardWidthPx = request.getCardWidthPx();
          int cardHeightPx = request.getCardHeightPx();
          for (int index = 0; index < maxCards; index++) {
            PaymentCard paymentCard = paymentCards.get(index);
            WalletCard walletCard =
                new WalletCard.Builder(
                        paymentCard.getCardId(),
                        paymentCard.getCardImage(cardWidthPx, cardHeightPx),
                        paymentCard.getContentDescription(),
                        paymentCard.getPendingIntent())
                    .build();
            walletCards.add(walletCard);
            if (paymentCard.isSelected()) {
              selectedIndex = index;
            }
          }
          GetWalletCardsResponse response = 
              new GetWalletCardsResponse(walletCards, selectedIndex);
          callback.onSuccess(response);
        });
  }

  @Override
  public void onWalletCardSelected(@NonNull SelectWalletCardRequest request) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
      return;
    }
    executor.submit(
        () -> paymentCardManager.selectCardById(request.getCardId()));
  }

  @Override
  public void onWalletDismissed() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
      return;
    }
    executor.submit(() -> {
      paymentCardManager.removeCardOverrides();
    });
  }
}

有關QuickAccessWalletService更多詳細信息,請參見QuickAccessWalletService API參考

權限

QuickAccessWalletService的清單條目必須要求Android 11中引入的android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE權限。這是系統UI持有的簽名級權限,這意味著只有系統UI進程才能綁定到QuickAccessWalletService實現。請注意,側面加載的應用可以申請此權限,並在運行Android 10或更低版本的設備上獲得對QuickAccessWalletService數據的完全訪問權限。為防止這種情況,建議該服務在onCreate檢查構建版本,並僅在運行Android 11及更高版本的設備上啟用該服務。除了提供主機卡仿真付款服務所需的權限外,不需要其他任何應用程序權限。

如果默認的NFC支付應用未實現或導出QuickAccessWalletService ,則不會顯示“快速訪問電子錢包” UI。

設定值

用戶可以從“設置”應用中關閉“快速訪問錢包”功能。可以在“設置” >“系統” >“手勢” >“卡片和通行證”中找到設置頁面。

設置頁面以啟用或禁用快速訪問錢包功能
圖3.設置頁面以啟用或禁用快速訪問錢包功能

客制化

將快速訪問電子錢包視圖添加到系統UI中的另一個位置

快速訪問電子錢包UI是作為系統插件構建的。儘管AOSP實現在GlobalActionsDialog使用了它(長GlobalActionsDialog顯示),但是只要您維持插件接口指定的協定,就可以將功能移到其他手勢後面。

public interface GlobalActionsPanelPlugin extends Plugin {

  /** Invoked when the view is shown */
  PanelViewController onPanelShown(Callbacks callbacks, boolean deviceLocked);

  /** Callbacks for interacting with the view container */
  interface Callbacks {
    /** Dismisses the view */
    void dismissGlobalActionsMenu();

    /** Starts a PendingIntent, dismissing the keyguard if necessary. */
    void startPendingIntentDismissingKeyguard(PendingIntent pendingIntent);
  }

  /** Provides the Quick Access Wallet view */
  interface PanelViewController {
    
    /** Returns the QuickAccessWallet view, which may take any size */
    View getPanelContent();
    
    /** Invoked when the view is dismissed */
    void onDismissed();

    /** Invoked when the device is either locked or unlocked. */
    void onDeviceLockStateChanged(boolean locked);
  }
}

快速訪問錢包UI實現了GlobalActionsPanelPluginPanelViewControllerGlobalActionsDialog通過使用com.android.systemui.Dependency獲取錢包插件的實例:

GlobalActionsPanelPlugin mPanelPlugin =
    Dependency.get(ExtensionController.class)
        .newExtension(GlobalActionsPanelPlugin.class)
        .withPlugin(GlobalActionsPanelPlugin.class)
        .build()
        .get();

在檢查插件為非null以及onPanelShown返回的PanelViewController為非null之後,對話框onPanelShown getPanelContent提供的View附加到其自己的View並為系統事件提供適當的回調。

// Construct a Wallet PanelViewController. 
// `this` implements GlobalActionsPanelPlugin.Callbacks
GlobalActionsPanelPlugin.PanelViewController mPanelController =
    mPanelPlugin.onPanelShown(this, !mKeyguardStateController.isUnlocked());

// Attach the view
FrameLayout panelContainer = findViewById(R.id.my_panel_container);
FrameLayout.LayoutParams panelParams =
    new FrameLayout.LayoutParams(
        FrameLayout.LayoutParams.MATCH_PARENT,
        FrameLayout.LayoutParams.MATCH_PARENT);
panelContainer.addView(mPanelController.getPanelContent(), panelParams);

// Respond to unlock events (if the view can be accessed while the phone is locked)
keyguardStateController.addCallback(new KeyguardStateController.Callback() {
  @Override
  public void onUnlockedChanged() {
    boolean unlocked = keyguardStateController.isUnlocked()
        || keyguardStateController.canDismissLockScreen();
    mPanelController.onDeviceLockStateChanged(unlocked);
  }
});

// Implement GlobalActionsPanelPlugin.Callbacks
@Override
public void dismissGlobalActionsMenu() {
  dismissDialog();
}
@Override
public void startPendingIntentDismissingKeyguard(PendingIntent pendingIntent) {
  mActivityStarter.startPendingIntentDismissingKeyguard(pendingIntent);
}

// Notify the wallet when the container view is dismissed
mPanelController.onDismissed();

從電源菜單中刪除快速訪問錢包,省略QuickAccessWallet從系統構建目標。要從快捷菜單中刪除快速訪問錢包,但將其添加到系統提供的其他視圖中,請包括構建目標,並從GlobalActionsImpl刪除對GlobalActionsPanelPlugin引用。

設置默認配置

快速訪問錢包的可見性由兩個安全設置控制: GLOBAL_ACTIONS_PANEL_ENABLEDGLOBAL_ACTIONS_PANEL_AVAILABLEAVAILABLE設置控制是否可以在“設置”中打開和關閉該功能。 WalletPluginService將此設置設置為true 。如果QuickAccessWallet中未包含QuickAccessWallet ,則該設置保持為false 。默認情況下,“ ENABLED設置在同一位置設置為true ,但是用戶可以在“設置”中將其關閉。要更改默認行為,請修改WalletPluginService#enableFeatureInSettings

驗證方式

要驗證您對快速訪問錢包的實施,請運行CTS和手動測試。對插件的更改還應進行包含的robolectric測試

CTS測試

運行位於cts/tests/quickaccesswallet的CTS測試。

手動測試

要測試快速訪問錢包的核心功能,需要使用NFC付款終端(真實或偽造)和實現QuickAccessWalletService (錢包應用)的NFC付款應用。應測試的核心功能包括可用性,零狀態,卡選擇和鎖定屏幕行為。

可用性

  • 如果GLOBAL_ACTIONS_PANEL_ENABLED設置為true ,並且默認NFC支付應用程序支持該功能,則可以訪問快速訪問錢包。
  • 如果GLOBAL_ACTIONS_PANEL_ENABLED設置為false且默認NFC支付應用程序支持該功能,則無法訪問“快速訪問錢包”。
  • 如果GLOBAL_ACTIONS_PANEL_ENABLED設置為true ,並且默認NFC支付應用支持該功能,則無法訪問快速訪問錢包。
  • 如果GLOBAL_ACTIONS_PANEL_ENABLED設置為false ,並且默認NFC支付應用支持該功能,則無法訪問快速訪問錢包。

零狀態

  • 如果啟用並導出了QuickAccessWalletService ,但不提供任何卡,則“快速訪問電子錢包” UI將顯示空狀態視圖。
  • 單擊空狀態視圖將打開錢包應用程序。

    快速訪問錢包用戶界面中的空狀態視圖
    圖4.快速訪問錢包UI中的空狀態視圖

非零狀態

  • 如果錢包應用程序提供一張或多張卡,則這些卡將顯示在快速訪問電子錢包用戶界面中。

    顯示卡片的快速訪問電子錢包用戶界面
    圖5.顯示卡的快速訪問錢包UI
  • 如果顯示的卡代表NFC付款方式,則將手機握在NFC付款終端上將導致該付款方式被使用,並且錢包視圖被關閉。

  • 單擊顯示的卡將退出錢包視圖,並打開該卡的詳細活動。

  • 如果QuickAccessWalletService提供了多張卡,則用戶可以在卡之間滑動。

  • 溢出菜單包含兩個條目:一個打開“錢包”應用程序,另一個打開“設置”中的“顯示卡和通行證”屏幕。

鎖定狀態測試

  • 如果手機已鎖定,則錢包的可見性由Settings.Secure.POWER_MENU_LOCK_SHOW_CONTENT設置控制,該Settings.Secure.POWER_MENU_LOCK_SHOW_CONTENT可以在“設置”中控制。
  • 如果電話已鎖定且POWER_MENU_LOCK_SHOW_CONTENTfalse ,則不會顯示錢包。
  • 如果電話已鎖定且POWER_MENU_LOCK_SHOW_CONTENTtrue ,則顯示錢包。
  • 在鎖定屏幕上顯示錢包時解鎖手機會導致重新查詢卡,這可能導致卡內容不同。

輔助功能測試

  • “話語提示”用戶可以通過左右滑動並收聽卡的內容描述來瀏覽錢包視圖。
  • 在啟用“話語提示”的情況下左右滑動即可依次選擇每張卡。 “話語提示”用戶可以在NFC付款終端上選擇並使用NFC付款方式。