addPermission method

OperationResult addPermission(
  1. String permissionName
)

Adds a permission to the AndroidManifest.xml file.

Implementation

OperationResult addPermission(String permissionName) {
  final manifestFile = File(_manifestPath);

  if (!manifestFile.existsSync()) {
    return const Failure(
      'Could not find AndroidManifest.xml. '
      'Are you in a Flutter project root directory?',
    );
  }

  final fullPermission = permissionName.contains('.')
      ? permissionName
      : 'android.permission.$permissionName';

  try {
    final content = manifestFile.readAsStringSync();
    final document = XmlDocument.parse(content);

    final manifest = document.rootElement;

    if (manifest.name.local != 'manifest') {
      return const Failure(
        'Invalid AndroidManifest.xml: root element is not <manifest>.',
      );
    }

    const androidNs = 'http://schemas.android.com/apk/res/android';
    final existingPermissions = manifest.findAllElements('uses-permission');

    for (final permission in existingPermissions) {
      final nameAttr =
          permission.getAttribute('name', namespace: androidNs) ??
              permission.getAttribute('android:name');
      if (nameAttr == fullPermission) {
        return Success('Permission $fullPermission already exists.');
      }
    }

    final permissionElement = XmlElement(
      XmlName('uses-permission'),
      [XmlAttribute(XmlName('android:name'), fullPermission)],
    );

    final children = manifest.children.toList();
    int insertIndex = 0;

    for (int i = 0; i < children.length; i++) {
      final child = children[i];
      if (child is XmlElement) {
        if (child.name.local == 'uses-permission' ||
            child.name.local == 'uses-feature') {
          insertIndex = i + 1;
        }
      }
    }

    if (insertIndex == 0) {
      for (int i = 0; i < children.length; i++) {
        if (children[i] is XmlElement &&
            (children[i] as XmlElement).name.local == 'application') {
          insertIndex = i;
          break;
        }
      }
    }

    manifest.children.insert(insertIndex, XmlText('\n    '));
    manifest.children.insert(insertIndex + 1, permissionElement);

    final output = document.toXmlString(pretty: true, indent: '    ');
    manifestFile.writeAsStringSync(output);

    return Success('Successfully added permission: $fullPermission');
  } on XmlParserException catch (e) {
    return Failure('Failed to parse AndroidManifest.xml: ${e.message}');
  } on FileSystemException catch (e) {
    return Failure('Failed to update AndroidManifest.xml: ${e.message}');
  }
}