eUICC-APIs

In Android 9 sind Profilverwaltungs-APIs (public und @SystemApi) über die Klasse EuiccManager verfügbar. eUICC-Kommunikations-APIs (nur (@SystemApi)) sind über die Klasse EuiccCardManager verfügbar.

Über eUICC

Netzbetreiber können mit EuiccManager Netzbetreiber-Apps erstellen, um Profile zu verwalten, wie in Abbildung 1 dargestellt. Netzbetreiber-Apps müssen keine System-Apps sein, sondern müssen über Netzbetreiberrechte verfügen, die durch eUICC-Profile gewährt werden. Eine LPA-App (LUI und LPA-Backend) muss eine System-App sein (dh im System-Image enthalten sein), um @SystemApi aufzurufen.

Android-Telefon mit Carrier-App und OEM-LPA

Abbildung 1. Android-Telefone mit Mobilfunkanbieter-App und OEM-LPA

Neben der Logik des Aufrufs EuiccCardManager und der Kommunikation mit eUICC müssen LPA-Apps Folgendes implementieren:

  • Der SM-DP+-Client kommuniziert mit dem SM-DP+-Server, um Profile zu authentifizieren und herunterzuladen
  • [Optional] SM-DS, um mehr potenziell herunterladbare Profile zu erhalten
  • Benachrichtigungsverarbeitung zum Senden von Benachrichtigungen an den Server, um den Profilstatus zu aktualisieren
  • [Optional] Slot-Verwaltung einschließlich Umschalten zwischen eSIM- und pSIM-Logik. Dies ist optional, wenn das Telefon nur über einen eSIM-Chip verfügt.
  • eSIM OTA

Obwohl mehr als eine LPA-App in einem Android-Telefon vorhanden sein kann, kann nur eine LPA als tatsächlich funktionierende LPA ausgewählt werden, basierend auf der Priorität, die in der Datei AndroidManifest.xml jeder App definiert ist.

Verwendung von EuiccManager

Die LPA-APIs sind über EuiccManager öffentlich (unter dem Paket android.telephony.euicc ). Eine Netzbetreiber-App kann die Instanz von EuiccManager abrufen und die Methoden in EuiccManager aufrufen, um die eUICC-Informationen abzurufen und Abonnements (in GSMA-RSP-Dokumenten als Profile bezeichnet) als SubscriptionInfo-Instanzen zu verwalten.

Um öffentliche APIs aufzurufen, einschließlich Vorgängen zum Herunterladen, Wechseln und Löschen von Abonnements, muss die Betreiber-App über die erforderlichen Berechtigungen verfügen. Betreiberprivilegien werden vom Mobilfunkanbieter in den Profilmetadaten hinzugefügt. Die eUICC-API setzt die Betreiberprivilegienregeln entsprechend durch.

Die Android-Plattform verarbeitet die Profilrichtlinienregeln nicht. Wenn in den Profilmetadaten eine Richtlinienregel deklariert ist, kann die LPA auswählen, wie mit dem Profil-Download- und Installationsvorgang umgegangen wird. Beispielsweise ist es für eine OEM-LPA eines Drittanbieters möglich, Richtlinienregeln mithilfe eines speziellen Fehlercodes zu verarbeiten (der Fehlercode wird von der OEM-LPA an die Plattform übergeben, und die Plattform übergibt den Code dann an die OEM-LUI).

Informationen zu APIs mit mehreren aktivierten Profilen finden Sie unter Mehrere aktivierte Profile .

APIs

Die folgenden APIs finden Sie in der Referenzdokumentation EuiccManager und EuiccManager.java .

Instanz abrufen (öffentlich)

Ruft die Instanz von EuiccManager über Context#getSystemService ab. Einzelheiten finden Sie unter getSystemService .

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

Prüfung aktiviert (öffentlich)

