ממשקי API של eUICC

ב-Android 9, ממשקי API לניהול פרופילים (ציבוריים ו-‎@SystemApi) זמינים דרך המחלקה EuiccManager. ממשקי API של תקשורת eUICC (@SystemApi בלבד) זמינים דרך המחלקה EuiccCardManager.

מידע על eUICC

ספקים יכולים ליצור אפליקציות ספק באמצעות EuiccManager כדי לנהל פרופילים, כמו שמוצג באיור 1. אפליקציות של ספקי סלולר לא צריכות להיות אפליקציות מערכת, אבל צריכות לקבל הרשאות ספק מפרופילים של eUICC. אפליקציית LPA (LUI ו-LPA backend) צריכה להיות אפליקציית מערכת (כלומר, כלולה בקובץ אימג' של המערכת) כדי לקרוא ל-‎ @SystemApi.

טלפון Android עם אפליקציית ספק ו-LPA של יצרן ציוד מקורי

איור 1. טלפונים עם Android עם אפליקציית ספק ו-LPA של יצרן ציוד מקורי

בנוסף ללוגיקה של קריאה ל-EuiccCardManager ודיבור עם eUICC, אפליקציות LPA צריכות להטמיע את הפעולות הבאות:

  • לקוח SM-DP+‎ מתקשר עם שרת SM-DP+‎ כדי לבצע אימות ולהוריד פרופילים
  • ‫[Optional] SM-DS כדי לקבל עוד פרופילים פוטנציאליים להורדה
  • טיפול בהתראות כדי לשלוח התראות לשרת ולעדכן את מצב הפרופיל
  • [אופציונלי] ניהול משבצות, כולל מעבר בין לוגיקה של eSIM ו-pSIM. השלב הזה הוא אופציונלי אם בטלפון יש רק שבב eSIM.
  • eSIM OTA

יכולות להיות יותר מאפליקציית LPA אחת בטלפון Android, אבל אפשר לבחור רק אחת מהן שתהיה ה-LPA הפעיל בפועל, על סמך העדיפות שמוגדרת בקובץ AndroidManifest.xml של כל אפליקציה.

שימוש ב-EuiccManager

ממשקי ה-API של LPA הם ציבוריים דרך EuiccManager (בקטע package android.telephony.euicc). אפליקציית ספק יכולה לקבל את המופע של EuiccManager, ולהפעיל את השיטות ב-EuiccManager כדי לקבל את פרטי ה-eUICC ולנהל מינויים (שנקראים פרופילים במסמכי GSMA RSP) כמופעים של SubscriptionInfo.

כדי להפעיל ממשקי API ציבוריים, כולל פעולות של הורדה, החלפה ומחיקה של מינוי, לאפליקציית הספק צריכות להיות ההרשאות הנדרשות. ההרשאות של הספק הסלולרי מתווספות על ידי הספק הסלולרי במטא-נתונים של הפרופיל. ממשק ה-API של eUICC אוכף את הכללים של הרשאות הספק בהתאם.

פלטפורמת Android לא מטפלת בכללי המדיניות של הפרופיל. אם כלל מדיניות מוצהר במטא-נתונים של הפרופיל, ה-LPA יכול לבחור איך לטפל בהליך ההורדה וההתקנה של הפרופיל. לדוגמה, יכול להיות ש-LPA של יצרן ציוד מקורי (OEM) מצד שלישי יטפל בכללי מדיניות באמצעות קוד שגיאה מיוחד (קוד השגיאה מועבר מ-LPA של ה-OEM לפלטפורמה, ואז הפלטפורמה מעבירה את הקוד לממשק המשתמש המקומי של ה-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. הערך בשדה הזה יכול להיות null אם כרטיס ה-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();

הורדת מינוי (ציבורי)

הורדה של המינוי שצוין (נקרא 'פרופיל' במסמכי GSMA RSP). אפשר ליצור את המינוי באמצעות קוד הפעלה. לדוגמה, אפשר לנתח קוד הפעלה מקוד QR. הורדת מינוי היא פעולה אסינכרונית.

למבצע השיחה צריכה להיות הרשאה 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.

מחיקת מינוי (גלוי לכולם)

מחיקת מינוי לפי מזהה מינוי. אם המינוי פעיל כרגע, הוא מושבת קודם. למתקשר צריכות להיות הרשאות 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, צריך לספק ערך enum כדי לציין אם למחוק את כל המינויים מסוג בדיקה, מסוג תפעולי או משני הסוגים.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);

ערכים קבועים

רשימת הקבועים ב-publicEuiccManager מופיעה במאמר קבועים.