Crear un script para editar AndroidManifest.xml después de generar el build con React Native Expo para eliminar permisos.

Tiempo de lectura: 3 minutos

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.

Deja un comentario