Überprüft, ob das eingebettete Abonnement aktiviert ist. Dies sollte vor dem Zugriff auf LPA-APIs überprüft werden. Einzelheiten finden Sie unter isEnabled .

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

EID erhalten (öffentlich)

Ruft die EID ab, die die eUICC-Hardware identifiziert. Dies kann null sein, wenn die eUICC nicht bereit ist. Der Anrufer muss über Netzbetreiberprivilegien oder die Berechtigung READ_PRIVILEGED_PHONE_STATE verfügen. Einzelheiten finden Sie getEid .

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

EuiccInfo abrufen (öffentlich)

Ruft Informationen über die eUICC ab. Dies enthält die Betriebssystemversion. Einzelheiten finden Sie unter getEuiccInfo .

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

Abonnement herunterladen (öffentlich)

Lädt das angegebene Abonnement herunter (in GSMA-RSP-Dokumenten als „Profil“ bezeichnet). Das Abonnement kann über einen Aktivierungscode erstellt werden. Beispielsweise kann ein Aktivierungscode aus einem QR-Code geparst werden. Das Herunterladen eines Abonnements ist ein asynchroner Vorgang.

Der Aufrufer muss entweder über die Berechtigung WRITE_EMBEDDED_SUBSCRIPTIONS oder über Netzbetreiberrechte für das Zielabonnement verfügen. Einzelheiten finden Sie unter 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);

Abonnement wechseln (öffentlich)

Wechselt zum angegebenen Abonnement (aktiviert es). Der Aufrufer muss entweder über WRITE_EMBEDDED_SUBSCRIPTIONS verfügen oder über Betreiberrechte für das aktuell aktivierte Abonnement und das Zielabonnement verfügen. Einzelheiten finden Sie unter 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);

Abonnement mit Port (öffentlich) wechseln

(Verfügbar ab Android 13) Wechselt zum angegebenen Abonnement (aktiviert es) mit dem angegebenen Portindex. Der Aufrufer muss entweder über WRITE_EMBEDDED_SUBSCRIPTIONS verfügen oder über Betreiberrechte für das aktuell aktivierte Abonnement und das Zielabonnement verfügen. Einzelheiten finden Sie unter 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);

Ist der SIM-Port verfügbar (öffentlich)?

public boolean isSimPortAvailable(int portIndex)

(Verfügbar ab Android 13) Gibt zurück, ob der übergebene Portindex verfügbar ist. Ein Port ist verfügbar, wenn für ihn kein Abonnement aktiviert ist oder die anrufende App über Netzbetreiberrechte für das auf dem ausgewählten Port installierte Abonnement verfügt. Einzelheiten finden Sie unter isSimPortAvailable .

Abonnement löschen (öffentlich)

Löscht ein Abonnement mit einer Abonnement-ID. Wenn das Abonnement derzeit aktiv ist, wird es zunächst deaktiviert. Der Aufrufer muss entweder über WRITE_EMBEDDED_SUBSCRIPTIONS oder Betreiberrechte für das Zielabonnement verfügen. Einzelheiten finden Sie unter 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);

Alle Abonnements löschen (System-API)

Löscht alle Abonnements auf einem Gerät. Ab Android 11 sollten Sie einen EuiccCardManager#ResetOption Enumerationswert angeben, um anzugeben, ob alle Test-, Betriebs- oder beide Arten von Abonnements gelöscht werden sollen. Der Aufrufer muss über die Berechtigung WRITE_EMBEDDED_SUBSCRIPTIONS verfügen.

// 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);

Lösungsaktivität starten (öffentlich)

Startet eine Aktivität zur Behebung eines vom Benutzer lösbaren Fehlers. Wenn ein Vorgang EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR zurückgibt, kann diese Methode aufgerufen werden, um den Benutzer aufzufordern, das Problem zu beheben. Diese Methode kann nur einmal für einen bestimmten Fehler aufgerufen werden.

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

Konstanten

Eine Liste der public Konstanten in EuiccManager finden Sie unter Konstanten .