updateStylesXml function

Future<void> updateStylesXml({
  1. YamlMap? android12AndAbove,
  2. bool hasDarkDrawable = false,
})

Updates values/styles.xml for pre-Android 12 splash style references.

If android_12_and_above is present, this recreates values-v31/styles.xml using only values from that block. If hasDarkDrawable is false, this also ensures any existing night styles don't reference the dark drawable

Implementation

Future<void> updateStylesXml({
  YamlMap? android12AndAbove,
  bool hasDarkDrawable = false,
}) async {
  const androidValuesFolder = CmdStrings.androidValuesDirectory;

  // Only use values explicitly set under android_12_and_above.
  // Top-level color and image are not inherited by Android 12+.
  if (android12AndAbove != null) {
    const v31 = CmdStrings.androidValuesV31Directory;
    await _ensureDirectoryExists(v31);
    const style = '$v31/${AndroidStrings.stylesXml}';
    if (await File(style).exists()) {
      await File(style).delete();
    }
    final styleFile = File(style);

    await createAndroid12Styles(
      styleFile: styleFile,
      color: android12AndAbove[YamlKeys.colorKey] as String?,
      imageSource: android12AndAbove[YamlKeys.imageKey] as String?,
      brandingImageSource: android12AndAbove[YamlKeys.brandingImageKey],
    );
  }

  final xml = File('$androidValuesFolder/${AndroidStrings.stylesXml}');
  final xmlExists = await xml.exists();
  if (!xmlExists) {
    log("styles.xml doesn't exists");
    return;
  }
  final xmlDoc = XmlDocument.parse(xml.readAsStringSync());
  xmlDoc.findAllElements(AndroidStrings.itemElement).where((itemElement) {
    return itemElement.getAttribute(AndroidStrings.nameAttr) ==
        AndroidStrings.itemNameAttrValue;
  }).forEach((itemElement) {
    itemElement.setAttribute(
      AndroidStrings.nameAttr,
      AndroidStrings.itemNameAttrValue,
    );
    itemElement.innerText = AndroidStrings.drawableSplashScreen;
  });

  await xml.writeAsString(xmlDoc.toXmlString(pretty: true));
  log('styles.xml updated.');

  // Ensure any existing pre-Android 12 night styles don't reference the
  // dark drawable when the user hasn't provided dark-mode pre-Android 12
  // assets in pubspec. This prevents references to missing
  // `@drawable/splash_screen_dark` and points night styles to the light
  // drawable instead so resource linking succeeds.
  if (!hasDarkDrawable) {
    try {
      const nightValuesPath =
          '${CmdStrings.androidDarkValuesDirectory}/${AndroidStrings.stylesXml}';
      final nightFile = File(nightValuesPath);
      if (await nightFile.exists()) {
        final nightDoc = XmlDocument.parse(nightFile.readAsStringSync());
        var changed = false;
        for (final itemElement
            in nightDoc.findAllElements(AndroidStrings.itemElement)) {
          if (itemElement.getAttribute(AndroidStrings.nameAttr) ==
              AndroidStrings.itemNameAttrValue) {
            if (itemElement.innerText.trim() ==
                AndroidStrings.androidDarkDrawable) {
              itemElement.innerText = AndroidStrings.drawableSplashScreen;
              changed = true;
            }
          }
        }
        if (changed) {
          await nightFile.writeAsString(nightDoc.toXmlString(pretty: true));
          log('values-night/styles.xml updated to reference light drawable.');
        }
      }
    } catch (e) {
      log('Error updating values-night/styles.xml: $e');
    }
  }
}