AndroidManifest.xml es un archivo de configuración obligatorio para cada aplicación Android que describe sus componentes, permisos y metadatos. El sistema Android lee este archivo al instalar y ejecutar cada aplicación. Según Android Developers, 2025, sin un manifiesto correcto, la aplicación no se instala en el dispositivo. AndroidManifest.xml registra Activity, Service, BroadcastReceiver y ContentProvider para el sistema operativo.
Puntos clave
AndroidManifest.xml es el archivo de configuración raíz en formato XML que todo proyecto Android debe tener en el directorio app/src/main. El sistema Android lo analiza antes de ejecutar cualquier código de la aplicación — durante el análisis del APK en la instalación. Si el manifiesto tiene un error de sintaxis o falta una declaración obligatoria, la instalación se interrumpe con un mensaje de error.
El archivo contiene una declaración completa de la aplicación: una lista de todos los componentes (Activity, Service, BroadcastReceiver, ContentProvider), permisos solicitados, versión mínima del SDK, requisitos de hardware y configuración de temas y estilos. Cada componente que pueda ser invocado por el sistema u otras aplicaciones debe declararse explícitamente en el manifiesto. Este es un requisito de seguridad: sin una declaración explícita, el componente no está disponible para su invocación.
Sin un manifiesto configurado correctamente, la aplicación no se puede instalar a través de Google Play ni mediante sideloading. El sistema verifica el manifiesto durante el análisis del APK y rechaza la instalación si hay errores. Google Play también analiza el manifiesto en busca de configuraciones inseguras: si exported=true en un componente sin intent-filter, se emite una advertencia; y si faltan permisos obligatorios para targetSdk 34+, se bloquea la publicación. Por lo tanto, comprender la estructura del manifiesto es una habilidad obligatoria para los desarrolladores de Android.
Cada componente de una aplicación Android debe estar explícitamente registrado en el manifiesto. Este es un requisito obligatorio de la plataforma para los cuatro tipos de componentes. Sin registro, el componente no puede ser creado por el sistema, e intentar iniciarlo provocará una ActivityNotFoundException o una excepción similar. Los componentes se registran dentro de la etiqueta application en un orden que no afecta su funcionamiento.
La etiqueta activity registra una pantalla de la aplicación. El atributo exported determina si otras aplicaciones pueden iniciar esta Activity. A partir de Android 12, la ausencia de exported cuando hay intent-filter provoca un error de compilación — esto es un requisito de seguridad. El punto de entrada se define mediante intent-filter con action MAIN y category LAUNCHER. Cada Activity debe tener un android:name único que coincida con el nombre completo o relativo de la clase.
<activity
android:name=".MainActivity"
android:exported="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
La etiqueta service define un servicio en segundo plano. A partir de Android 8, los servicios en segundo plano tienen limitaciones estrictas: un foreground service requiere una notificación obligatoria visible para el usuario con un icono, y un bound service solo vive mientras tiene un cliente vinculado. Los servicios que se ejecutan en segundo plano sin notificación son terminados automáticamente por el sistema a los pocos minutos de que la aplicación pase a segundo plano. Para tareas de larga duración, usa WorkManager en lugar de Service.
<service
android:name=".SyncService"
android:exported="false"
android:foregroundServiceType="dataSync" />
La etiqueta receiver declara un receptor de mensajes de difusión del sistema o personalizados. A partir de Android 8, la mayoría de las transmisiones implícitas ya no se entregan a los receptores declarados estáticamente en el manifiesto. En su lugar, se recomienda registrar los receptores dinámicamente mediante Context.registerReceiver en el código. Las excepciones incluyen algunas transmisiones del sistema como BOOT_COMPLETED, que aún requieren registro estático en el manifiesto.
<receiver
android:name=".ConnectivityReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
Cada permiso peligroso en Android requiere una declaración en el manifiesto mediante la etiqueta uses-permission. A partir de Android 6, los permisos peligrosos se solicitan en tiempo de ejecución a través de un diálogo con el usuario, pero la declaración en el manifiesto sigue siendo obligatoria. Sin ella, el método requestPermissions lanza una SecurityException. Los permisos de nivel normal como INTERNET y ACCESS_NETWORK_STATE se otorgan automáticamente durante la instalación.
| Permiso | Propósito |
|---|---|
| CAMERA | Acceso a la cámara del dispositivo para fotos y videos |
| ACCESS_FINE_LOCATION | Geolocalización precisa mediante GPS y red |
| RECORD_AUDIO | Grabación de audio desde el micrófono del dispositivo |
| READ_CONTACTS | Lectura de contactos de la agenda telefónica |
| POST_NOTIFICATIONS | Envío de notificaciones en Android 13+ |
La etiqueta uses-permission-sdk-23 especifica permisos necesarios solo en Android 6.0+. Esto permite mantener la compatibilidad con versiones anteriores sin solicitar permisos inexistentes. Por ejemplo, POST_NOTIFICATIONS solo está disponible en Android 13+, por lo que debe especificarse mediante uses-permission-sdk-33 para evitar un error de permiso desconocido en dispositivos más antiguos. El atributo maxSdkVersion en uses-permission permite revocar automáticamente permisos innecesarios al actualizar la aplicación en versiones más recientes de Android.
Los permisos de nivel normal (INTERNET, ACCESS_NETWORK_STATE) se otorgan automáticamente durante la instalación y no requieren solicitud en tiempo de ejecución. También se declaran mediante uses-permission, pero no se muestran al usuario en un diálogo. Para controlar el acceso a los componentes de la aplicación desde otras aplicaciones, se utiliza el mecanismo de componentes protegidos por permisos: se puede especificar un permiso personalizado a nivel de Activity o Service, que el sistema verificará cuando se llame al componente desde el exterior. Esto proporciona una capa adicional de seguridad para la comunicación entre procesos.
La etiqueta intent-filter en el manifiesto declara qué intents implícitos puede manejar un componente. Este es el mecanismo mediante el cual Android conecta acciones del sistema o personalizadas con la aplicación. Un intent filter consta de tres elementos: action (acción), category (categoría) y data (datos). Los tres se pueden combinar para describir con precisión qué intents debe recibir el componente. El sistema selecciona el componente adecuado según el filtro más específico.
<activity android:name=".DeepLinkActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="itsectr.com"
android:pathPrefix="/app" />
</intent-filter>
</activity>
El atributo autoVerify habilita la verificación de Android App Links: el sistema se comunica con el servidor para confirmar la propiedad del dominio. Sin verificación, los deep links funcionan a través del diálogo de selección estándar donde el usuario elige con qué aplicación abrir el enlace. Después de una verificación exitosa, los enlaces se abren directamente en la aplicación sin diálogo. Google Search Console también usa autoVerify para indexar deep links y mostrarlos en los resultados de búsqueda.
Los filtros con action.VIEW y las categorías DEFAULT y BROWSABLE manejan enlaces de navegadores, correos electrónicos y otras aplicaciones. Este es el mecanismo principal para implementar deep links en Android. Para admitir esquemas URL personalizados como myapp://, basta con especificar el scheme sin host. Sin embargo, Google recomienda usar deep links HTTPS en lugar de esquemas personalizados porque son más seguros y no requieren permisos adicionales. Los esquemas personalizados pueden ser interceptados por cualquier aplicación que registre el mismo esquema.
La etiqueta raíz manifest contiene atributos de paquete, versión y SDK. La etiqueta application almacena configuraciones globales: tema, icono, label y banderas de depuración. Los atributos de manifest definen el versionado a nivel de paquete, mientras que los atributos de application determinan la apariencia y el comportamiento general de la aplicación. Los valores pueden ser referencias a recursos mediante la sintaxis @ o literales de cadena.
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itsectr.myapp"
<uses-sdk
android:minSdkVersion="24"
android:targetSdkVersion="34" />
<application
android:label="MyApp"
android:icon="@mipmap/ic_launcher"
android:theme="@style/Theme.MyApp"
android:supportsRtl="true"
android:allowBackup="true">
<!-- Componentes de la aplicación -->
</application>
</manifest>
La etiqueta meta-data dentro de application permite almacenar pares clave-valor arbitrarios. Esto es útil para configurar bibliotecas de terceros: claves de API, URL de endpoints y banderas de funcionalidad. Los datos de meta-data son accesibles mediante PackageManager.getApplicationInfo().metaData en tiempo de ejecución. Por ejemplo, Firebase y Google Maps usan meta-data para pasar claves de acceso sin codificarlas directamente en el código fuente. En su lugar, las claves se definen en el manifiesto y pueden diferir según las variantes de compilación.
El atributo android:extractNativeLibs controla la extracción de bibliotecas nativas del APK. Para aplicaciones con targetSdk 34+, este atributo debe especificarse explícitamente; de lo contrario, la compilación puede fallar con el error INSTALL_FAILED_INVALID_APK. Si extractNativeLibs=false, las bibliotecas nativas permanecen dentro del APK sin desempaquetarse, lo que reduce el tamaño de la aplicación instalada pero aumenta el tiempo de carga de las bibliotecas. Para la mayoría de las aplicaciones modernas, se recomienda extractNativeLibs=false para reducir el espacio en disco utilizado en el dispositivo del usuario.
El atributo android:networkSecurityConfig permite especificar un archivo de configuración de seguridad de red. Esto es especialmente importante para aplicaciones con targetSdk 28+, donde el tráfico HTTP está bloqueado por defecto. El archivo de configuración define certificados de confianza, dominios para conexiones HTTP y reglas de pinning de certificados. Esto reemplaza el atributo obsoleto android:usesCleartextTraffic y proporciona un mecanismo más flexible para gestionar la seguridad de las conexiones a nivel del sistema operativo.
El atributo android:largeHeap solicita un tamaño de heap aumentado para la aplicación. Por defecto, Android asigna a cada aplicación una cantidad limitada de memoria que depende del dispositivo y la versión del sistema operativo. Si la aplicación trabaja con imágenes pesadas, videos o grandes conjuntos de datos, largeHeap puede evitar OutOfMemoryError. Sin embargo, abusar de este atributo es perjudicial: una aplicación con alto consumo de memoria es terminada más rápidamente por el sistema cuando hay escasez de recursos. Usa largeHeap solo después de realizar un perfilado y confirmar la necesidad.
Preguntas frecuentes
A partir de Android 12, la ausencia del atributo exported cuando hay intent-filter provoca un error de compilación. El sistema requiere visibilidad explícita para cada componente con intent-filter — esta es una medida de seguridad para evitar la exposición accidental de componentes a otras aplicaciones. Para una Activity sin intent-filter, exported es false por defecto.
Sí, pero el lanzador mostrará varios iconos de la aplicación. Cada Activity con MAIN/LAUNCHER se convierte en un punto de entrada independiente. Esto se usa para crear accesos directos a diferentes secciones de la aplicación, por ejemplo, para ir directamente a la configuración o crear un nuevo registro. Cada icono abre la Activity correspondiente directamente.
Android fusiona los manifiestos de las bibliotecas con el manifiesto principal de la aplicación. En caso de conflicto de atributos, se usa tools:replace o tools:node=“merge” para resolverlo. Este mecanismo es automático: cuando se agrega una biblioteca mediante Gradle, su manifiesto se fusiona con el principal. Para anular o reemplazar un atributo de una biblioteca, usa tools:node=“remove” o tools:replace=“attributeName”.
Razones típicas: el permiso no está declarado en el manifiesto mediante uses-permission, es un permiso de nivel normal (sin solicitud en tiempo de ejecución), el usuario seleccionó “No volver a preguntar” y el permiso está denegado permanentemente, o el targetSdkVersion es inferior a 23, donde los permisos se solicitan durante la instalación. Para el diagnóstico, verifica el manifiesto y los registros mediante adb logcat.
El atributo android:debuggable habilita la depuración de la aplicación mediante ADB. Para las compilaciones de lanzamiento en Google Play, debe ser false. Si debuggable=true en una compilación de lanzamiento, un atacante puede conectarse a la aplicación mediante ADB, leer datos y ejecutar código arbitrario. Google Play bloquea automáticamente la publicación de compilaciones con debuggable=true.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también