ממשקי API של eUICC

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

מידע על eUICC

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

טלפון Android עם אפליקציית ספק ו-OEM LPA

איור 1. טלפונים עם Android עם אפליקציית ספק ו-OEM LPA

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

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

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

שימוש ב-EuiccManager

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

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

פלטפורמת Android לא מטפלת בכללי מדיניות הפרופיל. אם כלל מדיניות מצוין במטא-נתונים של הפרופיל, ה-LPA יכול לבחור איך לטפל תהליך ההורדה וההתקנה של הפרופיל. לדוגמה, ייתכן שמודל ה-LPA של ה-OEM של הצד השלישי לטיפול בכללי מדיניות באמצעות קוד שגיאה מיוחד (השגיאה הקוד מועבר מה-OEM LPA לפלטפורמה, ואז הפלטפורמה מעבירה את ל-OEM (LUI)).

למידע על ממשקי API של פרופילים מרובים שמופעלים, אפשר לעיין בכתובת פרופילים מרובים שהופעלו.

ממשקי API

ממשקי ה-API הבאים נמצאים מאמרי עזרה של EuiccManager וגם EuiccManager.java

אחזור של מופע (ציבורי)

הפונקציה מקבלת את המופע של EuiccManager עד Context#getSystemService. פרטים נוספים זמינים במאמר getSystemService

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

המחאה מופעלת (ציבורית)

בודק אם המינוי המוטמע מופעל. צריך לסמן את זה לפני הגישה לממשקי API של LPA. פרטים נוספים זמינים במאמר isEnabled

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

קבלת EID (ציבורי)

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

החלפת מינוי (ציבורי)

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