addPermission method
Adds a permission to the AndroidManifest.xml file.
This method safely parses the XML, checks for duplicates, and inserts the permission in the appropriate location within the manifest.
Parameters
permissionName: The Android permission to add. Can be either:- Full permission string:
android.permission.CAMERA - Short name:
CAMERA(will be prefixed withandroid.permission.)
- Full permission string:
Returns
- Success if the permission was added or already exists
- Failure if the manifest could not be found or parsed
Example
final manager = AndroidManager('/path/to/project');
// Using full permission string
manager.addPermission('android.permission.CAMERA');
// Using short name (automatically prefixed)
manager.addPermission('INTERNET');
Manifest Changes
Before:
<manifest>
<application>...</application>
</manifest>
After:
<manifest>
<uses-permission android:name="android.permission.CAMERA"/>
<application>...</application>
</manifest>
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?',
);
}
// Normalize the permission name
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>.',
);
}
// Check if permission already exists (prevent duplicates)
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.');
}
}
// Create the new <uses-permission> element
final permissionElement = XmlElement(
XmlName('uses-permission'),
[XmlAttribute(XmlName('android:name'), fullPermission)],
);
// Find the best insertion point
final children = manifest.children.toList();
int insertIndex = 0;
// Look for existing permission/feature elements to insert after
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 no permission elements found, insert before <application> tag
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;
}
}
}
// Insert the permission with proper formatting
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}');
}
}