В Android 9 API управления профилями (public и @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 ОТА
Хотя в телефоне 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 можно найти в справочной EuiccManager
EuiccManager и EuiccManager.java
.
Получить экземпляр (общедоступный)
Получает экземпляр EuiccManager
через Context#getSystemService
.
EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
Проверка включена (общедоступная)
Проверяет, включена ли встроенная подписка. Это следует проверить перед доступом к API LPA.
boolean isEnabled = mgr.isEnabled();
if (!isEnabled) {
return;
}
Получить EID (общедоступный)
Получает EID, идентифицирующий оборудование eUICC. Это может быть пустым, если карта eUICC не готова. Вызывающий должен иметь привилегию оператора связи или разрешение READ_PRIVILEGED_PHONE_STATE
.
String eid = mgr.getEid();
if (eid == null) {
// Handle null case.
}
Получить EuiccInfo (общедоступный)
Получает информацию о eUICC. Он содержит версию ОС.
EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();
Скачать подписку (общедоступную)
Загружает данную подписку (называемую «профилем» в документах GSMA RSP). Подписку можно создать из кода активации. Например, код активации можно получить из QR-кода. Загрузка подписки — это асинхронная операция.
Вызывающий должен либо иметь разрешение WRITE_EMBEDDED_SUBSCRIPTIONS
, либо иметь привилегии оператора для целевой подписки.
// 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
, либо иметь привилегии оператора связи для текущей включенной подписки и целевой подписки.
// 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);
Удалить подписку (общедоступную)
Удаляет подписку с идентификатором подписки. Если подписка в данный момент активна, она сначала отключается. Вызывающий должен иметь 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 */);
// 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
см. в разделе Константы .