En Android 9, las API de administración de perfiles (public y @SystemApi) están disponibles a través de la clase EuiccManager
. Las API de comunicación eUICC (@SystemApi únicamente) están disponibles a través de la clase EuiccCardManager
.
Acerca de eUICC
Los operadores pueden crear aplicaciones de operadores utilizando EuiccManager para administrar perfiles, como se muestra en la Figura 1. Las aplicaciones de operadores no necesitan ser aplicaciones del sistema, pero deben tener privilegios de operador otorgados por perfiles eUICC. Una aplicación LPA (LUI y backend LPA) debe ser una aplicación del sistema (es decir, incluida en la imagen del sistema) para llamar a @SystemApi.
Figura 1. Teléfonos Android con aplicación de operador y OEM LPA
Además de la lógica de llamar a EuiccCardManager
y hablar con eUICC, las aplicaciones LPA deben implementar lo siguiente:
- Cliente SM-DP+ hablando con el servidor SM-DP+ para autenticar y descargar perfiles
- [Opcional] SM-DS para obtener más perfiles descargables potenciales
- Manejo de notificaciones para enviar notificaciones al servidor para actualizar el estado del perfil
- [Opcional] Gestión de ranuras, incluida la conmutación entre lógica eSIM y pSIM. Esto es opcional si el teléfono solo tiene un chip eSIM.
- eSIM OTA
Aunque más de una aplicación LPA puede estar presente en un teléfono Android, solo se puede seleccionar una LPA para que sea la LPA de trabajo real según la prioridad definida en el archivo AndroidManifest.xml
de cada aplicación.
Uso de EuiccManager
Las API de LPA son públicas a través de EuiccManager
(en el paquete android.telephony.euicc
). Una aplicación de operador puede obtener la instancia de EuiccManager
y llamar a los métodos en EuiccManager
para obtener la información de eUICC y administrar las suscripciones (denominadas perfiles en los documentos GSMA RSP) como instancias de SubscriptionInfo.
Para llamar a las API públicas, incluidas las operaciones de descarga, cambio y eliminación de suscripción, la aplicación del operador debe tener los privilegios necesarios. Los privilegios del operador son agregados por el operador móvil en los metadatos del perfil. La API de eUICC hace cumplir las reglas de privilegio del operador en consecuencia.
La plataforma Android no maneja 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 manejar el procedimiento de descarga e instalación del perfil. Por ejemplo, es posible que un OEM LPA de terceros maneje las reglas de la política usando un código de error especial (el código de error se pasa del OEM LPA a la plataforma, luego la plataforma pasa el código a la OEM LUI).
API
Las siguientes API se pueden encontrar en la documentación EuiccManager
de EuiccManager y EuiccManager.java
.
Obtener instancia (pública)
Obtiene la instancia de EuiccManager
a través de Context#getSystemService
.
EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
Comprobar habilitado (público)
Comprueba si la suscripción integrada está habilitada. Esto debe verificarse antes de acceder a las API de LPA.
boolean isEnabled = mgr.isEnabled();
if (!isEnabled) {
return;
}
Obtener EID (público)
Obtiene el EID que identifica el hardware eUICC. Esto puede ser nulo si el eUICC no está listo. La persona que llama debe tener privilegios de operador o el permiso READ_PRIVILEGED_PHONE_STATE
.
String eid = mgr.getEid();
if (eid == null) {
// Handle null case.
}
Obtener EuiccInfo (público)
Obtiene información sobre la eUICC. Contiene la versión del sistema operativo.
EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();
Descargar suscripción (pública)
Descarga la suscripción dada (denominada "perfil" en los documentos 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 asincrónica.
La persona que llama debe tener el permiso WRITE_EMBEDDED_SUBSCRIPTIONS
o tener privilegios de operador para la suscripción de destino.
// 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 suscripción (pública)
Cambia a (habilita) la suscripción dada. La persona que llama debe tener WRITE_EMBEDDED_SUBSCRIPTIONS
o tener privilegios de operador para la suscripción habilitada actual y la suscripción de destino.
// 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);
Eliminar suscripción (pública)
Elimina una suscripción con un ID de suscripción. Si la suscripción está actualmente activa, primero se deshabilita. La persona que llama debe tener WRITE_EMBEDDED_SUBSCRIPTIONS
o privilegios de operador para la suscripción de destino.
// 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 en un dispositivo. A partir de Android 11, debe proporcionar un valor de enumeración EuiccCardManager#ResetOption
para especificar si desea borrar todas las suscripciones de prueba, operativas o ambos tipos. La persona que llama debe tener 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úblico)
Inicia una actividad para resolver un error que puede resolver el usuario. Si una operación devuelve EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
, se puede llamar a este método para solicitar al usuario que resuelva el problema. Este método solo se puede llamar una vez para un error en particular.
...
mgr.startResolutionActivity(getActivity(), 0 /* requestCode */, resultIntent, callbackIntent);
constantes
Para ver una lista de las constantes public
en EuiccManager
, consulte Constantes .