W Androidzie 9 interfejsy API do zarządzania profilami (publiczne i @SystemApi) są dostępne w klasie EuiccManager
. Interfejsy API komunikacji eUICC (@SystemApi only) są dostępne w klasie EuiccCardManager
.
Informacje o eUICC
Operatorzy mogą tworzyć aplikacje operatora za pomocą EuiccManager do zarządzania profilami, jak pokazano na rysunku 1. Aplikacje operatora nie muszą być aplikacjami systemowymi, ale muszą mieć uprawnienia operatora przyznane przez profile eUICC. Aplikacja LPA (LUI i backend LPA) musi być aplikacją systemową (tzn. być częścią obrazu systemu), aby wywoływać @SystemApi.
Rysunek 1. Telefony z Androidem z aplikacją operatora i LPA producenta OEM
Oprócz logiki wywoływania EuiccCardManager
i komunikowania się z eUICC aplikacje LPA muszą implementować te funkcje:
- Klient SM-DP+ komunikuje się z serwerem SM-DP+, aby uwierzytelnić i pobrać profile
- [Opcjonalnie] SM-DS, aby uzyskać więcej potencjalnych profili do pobrania
- Obsługa powiadomień w celu wysyłania powiadomień na serwer w celu aktualizacji stanu profilu
- [Opcjonalnie] Zarządzanie gniazdami, w tym przełączanie między logiką eSIM i pSIM. Jest to opcjonalne, jeśli telefon ma tylko chip eSIM.
- eSIM OTA
Chociaż na telefonie z Androidem może być więcej niż jedna aplikacja LPA, tylko jedna z nich może być faktycznie używana. Wybór zależy od priorytetu określonego w pliku AndroidManifest.xml
każdej aplikacji.
Używanie EuiccManager
Interfejsy LPA API są publiczne w ramach EuiccManager
(w pakiecie android.telephony.euicc
). Aplikacja operatora może uzyskać instancję EuiccManager
i wywoływać metody w EuiccManager
, aby pobierać informacje o eUICC i zarządzać subskrypcjami (w dokumentach GSMA RSP nazywanymi profilami) jako instancjami SubscriptionInfo.
Aby wywoływać publiczne interfejsy API, w tym operacje pobierania, przełączania i usuwania subskrypcji, aplikacja operatora musi mieć wymagane uprawnienia. Uprawnienia operatora są dodawane przez operatora komórkowego w metadanych profilu. Interfejs eUICC API egzekwuje odpowiednio reguły uprawnień operatora.
Platforma Android nie obsługuje reguł zasad profilu. Jeśli w metadanych profilu zadeklarowano regułę zasad, LPA może wybrać sposób obsługi pobierania i instalowania profilu. Na przykład zewnętrzny dostawca OEM LPA może obsługiwać reguły zasad za pomocą specjalnego kodu błędu (kod błędu jest przekazywany z OEM LPA na platformę, a następnie z platformy do OEM LUI).
Więcej informacji o interfejsach API wielu włączonych profili znajdziesz w artykule Wiele włączonych profili.
Interfejsy API
Poniższe interfejsy API znajdziesz w EuiccManager
dokumentacji referencyjnej i EuiccManager.java
.
Pobieranie instancji (publicznej)
Pobiera instancję EuiccManager
przez Context#getSystemService
.
Więcej informacji znajdziesz w sekcji getSystemService
.
EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
Sprawdzanie włączone (publiczne)
Sprawdza, czy wbudowana subskrypcja jest włączona. Należy to sprawdzić przed uzyskaniem dostępu do interfejsów API LPA. Więcej informacji znajdziesz w sekcji isEnabled
.
boolean isEnabled = mgr.isEnabled();
if (!isEnabled) {
return;
}
Pobieranie identyfikatora EID (publicznego)
Pobiera numer EID identyfikujący sprzęt eUICC. Może mieć wartość null, jeśli karta eUICC nie jest gotowa. Dzwoniący musi mieć uprawnienia operatora lub uprawnienie READ_PRIVILEGED_PHONE_STATE
. Więcej informacji znajdziesz w sekcji getEid
.
String eid = mgr.getEid();
if (eid == null) {
// Handle null case.
}
Get EuiccInfo (public)
Pobiera informacje o karcie eUICC. Zawiera wersję systemu operacyjnego. Więcej informacji znajdziesz w sekcji getEuiccInfo
.
EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();
Pobieranie subskrypcji (publicznej)
Pobiera daną subskrypcję (w dokumentach GSMA RSP nazywaną „profilem”). Subskrypcję można utworzyć na podstawie kodu aktywacyjnego. Na przykład kod aktywacyjny można odczytać z kodu QR. Pobieranie subskrypcji to operacja asynchroniczna.
Dzwoniący musi mieć uprawnienie WRITE_EMBEDDED_SUBSCRIPTIONS
lub uprawnienia operatora do subskrypcji docelowej. Więcej informacji znajdziesz w sekcji 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);
Przełączanie subskrypcji (publiczne)
Przełącza na podaną subskrypcję (włącza ją). Dzwoniący musi mieć WRITE_EMBEDDED_SUBSCRIPTIONS
lub uprawnienia operatora do bieżącej aktywnej subskrypcji i subskrypcji docelowej. Więcej informacji znajdziesz w sekcji 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);
Przełączanie subskrypcji z przeniesieniem numeru (publiczne)
(Dostępne od Androida 13) Przełącza się na podaną subskrypcję (włącza ją) z określonym indeksem portu.
Dzwoniący musi mieć WRITE_EMBEDDED_SUBSCRIPTIONS
lub uprawnienia operatora w przypadku bieżącej aktywnej subskrypcji i subskrypcji docelowej.
Więcej informacji znajdziesz w sekcji 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);
Czy port SIM jest dostępny (publiczny)
public boolean isSimPortAvailable(int portIndex)
(Dostępne od Androida 13) Zwraca informację o tym, czy dostępny jest indeks portu przekazującego. Port jest dostępny, jeśli nie ma włączonej subskrypcji lub aplikacja do dzwonienia ma uprawnienia operatora do subskrypcji zainstalowanej na wybranym porcie. Więcej informacji znajdziesz w sekcji isSimPortAvailable
.
Usuwanie subskrypcji (publiczne)
Usuwa subskrypcję o podanym identyfikatorze. Jeśli subskrypcja jest obecnie aktywna, najpierw zostanie wyłączona. Dzwoniący musi mieć WRITE_EMBEDDED_SUBSCRIPTIONS
lub uprawnienia operatora do docelowej subskrypcji. Więcej informacji znajdziesz w sekcji 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);
Usuwanie wszystkich subskrypcji (interfejs API systemu)
Usuwa wszystkie subskrypcje na urządzeniu. Począwszy od Androida 11, musisz podać wartość EuiccCardManager#ResetOption
enum, aby określić, czy chcesz usunąć wszystkie subskrypcje testowe, operacyjne czy oba rodzaje subskrypcji. Wywołujący musi mieć uprawnienie 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);
Rozpoczęcie aktywności związanej z rozwiązywaniem problemów (publiczne)
Uruchamia działanie, które ma rozwiązać błąd, który może naprawić użytkownik. Jeśli operacja zwróci wartość
EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
, można wywołać tę metodę, aby poprosić użytkownika o rozwiązanie problemu. Tę metodę można wywołać tylko raz w przypadku danego błędu.
...
mgr.startResolutionActivity(getActivity(), 0 /* requestCode */, resultIntent, callbackIntent);
Stałe
Listę stałych public
w EuiccManager
znajdziesz w sekcji Stałe.