API ของ eUICC

ใน Android 9 คุณจะเข้าถึง Profile Management API (สาธารณะและ @SystemApi) ผ่านคลาส EuiccManager ได้ eUICC Communication API (@SystemApi เท่านั้น) มีให้ใช้งานผ่านคลาส EuiccCardManager

เกี่ยวกับ eUICC

ผู้ให้บริการสามารถสร้างแอปของผู้ให้บริการโดยใช้ EuiccManager เพื่อจัดการโปรไฟล์ดังที่แสดงในรูปที่ 1 แอปของผู้ให้บริการไม่จำเป็นต้องเป็นแอประบบ แต่ต้องมีสิทธิ์ของผู้ให้บริการที่ได้รับจากโปรไฟล์ eUICC แอป LPA (LUI และแบ็กเอนด์ LPA) ต้องเป็นแอประบบ (กล่าวคือรวมอยู่ในอิมเมจระบบ) เพื่อเรียกใช้ @SystemApi

โทรศัพท์ Android ที่มีแอป Carrier และ OEM LPA

รูปที่ 1 โทรศัพท์ Android ที่มีแอปของผู้ให้บริการและ LPA ของ OEM

นอกจากตรรกะในการเรียก EuiccCardManager และพูดคุยกับ eUICC แล้ว แอป LPA ต้องใช้งานสิ่งต่อไปนี้

  • ไคลเอ็นต์ SM-DP+ สื่อสารกับเซิร์ฟเวอร์ SM-DP+ เพื่อตรวจสอบสิทธิ์และดาวน์โหลดโปรไฟล์
  • [ไม่บังคับ] SM-DS เพื่อรับโปรไฟล์ที่ดาวน์โหลดได้มากขึ้น
  • การจัดการการแจ้งเตือนเพื่อส่งการแจ้งเตือนไปยังเซิร์ฟเวอร์เพื่ออัปเดตสถานะโปรไฟล์
  • [ไม่บังคับ] การจัดการช่อง รวมถึงการเปลี่ยนระหว่างตรรกะ eSIM กับ pSIM ขั้นตอนนี้ไม่บังคับหากโทรศัพท์มีเพียงชิป eSIM เท่านั้น
  • OTA ของ eSIM

แม้ว่าโทรศัพท์ Android จะมีแอป LPA มากกว่า 1 แอป แต่คุณจะเลือกได้เพียง 1 แอปเท่านั้นที่จะใช้เป็น LPA ที่ทำงานจริง โดยอิงตามลําดับความสําคัญที่กําหนดไว้ในไฟล์ AndroidManifest.xml ของแต่ละแอป

ใช้ EuiccManager

LPA API เป็น API แบบสาธารณะผ่าน EuiccManager (ในแพ็กเกจ android.telephony.euicc) แอปของผู้ให้บริการสามารถรับอินสแตนซ์ของ EuiccManager และเรียกใช้เมธอดใน EuiccManager เพื่อรับข้อมูล eUICC และจัดการการสมัครใช้บริการ (เรียกว่าโปรไฟล์ในเอกสาร RSP ของ GSMA) เป็นอินสแตนซ์ SubscriptionInfo

หากต้องการเรียก API สาธารณะ ซึ่งรวมถึงการดาวน์โหลด เปลี่ยน และลบการสมัครใช้บริการ แอปของผู้ให้บริการต้องมีสิทธิ์ที่จำเป็น ผู้ให้บริการเครือข่ายมือถือจะเพิ่มสิทธิ์ของผู้ให้บริการในข้อมูลเมตาของโปรไฟล์ eUICC API จะบังคับใช้กฎสิทธิ์ของผู้ให้บริการตามกฎดังกล่าว

