Các API eUICC

Trong Android 9, API quản lý hồ sơ (công khai và @SystemApi) có sẵn thông qua lớp EuiccManager. Giao tiếp eUICC Các API (chỉ dành cho @SystemApi) được cung cấp thông qua lớp EuiccCardManager.

Giới thiệu về eUICC

Nhà mạng có thể tạo ứng dụng của nhà mạng bằng EuiccManager để quản lý hồ sơ, như minh hoạ trong Hình 1. Ứng dụng của nhà mạng không nhất thiết phải là ứng dụng hệ thống nhưng cần phải có nhà mạng đặc quyền được cấp bởi hồ sơ eUICC. Một Ứng dụngLPA (LUI và LPA phần phụ trợ) cần phải là một ứng dụng hệ thống (tức là có trong hình ảnh hệ thống) để gọi @SystemApi.

Điện thoại Android có Ứng dụng của nhà mạng và LPA của OEM

Hình 1. Điện thoại Android có ứng dụng của nhà mạng và LPA của OEM (Nhà sản xuất thiết bị gốc)

Ngoài logic gọi EuiccCardManager và trò chuyện với eUICC, các ứng dụng LPA phải triển khai những nội dung sau:

  • Máy khách SM-DP+ giao tiếp với máy chủ SM-DP+ để xác thực và tải hồ sơ xuống
  • [Không bắt buộc] SM-DS để nhận thêm nhiều hồ sơ có thể tải xuống được
  • Xử lý thông báo để gửi thông báo tới máy chủ cập nhật trạng thái của hồ sơ
  • [Không bắt buộc] Quản lý vị trí sử dụng, bao gồm cả việc chuyển đổi giữa logic eSIM và pSIM. Bạn không bắt buộc phải làm việc này nếu điện thoại chỉ có chip eSIM.
  • eSIM OTA

Mặc dù điện thoại Android có thể có nhiều ứng dụng LPA, nhưng chỉ có một ứng dụng LPA có thể được chọn là LPA hoạt động thực tế dựa trên mức độ ưu tiên được xác định trong tệp AndroidManifest.xml của từng ứng dụng.

Sử dụng EuiccManager

Các API LPA được công khai qua EuiccManager (trong gói android.telephony.euicc). Ứng dụng của nhà mạng có thể tải thực thể của EuiccManager, và gọi các phương thức trong EuiccManager để lấy thông tin eUICC và quản lý gói thuê bao (còn gọi là cấu hình trong các tài liệu GSMA RSP) dưới dạng Các phiên bản SubscriptionInfo.

Để gọi các API công khai, bao gồm cả tải xuống, chuyển đổi và xoá gói thuê bao , thì ứng dụng của nhà mạng phải có các đặc quyền cần thiết. Nhà mạng đặc quyền do nhà mạng di động thêm vào trong siêu dữ liệu của hồ sơ. eUICC API sẽ thực thi các quy tắc về đặc quyền của nhà mạng theo đó.

Nền tảng Android không xử lý các quy tắc chính sách hồ sơ. Nếu một quy tắc chính sách được khai báo trong siêu dữ liệu hồ sơ, LPA có thể chọn cách xử lý quy trình tải xuống và cài đặt hồ sơ. Ví dụ: có thể là LPA OEM của bên thứ ba để xử lý các quy tắc chính sách bằng cách sử dụng mã lỗi đặc biệt (lỗi mã được truyền từ OEM LPA đến nền tảng, sau đó nền tảng truyền cho OEM LUI).

Để biết thông tin về nhiều API hồ sơ được bật, hãy xem Nhiều hồ sơ được bật.

API

Bạn có thể tìm thấy các API sau trong Tài liệu tham khảo về EuiccManagerEuiccManager.java.

Nhận thực thể (công khai)

Lấy thực thể của EuiccManager thông qua Context#getSystemService. Để biết thông tin chi tiết, hãy xem getSystemService.

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

Đã bật tính năng kiểm tra (công khai)

