Hoy vamos a hacer un script que nos ayudará a editar el AndroidManifest.xml después de generar el build con React Native Expo para evitar permisos extras que añaden ciertas librerías.
En mi caso quiero eliminar el permiso:
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
Que añade automáticamente la librería de Expo Sensors.
Para eliminarlo lo que haremos es generar un paso posterior en el gradle que edite el AndroidManifest.xml y elimine el permiso.
Tenemos que añadir el siguiente script dentro de app/build.gradle dentro de Android:
applicationVariants.all { variant -> variant.outputs.each { output -> output.processManifest.doLast { def manifestFile = file("$buildDir/intermediates/merged_manifests/${variant.dirName}/AndroidManifest.xml") if (manifestFile.exists()) { def manifestText = manifestFile.getText('UTF-8') def updatedManifestText = manifestText.replaceAll('<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />', '') manifestFile.write(updatedManifestText, 'UTF-8') } } } }
Quedando de la siguiente forma en el archivo:
android { ... packagingOptions { ... } ... applicationVariants.all { variant -> variant.outputs.each { output -> output.processManifest.doLast { def manifestFile = file("$buildDir/intermediates/merged_manifests/${variant.dirName}/AndroidManifest.xml") if (manifestFile.exists()) { def manifestText = manifestFile.getText('UTF-8') def updatedManifestText = manifestText.replaceAll('<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />', '') manifestFile.write(updatedManifestText, 'UTF-8') } } } } ... }
Con esto habremos eliminado este permiso del manifest.
Si queremos añadir mas pondremos lo siguiente:
applicationVariants.all { variant -> variant.outputs.each { output -> output.processManifest.doLast { def manifestFile = file("$buildDir/intermediates/merged_manifests/${variant.dirName}/AndroidManifest.xml") if (manifestFile.exists()) { def manifestText = manifestFile.getText('UTF-8') def updatedManifestText = manifestText .replaceAll('<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />', '') .replaceAll('<uses-permission android:name="android.permission.SEND_SMS" />', '') .replaceAll('<uses-permission android:name="android.permission.RECEIVE_MMS" />', '') manifestFile.write(updatedManifestText, 'UTF-8') } } } }
A partir de Android Gradle 9.0 output.processManifest.doLast es obsoleto y se debe cambiar por: output.processManifestProvider.get().doLast
applicationVariants.all { variant -> variant.outputs.each { output -> output.processManifestProvider.get().doLast { def manifestFile = file("$buildDir/intermediates/merged_manifests/${variant.dirName}/AndroidManifest.xml") if (manifestFile.exists()) { def manifestText = manifestFile.getText('UTF-8') def updatedManifestText = manifestText .replaceAll('<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />', '') .replaceAll('<uses-permission android:name="android.permission.SEND_SMS" />', '') .replaceAll('<uses-permission android:name="android.permission.RECEIVE_SMS" />', '') .replaceAll('<uses-permission android:name="android.permission.READ_SMS" />', '') .replaceAll('<uses-permission android:name="android.permission.RECEIVE_MMS" />', '') .replaceAll('<uses-permission android:name="android.permission.READ_MMS" />', '') manifestFile.write(updatedManifestText, 'UTF-8') } } } }
PARTE 2: Añadir el script automáticamente sin editar el archivo gradle.build.
Para realizar esta parte de forma automática por ejemplo al hacer expo prebuild tendremos que crear un plugin que nos añada esta configuración directamente en nuestro build.gradle.
Primero creamos el plugin encargado de realizar esta tarea, remove-permissions.js
const { withAppBuildGradle } = require('@expo/config-plugins'); const withCustomAndroidConfig = (config) => { config = withAppBuildGradle(config, (config) => { // Verifica que el contenido del build.gradle esté presente if (config.modResults.contents) { const buildGradleContents = config.modResults.contents; // Verificar si el código ya está presente para evitar duplicados const codeToAdd = ` applicationVariants.all { variant -> variant.outputs.each { output -> output.processManifestProvider.get().doLast { def manifestFile = file("$buildDir/intermediates/merged_manifests/\${variant.dirName}/AndroidManifest.xml") if (manifestFile.exists()) { def manifestText = manifestFile.getText('UTF-8') def updatedManifestText = manifestText .replaceAll('<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />', '') .replaceAll('<uses-permission android:name="android.permission.SEND_SMS" />', '') .replaceAll('<uses-permission android:name="android.permission.RECEIVE_SMS" />', '') .replaceAll('<uses-permission android:name="android.permission.READ_SMS" />', '') .replaceAll('<uses-permission android:name="android.permission.RECEIVE_MMS" />', '') .replaceAll('<uses-permission android:name="android.permission.READ_MMS" />', '') .replaceAll('<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />', '') manifestFile.write(updatedManifestText, 'UTF-8') } } } }`; // Verificar si el texto ya está presente para evitar duplicados if (!buildGradleContents.includes(codeToAdd)) { // Agregar codeToAdd al final del bloque 'android { ... }' const modifiedContents = buildGradleContents.replace( /(android\s*{[\s\S]*?})/g, // Aquí buscamos el bloque 'android { ... }' (match) => { return `${match.trim()} ${codeToAdd}`; // Añadimos el texto justo antes de cerrar el bloque 'android' } ); config.modResults.contents = modifiedContents; console.log("Contenido modificado de build.gradle:", modifiedContents); } } return config; }); return config; }; module.exports = withCustomAndroidConfig;
Ahora añadimos este plungin dentro de app.json
"plugins": [ ... "./remove-permissions" ],
Indica la ruta correcta, aquí suponemos que es en raíz.
Ahora si ejeuctamos:
expo prebuild
Veremos añadido en build.gradle nuestro script de forma automática.
Ingeniero en Informática, me encanta crear cosas o arreglarlas y darles una nueva vida. Escritor y poeta. Más de 20 APPs publicadas y un libro en Amazon.