En Android 9, las APIs de administración de perfiles (públicas y @SystemApi) están disponibles a través de la clase EuiccManager
. Las APIs de comunicación de eUICC (solo @SystemApi) están disponibles a través de la clase EuiccCardManager
.
Información acerca de la eUICC
Los operadores pueden crear apps de operador con EuiccManager para administrar perfiles, como se muestra en la Figura 1. Las apps del operador no tienen que ser apps del sistema, pero deben tener privilegios del operador otorgados por los perfiles de eUICC. Una app de LPA (backend de LUI y LPA) debe ser una app del sistema (es decir, incluida en la imagen del sistema) para llamar a @SystemApi.
Figura 1: Teléfonos Android con app del operador y LPA del OEM
Además de la lógica de llamar a EuiccCardManager
y comunicarse con la eUICC, las apps de LPA deben implementar lo siguiente:
- Cliente SM-DP+ que se comunica con el servidor SM-DP+ para autenticar y descargar perfiles
- [Opcional] SM-DS para obtener más perfiles descargables potenciales
- Control de notificaciones para enviar notificaciones al servidor a fin de actualizar el estado del perfil
- [Opcional] Administración de ranuras, incluido el cambio entre la lógica de eSIM y pSIM. Esto es opcional si el teléfono solo tiene un chip eSIM.
- OTA de eSIM
Aunque se puede incluir más de una app de LPA en un teléfono Android, solo se puede seleccionar una para que sea la LPA que funcione según la prioridad definida en el archivo AndroidManifest.xml
de cada app.
Cómo usar EuiccManager
Las APIs de LPA son públicas a través de EuiccManager
(en el paquete android.telephony.euicc
). Una app del operador puede obtener la instancia de EuiccManager
y llamar a los métodos en EuiccManager
para obtener la información de la eUICC y administrar las suscripciones (denominadas perfiles en los documentos de RSP de GSMA) como instancias de SubscriptionInfo.
Para llamar a las APIs públicas, incluidas las operaciones de descarga, cambio y eliminación de suscripción, la app del operador debe tener los privilegios necesarios. El operador de telefonía celular agrega los privilegios del operador en los metadatos del perfil. La API de eUICC aplica las reglas de privilegios del operador según corresponda.
La plataforma de Android no controla las reglas de la política de perfil. Si se declara una regla de política en los metadatos del perfil, el LPA puede elegir cómo controlar el procedimiento de descarga e instalación del perfil. Por ejemplo, es posible que un LPA de OEM externo controle las reglas de políticas con un código de error especial (el código de error se pasa del LPA de OEM a la plataforma y, luego, la plataforma pasa el código a la LUI del OEM).
Para obtener información sobre varias APIs de perfiles habilitados, consulta Varios perfiles habilitados.
APIs
Puedes encontrar las siguientes APIs en la documentación de referencia de EuiccManager
y en EuiccManager.java
.
Obtener instancia (pública)
Obtiene la instancia de EuiccManager
a través de Context#getSystemService
.
Para obtener más información, consulta getSystemService
.
EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
Verificación habilitada (pública)
Verifica si la suscripción incorporada está habilitada. Esto se debe verificar antes de acceder a las APIs de LPA. Para obtener más información, consulta isEnabled
.
boolean isEnabled = mgr.isEnabled();
if (!isEnabled) {
return;
}
Cómo obtener el EID (público)
Obtiene el EID que identifica el hardware de la eUICC. Puede ser nulo si la eUICC no está lista. El emisor debe tener el privilegio del operador o el permiso READ_PRIVILEGED_PHONE_STATE
. Para obtener más información, consulta getEid
.
String eid = mgr.getEid();
if (eid == null) {
// Handle null case.
}
Get EuiccInfo (público)
Obtiene información sobre el eUICC. Contiene la versión del SO. Para obtener más información, consulta getEuiccInfo
.
EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();
Suscripción de descarga (pública)
Descarga la suscripción determinada (denominada “perfil” en los documentos de GSMA RSP). La suscripción se puede crear a partir de un código de activación. Por ejemplo, un código de activación se puede analizar a partir de un código QR. La descarga de una suscripción es una operación asíncrona.
El llamador debe tener el permiso WRITE_EMBEDDED_SUBSCRIPTIONS
o privilegios del operador para la suscripción de destino. Para obtener más información, consulta 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);
Cambiar de suscripción (pública)
Cambia a (habilita) la suscripción determinada. El emisor debe tener WRITE_EMBEDDED_SUBSCRIPTIONS
o privilegios de operador para la suscripción habilitada actual y la suscripción de destino. Para obtener más información, consulta 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);
Cambia la suscripción con el puerto (público)
(Disponible a partir de Android 13) Cambia a (habilita) la suscripción determinada con el índice de puerto especificado.
El llamador debe tener WRITE_EMBEDDED_SUBSCRIPTIONS
o privilegios del operador para la suscripción habilitada actual y la suscripción objetivo.
Para obtener más información, consulta 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);
¿Está disponible el puerto SIM (público)?
public boolean isSimPortAvailable(int portIndex)
(Disponible a partir de Android 13) Muestra si el índice de puerto de paso está disponible. Un puerto está disponible si no tiene habilitada ninguna suscripción o si la app de llamada tiene privilegios del operador sobre la suscripción instalada en el puerto seleccionado. Para obtener más información, consulta isSimPortAvailable
.
Borrar suscripción (pública)
Borra una suscripción con un ID de suscripción. Si la suscripción está activa, primero se inhabilita. El llamador debe tener privilegios WRITE_EMBEDDED_SUBSCRIPTIONS
o del operador para la suscripción de destino. Para obtener más información, consulta 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);
Borrar todas las suscripciones (API del sistema)
Borra todas las suscripciones de un dispositivo. A partir de Android 11, debes proporcionar un valor de enumeración EuiccCardManager#ResetOption
para especificar si se borran todas las suscripciones de pruebas, las operacionales o ambos tipos. El llamador debe tener el permiso 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);
Iniciar actividad de resolución (pública)
Inicia una actividad para resolver un error que el usuario puede resolver. Si una operación muestra EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
, se puede llamar a este método para solicitarle al usuario que resuelva el problema. Solo se puede llamar a este método una vez por un error en particular.
...
mgr.startResolutionActivity(getActivity(), 0 /* requestCode */, resultIntent, callbackIntent);
Constantes
Para ver una lista de las constantes public
en EuiccManager
, consulta Constantes.