detectMinSdkAndroid function

Future<MinSdkDetection> detectMinSdkAndroid({
  1. String prefixPath = '.',
})

Like minSdk but additionally returns the human-readable label of the pattern that matched. Used by doctor to keep its report aligned with the generation pipeline's actual detection logic.

Implementation

Future<MinSdkDetection> detectMinSdkAndroid({String prefixPath = '.'}) async {
  final gradleFile = await findAndroidGradleFile(prefixPath);
  final localPropertiesFile = File(
    path.join(prefixPath, constants.androidLocalPropertiesFile),
  );

  if (gradleFile == null) {
    final fromLocalProps = await _getMinSdkFromLocalProperties(
      localPropertiesFile,
    );
    return MinSdkDetection(value: fromLocalProps, matchedLabel: null);
  }

  final isKts = gradleFile.path.endsWith('.kts');
  final patterns = isKts ? _ktsMinSdkPatterns : _groovyMinSdkPatterns;
  final content = await gradleFile.readAsString();

  for (final p in patterns) {
    final match = p.regex.firstMatch(content);
    if (match == null) {
      continue;
    }
    if (p.recurseToFlutter) {
      final fromFlutterGradle = await _getMinSdkFromFlutterSdkGradle(
        localPropertiesFile,
      );
      if (fromFlutterGradle != null) {
        return MinSdkDetection(value: fromFlutterGradle, matchedLabel: p.label);
      }
      final fromLocalProps = await _getMinSdkFromLocalProperties(
        localPropertiesFile,
      );
      // Even if the recurse failed to land a value, the pattern *did*
      // match; preserve the label so doctor can report the indirection.
      return MinSdkDetection(value: fromLocalProps, matchedLabel: p.label);
    }
    final captured = match.group(1);
    if (captured == null) {
      continue;
    }
    final parsed = int.tryParse(captured);
    if (parsed != null) {
      return MinSdkDetection(value: parsed, matchedLabel: p.label);
    }
  }

  // No app-level pattern matched. Try local.properties as a last-ditch
  // effort. No `matchedLabel` because no gradle pattern matched.
  final fromLocalProps = await _getMinSdkFromLocalProperties(
    localPropertiesFile,
  );
  return MinSdkDetection(value: fromLocalProps, matchedLabel: null);
}