แพลตฟอร์ม Android ไม่จัดการกฎนโยบายโปรไฟล์ หากมีการประกาศกฎนโยบายในข้อมูลเมตาของโปรไฟล์ LPA จะเลือกวิธีจัดการขั้นตอนการดาวน์โหลดและการติดตั้งโปรไฟล์ได้ ตัวอย่างเช่น LPA ของ OEM บุคคลที่สามอาจจัดการกฎนโยบายโดยใช้รหัสข้อผิดพลาดพิเศษได้ (ระบบจะส่งรหัสข้อผิดพลาดจาก LPA ของ OEM ไปยังแพลตฟอร์ม จากนั้นแพลตฟอร์มจะส่งรหัสไปยัง LUI ของ OEM)

ดูข้อมูลเกี่ยวกับ API ของโปรไฟล์ที่เปิดใช้หลายรายการได้ที่โปรไฟล์ที่เปิดใช้หลายรายการ

API

คุณดู API ต่อไปนี้ได้ในเอกสารอ้างอิงEuiccManager และ EuiccManager.java

รับอินสแตนซ์ (สาธารณะ)

รับอินสแตนซ์ของ EuiccManager ถึง Context#getSystemService ดูรายละเอียดได้ที่ getSystemService

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

เปิดใช้การตรวจสอบ (สาธารณะ)

ตรวจสอบว่ามีการเปิดใช้การสมัครใช้บริการแบบฝังหรือไม่ ซึ่งควรตรวจสอบก่อนเข้าถึง LPA API ดูรายละเอียดได้ที่ isEnabled

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

รับ EID (สาธารณะ)

รับ EID ที่ระบุฮาร์ดแวร์ eUICC ค่านี้อาจเป็นค่าว่างหาก eUICC ไม่พร้อมใช้งาน ผู้โทรต้องมีสิทธิ์ของผู้ให้บริการหรือสิทธิ์ READ_PRIVILEGED_PHONE_STATE โปรดดูรายละเอียดที่ getEid

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

รับ EuiccInfo (สาธารณะ)

รับข้อมูลเกี่ยวกับ eUICC จะประกอบด้วยเวอร์ชันของระบบปฏิบัติการ ดูรายละเอียดได้ที่ getEuiccInfo

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

การสมัครใช้บริการการดาวน์โหลด (สาธารณะ)

ดาวน์โหลดการสมัครใช้บริการที่ระบุ (เรียกว่า "โปรไฟล์" ในเอกสาร RSP ของ GSMA) คุณสร้างการสมัครใช้บริการได้จากรหัสเปิดใช้งาน เช่น แยกวิเคราะห์รหัสเปิดใช้งานจากคิวอาร์โค้ด การดาวน์โหลดการติดตามเป็นการดำเนินการแบบไม่พร้อมกัน

ผู้โทรต้องมีสิทธิ์ 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);

พอร์ตซิมพร้อมใช้งานหรือไม่ (สาธารณะ)

public boolean isSimPortAvailable(int portIndex)

(ใช้ได้ใน Android 13) แสดงผลว่าดัชนีพอร์ตที่ส่งผ่านพร้อมใช้งานหรือไม่ พอร์ตจะพร้อมใช้งานหากไม่ได้เปิดใช้การสมัครใช้บริการ หรือแอปการโทรมีสิทธิ์ของผู้ให้บริการเหนือการสมัครใช้บริการที่ติดตั้งไว้ในพอร์ตที่เลือก ดูรายละเอียดได้ที่ isSimPortAvailable

ลบการสมัครใช้บริการ (สาธารณะ)

ลบการสมัครใช้บริการที่มีรหัสการสมัครใช้บริการ หากการสมัครใช้บริการเปิดใช้งานอยู่ ระบบจะปิดใช้การสมัครใช้บริการนั้นก่อน ผู้โทรต้องมีสิทธิ์ 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 ที่เป็นค่า Enum เพื่อระบุว่าจะลบการสมัครใช้บริการทั้งหมดสำหรับการทดสอบ การทํางาน หรือทั้ง 2 ประเภทหรือไม่ ผู้โทรต้องมีสิทธิ์ 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);

ค่าคงที่

หากต้องการดูรายการค่าคงที่ public ใน EuiccManager โปรดดูหัวข้อค่าคงที่