Kiểm tra xem bạn đã bật gói thuê bao được nhúng hay chưa. Bạn cần kiểm tra điều này trước khi truy cập API LPA. Để biết thông tin chi tiết, hãy xem isEnabled.

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

Nhận EID (công khai)

Lấy EID (mã định danh dành cho eSIM) để xác định phần cứng eUICC. Giá trị này có thể rỗng nếu eUICC là chưa sẵn sàng. Người gọi phải có đặc quyền của nhà mạng hoặc Quyền READ_PRIVILEGED_PHONE_STATE. Để biết thông tin chi tiết, hãy xem getEid.

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

Tải EuiccInfo (công khai)

Nhận thông tin về eUICC. Tệp này có chứa phiên bản hệ điều hành. Để biết thông tin chi tiết, xem getEuiccInfo.

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

Tải gói thuê bao xuống (công khai)

Tải gói thuê bao đã cho xuống (còn gọi là "hồ sơ" trong GSMA RSP chứng từ). Bạn có thể tạo gói thuê bao bằng mã kích hoạt. Cho ví dụ: mã kích hoạt có thể được phân tích cú pháp từ mã QR. Tải xuống thuê bao là một hoạt động không đồng bộ.

Phương thức gọi phải có quyền WRITE_EMBEDDED_SUBSCRIPTIONS hoặc có đặc quyền của nhà mạng đối với gói thuê bao đích. Để biết thông tin chi tiết, hãy xem 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);

Chuyển gói thuê bao (công khai)

Chuyển sang (bật) gói thuê bao đã cho. Phương thức gọi phải có WRITE_EMBEDDED_SUBSCRIPTIONS hoặc có đặc quyền của nhà mạng đối với đã bật gói thuê bao và gói thuê bao mục tiêu. Để biết thông tin chi tiết, hãy xem 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);

Chuyển gói thuê bao bằng cổng (công khai)

(Có trên Android 13) Chuyển sang (bật) gói thuê bao đã cho có chỉ mục cổng được chỉ định. Người gọi phải có WRITE_EMBEDDED_SUBSCRIPTIONS hoặc có nhà mạng dành cho gói thuê bao đã kích hoạt hiện tại và gói thuê bao đích. Để biết thông tin chi tiết, hãy xem 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);

Có cổng SIM không (công khai)

public boolean isSimPortAvailable(int portIndex)

(Có từ Android 13) Trả về liệu giá trị chỉ mục cổng truyền sẽ có sẵn. Một cổng sẽ được cung cấp nếu chưa bật gói thuê bao hoặc ứng dụng gọi có đặc quyền của nhà mạng đối với gói thuê bao trên cổng đã chọn. Để biết thông tin chi tiết, hãy xem isSimPortAvailable.

Xoá gói thuê bao (công khai)

Xoá một gói thuê bao có mã nhận dạng gói thuê bao. Nếu gói thuê bao hiện là đang hoạt động, thì đầu tiên sẽ bị tắt. Phương thức gọi phải có WRITE_EMBEDDED_SUBSCRIPTIONS hoặc đặc quyền của nhà mạng đối với mục tiêu của bạn. Để biết thông tin chi tiết, hãy xem 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);

Xoá tất cả gói thuê bao (API hệ thống)

Xoá tất cả các gói thuê bao trên một thiết bị. Kể từ Android 11, bạn nên cung cấp EuiccCardManager#ResetOption giá trị enum để chỉ định xóa tất cả các bài kiểm thử, hoạt động hay cả hai loại gói thuê bao. Phương thức gọi phải có quyền 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);

Bắt đầu hoạt động giải quyết (công khai)

Bắt đầu một hoạt động để giải quyết lỗi có thể giải quyết được cho người dùng. Nếu một toán tử trả về EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR, phương thức này có thể là để nhắc người dùng giải quyết vấn đề. Chỉ có thể gọi phương thức này một lần cho một lỗi cụ thể.

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

Hằng số

Để xem danh sách các hằng số public trong EuiccManager, hãy xem Hằng số.