eUICC API

在 Android 9 中,設定檔管理 API (公開 @SystemApi) 可以透過 EuiccManager 類別取得。eUICC 通訊 API (僅限 @SystemApi) 可透過類別 EuiccCardManager 取得。

關於 eUICC

電信業者可以使用 EuiccManager 管理個人資料,步驟如下: 圖 1.電信業者應用程式不一定要是系統應用程式,但需要有電信業者 由 eUICC 設定檔授予的權限。一個 LPA 應用程式 (LUI 和 LPA) 後端) 必須是系統應用程式 (即系統映像檔中) 才能呼叫 @SystemApi。

已安裝電信業者應用程式,並採用原始設備製造商 (OEM) LPA 的 Android 手機

圖 1. 已安裝電信業者應用程式和原始設備製造商 (OEM) LPA 的 Android 手機

除了呼叫 EuiccCardManager 與與 eUICC 和 LPA 應用程式通訊的邏輯之外 必須實作下列項目:

  • SM-DP+ 用戶端與 SM-DP+ 伺服器進行通訊,藉此驗證並 下載設定檔
  • [選用] SM-DS 取得更多可下載的設定檔
  • 如何傳送通知給伺服器 更新設定檔狀態
  • [選用] 運算單元管理,包括切換 eSIM 卡和 PSIM 邏輯。 如果手機只有 eSIM 卡晶片,則不一定要選取。
  • eSIM 卡 OTA

雖然 Android 手機可以同時使用多個 LPA 應用程式,但只能有一個 LPA 並根據 Deployment 的 每個應用程式的 AndroidManifest.xml 檔案。

使用 EuiccManager

LPA API 會透過 EuiccManager (在套件之下) 公開 android.telephony.euicc)。電信業者應用程式可取得 EuiccManager 的例項。 並呼叫 EuiccManager 中的方法,取得 eUICC 資訊並管理 (在 GSMA RSP 文件中稱為設定檔) SubscriptionInfo 執行個體。

呼叫公用 API,包括下載、切換及刪除訂閱項目 作業時,電信業者應用程式必須具備必要權限。電信業者 權限是由電信業者所新增。eUICC API 就會據此執行電信業者特權規則。

Android 平台不會處理設定檔政策規則。如果政策規則 會在設定檔中繼資料中宣告,LPA 可能會選擇處理 設定檔下載與安裝程序。舉例來說, 第三方 OEM LPA 使用特殊錯誤代碼處理政策規則 (錯誤 程式碼會從原始設備製造商 (OEM) LPA 傳遞到平台,接著平台就會將 原始設備製造商 (OEM) LUI)。

如要進一步瞭解多個已啟用的設定檔 API,請參閱 已啟用多個設定檔

API

下列 API 位於 EuiccManager 參考說明文件EuiccManager.java

取得執行個體 (公開)

透過 Context#getSystemService 取得 EuiccManager 的例項。 詳情請參閱 getSystemService

EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);

已啟用檢查功能 (公開)

檢查是否已啟用嵌入式訂閱項目。應勾選這個選項 然後再存取 LPA API詳情請參閱 isEnabled

boolean isEnabled = mgr.isEnabled();
if (!isEnabled) {
    return;
}

取得 EID (公開)

取得用於識別 eUICC 硬體的 EID。如果 eUICC 是 尚未就緒。來電者必須具備電信業者權限,或者 READ_PRIVILEGED_PHONE_STATE權限。詳情請參閱 getEid

String eid = mgr.getEid();
if (eid == null) {
  // Handle null case.
}

取得 EuiccInfo (公開)

取得 eUICC 相關資訊。這包含 OS 版本。詳情 看 getEuiccInfo

EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();

下載訂閱 (公開)

下載特定訂閱項目 (在 GSMA RSP 中稱為「設定檔」) 文件)。您可以使用啟用代碼建立訂閱項目。適用對象 例如從 QR code 剖析啟用碼。下載 訂閱項目屬於非同步作業

呼叫端必須具備 WRITE_EMBEDDED_SUBSCRIPTIONS 權限或 具備目標訂閱項目的電信業者權限。詳情請參閱 downloadSubscription

// Register receiver.
String action = "download_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                    0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(
        receiver,
        new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Download subscription asynchronously.
DownloadableSubscription sub =
        DownloadableSubscription.forActivationCode(code /* encodedActivationCode*/);
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.downloadSubscription(sub, true /* switchAfterDownload */, callbackIntent);

切換訂閱方案 (公開)

可切換為 (啟用) 指定訂閱項目。呼叫端必須具有 「WRITE_EMBEDDED_SUBSCRIPTIONS」或具備目前裝置的電信業者權限 啟用訂閱項目及目標訂閱項目詳情請參閱 switchToSubscription

// Register receiver.
String action = "switch_to_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Switch to a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.switchToSubscription(1 /* subscriptionId */, callbackIntent);

透過通訊埠 (公開) 切換訂閱方案

(適用於 Android 13) 切換至 (啟用) 已指定通訊埠索引的指定訂閱項目。 來電者必須有 WRITE_EMBEDDED_SUBSCRIPTIONS 或有電信業者的服務 權限。 詳情請參閱 switchToSubscription

// Register receiver.
String action = "switch_to_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Switch to a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.switchToSubscription(1 /* subscriptionId */, 0 /*portIndex*/, callbackIntent);

有可用的 SIM 卡連接埠 (公開)

public boolean isSimPortAvailable(int portIndex)

(適用於 Android 13) 傳回 可以使用傳遞通訊埠索引有可用的通訊埠 (如果有的話) 未啟用訂閱服務,或通話應用程式擁有專屬的電信業者權限 訂閱項目已安裝在所選通訊埠。詳情請參閱 isSimPortAvailable

刪除訂閱項目 (公開)

刪除具有訂閱項目 ID 的訂閱項目。如果訂閱項目目前為 處於啟用狀態時,會先停用。呼叫端必須具備 目標的 WRITE_EMBEDDED_SUBSCRIPTIONS 或電信業者權限 訂閱項目中的所有進階功能!詳情請參閱 deleteSubscription

// Register receiver.
String action = "delete_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                    0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/,
        null /* handler */);

// Delete a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.deleteSubscription(1 /* subscriptionId */, callbackIntent);

清除所有訂閱項目 (系統 API)

清除裝置上的所有訂閱項目。在 Android 裝置上開始行動 11,應提供 EuiccCardManager#ResetOption 列舉值,指定是否要清除所有測試和/或作業 訂閱項目。呼叫端必須具備 WRITE_EMBEDDED_SUBSCRIPTIONS 權限。

// Register receiver.
String action = "delete_subscription";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                    0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver, new IntentFilter(action),
        "example.broadcast.permission" /* broadcastPermission*/,
        null /* handler */);

// Erase all operational subscriptions asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.eraseSubscriptions(
        EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, callbackIntent);

開始解決活動 (公開)

啟動活動,以解決使用者能解決的錯誤。如果作業傳回 EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR,這個方法可 ,提示使用者解決問題。這個方法只能呼叫 處理特定錯誤一次

...
mgr.startResolutionActivity(getActivity(), 0 /* requestCode */, resultIntent, callbackIntent);

常數

如要查看 EuiccManager 中的 public 常數清單,請參閱 常數