В Android 9 API управления профилями (публичные и @SystemApi) доступны через класс EuiccManager
. API связи eUICC (только @SystemApi) доступны через класс EuiccCardManager
.
О eUICC
Операторы могут создавать приложения оператора с помощью EuiccManager для управления профилями, как показано на рисунке 1. Приложения оператора не обязательно должны быть системными приложениями, но должны иметь привилегии оператора, предоставленные профилями eUICC. Приложение LPA (LUI и бэкэнд LPA) должно быть системным приложением (т. е. быть включенным в образ системы) для вызова @SystemApi.
Рисунок 1. Телефоны Android с приложением оператора и OEM LPA
Помимо логики вызова EuiccCardManager
и взаимодействия с eUICC, приложения LPA должны реализовывать следующее:
- Клиент SM-DP+ взаимодействует с сервером SM-DP+ для аутентификации и загрузки профилей
- [Необязательно] SM-DS для получения большего количества потенциально загружаемых профилей
- Обработка уведомлений для отправки уведомлений на сервер для обновления состояния профиля
- [Необязательно] Управление слотами, включая переключение между логикой eSIM и pSIM. Это необязательно, если в телефоне есть только чип eSIM.
- eSIM OTA
Хотя на телефоне Android может присутствовать более одного приложения LPA, только одно LPA может быть выбрано в качестве фактического рабочего LPA на основе приоритета, определенного в файле AndroidManifest.xml
каждого приложения.
Использовать EuiccManager
API LPA являются общедоступными через EuiccManager
(в пакете android.telephony.euicc
). Приложение оператора может получить экземпляр EuiccManager
и вызвать методы в EuiccManager
для получения информации eUICC и управления подписками (называемые профилями в документах GSMA RSP) как экземплярами SubscriptionInfo.
Для вызова публичных API, включая операции загрузки, переключения и удаления подписки, приложение оператора должно иметь требуемые привилегии. Привилегии оператора добавляются оператором мобильной связи в метаданные профиля. API eUICC соответствующим образом применяет правила привилегий оператора.
Платформа Android не обрабатывает правила политики профиля. Если правило политики объявлено в метаданных профиля, LPA может выбрать, как обрабатывать процедуру загрузки и установки профиля. Например, сторонний OEM LPA может обрабатывать правила политики с использованием специального кода ошибки (код ошибки передается из 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 не готов. Вызывающий должен иметь привилегию оператора или разрешение 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, необходимо указать значение перечисления 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);
Константы
Чтобы просмотреть список public
констант в EuiccManager
, см. Константы .