В 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 ОТА
Хотя на телефоне 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
, см. Константы .