В 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. Может быть пустым, если 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
см. в разделе Константы .