W Androidzie 9 interfejsy API do zarządzania profilami (publiczne i @SystemApi) są dostępne za pomocą klasy EuiccManager
. Interfejsy API do komunikacji eUICC (tylko @SystemApi) są dostępne w klasie EuiccCardManager
.
Informacje o kartach eUICC
Operatorzy mogą tworzyć aplikacje operatora, aby zarządzać profilami za pomocą interfejsu EuiccManager, jak pokazano na rysunku 1. Aplikacje operatora nie muszą być aplikacjami systemowymi, ale muszą mieć uprawnienia operatora przyznawane przez profile eUICC. Aby wywołać interfejs @SystemApi, aplikacja LPA (interfejs użytkownika i back-end LPA) musi być aplikacją systemową (czyli musi być uwzględniona w systemowym pliku obrazu).
Rysunek 1. telefony z Androidem z aplikacją operatora i usługą LPA OEM,
Oprócz logiki wywoływania EuiccCardManager
i komunikowania się z eUICC aplikacje LPA muszą implementować:
- 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ń do serwera w celu zaktualizowania stanu profilu
- [Opcjonalnie] Zarządzanie slotami, w tym przełączanie się między logiką eSIM i pSIM. To pole jest opcjonalne, jeśli telefon ma tylko kartę eSIM.
- eSIM OTA
Na telefonie z Androidem może być zainstalowanych więcej niż 1 aplikacja LPA, ale tylko 1 z nich może być wybrana jako aktywna na podstawie priorytetu zdefiniowanego w pliku AndroidManifest.xml
każdej aplikacji.
Korzystanie z EuiccManager
Interfejsy LPA API są publiczne za pośrednictwem EuiccManager
(w ramach pakietu android.telephony.euicc
). Aplikacja operatora może pobrać instancję EuiccManager
i wywoływać metody w EuiccManager
, aby uzyskać informacje o eUICC i zarządzać subskrypcjami (określanymi jako profile w dokumentach GSMA RSP) jako instancje 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 odpowiednie zasady dotyczące przywilejów operatora.
Platforma Android nie obsługuje zasad dotyczących profilu. Jeśli w metadanych profilu jest zadeklarowana reguła zasad, dostawca aplikacji o ograniczonym dostępie może wybrać sposób postępowania z procedurą pobierania i instalacji profilu. Na przykład zewnętrzny OEM LPA może obsługiwać reguły zasad za pomocą specjalnego kodu błędu (kod błędu jest przekazywany z OEM LPA do platformy, a następnie platforma przekazuje kod do LUI OEM).
Informacje o interfejsach API z wielu włączonych profili znajdziesz w artykule Wiele włączonych profili.
Interfejsy API
Te interfejsy API znajdziesz w dokumentacji referencyjnej EuiccManager
i EuiccManager.java
.
Pobieranie instancji (publiczne)
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 subskrypcja wbudowana jest włączona. Należy to sprawdzić przed uzyskaniem dostępu do interfejsów LPA API. Więcej informacji znajdziesz w sekcji isEnabled
.
boolean isEnabled = mgr.isEnabled();
if (!isEnabled) {
return;
}
Pobieranie EID (publiczny)
Pobiera identyfikator EID identyfikujący sprzęt eUICC. Może być ona pusta, jeśli eUICC nie jest gotowy. Osoba dzwoniąca 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 eUICC. Zawiera wersję systemu operacyjnego. Więcej informacji znajdziesz w sekcji getEuiccInfo
.
EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();
Subskrypcja pobierania (publiczna)
Pobiera daną subskrypcję (w dokumentach GSMA RSP nazywaną „profilem”). Subskrypcję można utworzyć za pomocą kodu aktywacyjnego. Na przykład kod aktywacyjny może być zinterpretowany z kodu QR. Pobieranie subskrypcji to operacja asynchroniczna.
Wywołujący musi mieć uprawnienia WRITE_EMBEDDED_SUBSCRIPTIONS
lub uprawnienia operatora dotyczące 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łącz subskrypcję (publiczna)
Przełącza (włącza) daną subskrypcję. Osoba dzwoniąca musi mieć uprawnienia WRITE_EMBEDDED_SUBSCRIPTIONS
lub uprawnienia operatora dotyczące bieżącej 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łącz subskrypcję z portem (publiczny)
(Dostępne od Androida 13) Przełącza (włącza) daną subskrypcję z określonym indeksem portu.
Osoba dzwoniąca musi mieć uprawnienia WRITE_EMBEDDED_SUBSCRIPTIONS
lub 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ę, czy indeks portów przekierowujących jest dostępny. Port jest dostępny, jeśli nie ma włączonej subskrypcji lub aplikacja do połączeń ma uprawnienia operatora dotyczące subskrypcji zainstalowanej na wybranym porcie. Więcej informacji znajdziesz w sekcji isSimPortAvailable
.
Usuń subskrypcję (publiczna)
Usuwa subskrypcję o podanym identyfikatorze. Jeśli subskrypcja jest obecnie aktywna, jest najpierw wyłączana. Osoba dzwoniąca musi mieć uprawnienia WRITE_EMBEDDED_SUBSCRIPTIONS
lub uprawnienia operatora dla subskrypcji docelowej. 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);
Wymaż wszystkie subskrypcje (interfejs API systemu)
kasuje wszystkie subskrypcje na urządzeniu. Począwszy od Androida 11, musisz podać wartość enumeracji EuiccCardManager#ResetOption
, aby określić, czy usunąć wszystkie subskrypcje testowe, operacyjne czy oba typy. 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 rozwiązywania problemu (publicznie)
Rozpoczyna działanie, które ma na celu rozwiązanie błędu, który użytkownik może naprawić. Jeśli operacja zwraca wartość EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
, ta metoda może zostać wywołana, aby poprosić użytkownika o rozwiązanie problemu. Ta metoda może być wywołana tylko raz w przypadku danego błędu.
...
mgr.startResolutionActivity(getActivity(), 0 /* requestCode */, resultIntent, callbackIntent);
Stałe
Aby zobaczyć listę stałych public
w funkcji EuiccManager
, zapoznaj się z artykułem Stałe.