getManifest method

  1. @override
File? getManifest()
override

Attempts to locate the AndroidManifest.xml actually used by the app. Returns null if it cannot be determined reliably.

Implementation

@override
File? getManifest() {
  final androidDir = Directory('${root.path}/android/app');
  if (!androidDir.existsSync()) return null;

  // 1. Check conventional location first (most common case)
  final conventional = File(
    '${androidDir.path}/src/main/AndroidManifest.xml',
  );
  if (conventional.existsSync() && _isMainManifest(conventional)) {
    return conventional;
  }

  // 2. Honor custom sourceSets in build.gradle(.kts)
  final gradleFiles = [
    File('${androidDir.path}/build.gradle'),
    File('${androidDir.path}/build.gradle.kts'),
  ].where((f) => f.existsSync());

  for (final gradle in gradleFiles) {
    final content = gradle.readAsStringSync();

    final match = RegExp(
      r'manifest\.srcFile\s*[=(]?\s*(["'
      "'"
      r'])(.+AndroidManifest\.xml)\1',
    ).firstMatch(content);
    if (match != null) {
      final customPath = match.group(2)!;

      // Try relative to android/app first
      var file = File('${androidDir.path}/$customPath');
      if (file.existsSync() && _isMainManifest(file)) return file;

      // Try relative to android root
      file = File('${root.path}/android/$customPath');
      if (file.existsSync() && _isMainManifest(file)) return file;

      // Try as absolute path
      file = File(customPath);
      if (file.existsSync() && _isMainManifest(file)) return file;
    }
  }

  // Anything beyond this requires Gradle execution
  return null;
}