diff --git a/README.md b/README.md
index b094fab868..0650989eab 100644
--- a/README.md
+++ b/README.md
@@ -105,6 +105,8 @@ Shown below is the full list of attributes which you can specify within your Flu
be used to fill out the background of the adaptive icon.
- `adaptive_icon_foreground`: The image asset which will be used for the icon foreground of the adaptive icon
*Note: Adaptive Icons will only be generated when both adaptive_icon_background and adaptive_icon_foreground are specified. (the image_path is not automatically taken as foreground)*
+- `adaptive_icon_monochrome`: The image asset which will be used for the icon
+foreground of the Android 13+ themed icon. For more information see [Android Adaptive Icons](https://developer.android.com/develop/ui/views/launch/icon_design_adaptive#user-theming)
### IOS
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 1421ef5bcb..37f1c95755 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -8,10 +8,6 @@ analyzer:
missing_return: warning
# allow having TODOs in the code
todo: ignore
- # Ignore analyzer hints for updating pubspecs when using Future or
- # Stream and not importing dart:async
- # Please see https://github.com/flutter/flutter/pull/24528 for details.
- sdk_version_async_exported_from_core: ignore
exclude:
- "bin/cache/**"
# the following two are relative to the stocks example and the flutter package respectively
@@ -55,10 +51,9 @@ linter:
- flutter_style_todos
- hash_and_equals
- implementation_imports
- - iterable_contains_unrelated_type
+ - collection_methods_unrelated_type
- library_names
- library_prefixes
- - list_remove_unrelated_type
- no_adjacent_strings_in_list
- no_duplicate_case_values
- non_constant_identifier_names
diff --git a/bin/generate.dart b/bin/generate.dart
index 7f52e5cec5..b7772d7827 100644
--- a/bin/generate.dart
+++ b/bin/generate.dart
@@ -91,6 +91,7 @@ flutter_launcher_icons:
min_sdk_android: 21 # android min sdk min:16, default 21
# adaptive_icon_background: "assets/icon/background.png"
# adaptive_icon_foreground: "assets/icon/foreground.png"
+ # adaptive_icon_monochrome: "assets/icon/monochrome.png"
ios: true
# image_path_ios: "assets/icon/icon.png"
diff --git a/example/default_example/assets/images/icon-monochrome-432x432.png b/example/default_example/assets/images/icon-monochrome-432x432.png
new file mode 100644
index 0000000000..7a07022414
Binary files /dev/null and b/example/default_example/assets/images/icon-monochrome-432x432.png differ
diff --git a/example/default_example/pubspec.yaml b/example/default_example/pubspec.yaml
index c7d4046e7d..b3aab90ccd 100644
--- a/example/default_example/pubspec.yaml
+++ b/example/default_example/pubspec.yaml
@@ -21,6 +21,7 @@ flutter_launcher_icons:
ios: true # can specify file name here e.g. "My-Launcher-Icon"
adaptive_icon_background: "assets/images/christmas-background.png" # only available for Android 8.0 devices and above
adaptive_icon_foreground: "assets/images/icon-foreground-432x432.png" # only available for Android 8.0 devices and above
+ adaptive_icon_monochrome: "assets/images/icon-monochrome-432x432.png" # only available for Android 13 devices and above
min_sdk_android: 21 # android min sdk min:16, default 21
remove_alpha_ios: true
background_color_ios: "#ffffff"
diff --git a/lib/android.dart b/lib/android.dart
index a94d7ae773..a9e8327b9a 100644
--- a/lib/android.dart
+++ b/lib/android.dart
@@ -123,11 +123,83 @@ void createAdaptiveIcons(
flavor,
);
} else {
- createAdaptiveIconMipmapXmlFile(config, flavor);
updateColorsXmlFile(backgroundConfig, flavor);
}
}
+void createAdaptiveMonochromeIcons(
+ Config config,
+ String? flavor,
+) {
+ utils.printStatus('Creating adaptive monochrome icons Android');
+
+ // Retrieve the necessary Flutter Launcher Icons configuration from the pubspec.yaml file
+ final String? monochromeImagePath = config.adaptiveIconMonochrome;
+ if (monochromeImagePath == null) {
+ throw const InvalidConfigException(errorMissingImagePath);
+ }
+ final Image? monochromeImage = utils.decodeImageFile(monochromeImagePath);
+ if (monochromeImage == null) {
+ return;
+ }
+
+ // Create adaptive icon monochrome images
+ for (AndroidIconTemplate androidIcon in adaptiveForegroundIcons) {
+ overwriteExistingIcons(
+ androidIcon,
+ monochromeImage,
+ constants.androidAdaptiveMonochromeFileName,
+ flavor,
+ );
+ }
+}
+
+void createMipmapXmlFile(
+ Config config,
+ String? flavor,
+) {
+ utils.printStatus('Creating mipmap xml file Android');
+
+ String xmlContent = '';
+
+ if (config.hasAndroidAdaptiveConfig) {
+ if (isAdaptiveIconConfigPngFile(config.adaptiveIconBackground!)) {
+ xmlContent +=
+ ' \n';
+ } else {
+ xmlContent +=
+ ' \n';
+ }
+
+ xmlContent +=
+ ' \n';
+ }
+
+ if (config.hasAndroidAdaptiveMonochromeConfig) {
+ xmlContent +=
+ ' \n';
+ }
+
+ late File mipmapXmlFile;
+ if (config.isCustomAndroidFile) {
+ mipmapXmlFile = File(
+ constants.androidAdaptiveXmlFolder(flavor) + config.android + '.xml',
+ );
+ } else {
+ mipmapXmlFile = File(
+ constants.androidAdaptiveXmlFolder(flavor) +
+ constants.androidDefaultIconName +
+ '.xml',
+ );
+ }
+
+ mipmapXmlFile.create(recursive: true).then((File adaptiveIconFile) {
+ adaptiveIconFile.writeAsString(
+ xml_template.mipmapXmlFile.replaceAll('{{CONTENT}}', xmlContent),
+ );
+ });
+}
+
/// Retrieves the colors.xml file for the project.
///
/// If the colors.xml file is found, it is updated with a new color item for the
@@ -151,29 +223,6 @@ void updateColorsXmlFile(String backgroundConfig, String? flavor) {
}
}
-/// Creates the xml file required for the adaptive launcher icon
-/// FILE LOCATED HERE: res/mipmap-anydpi/{icon-name-from-yaml-config}.xml
-void createAdaptiveIconMipmapXmlFile(
- Config config,
- String? flavor,
-) {
- if (config.isCustomAndroidFile) {
- File(
- constants.androidAdaptiveXmlFolder(flavor) + config.android + '.xml',
- ).create(recursive: true).then((File adaptiveIcon) {
- adaptiveIcon.writeAsString(xml_template.icLauncherXml);
- });
- } else {
- File(
- constants.androidAdaptiveXmlFolder(flavor) +
- constants.androidDefaultIconName +
- '.xml',
- ).create(recursive: true).then((File adaptiveIcon) {
- adaptiveIcon.writeAsString(xml_template.icLauncherXml);
- });
- }
-}
-
/// creates adaptive background using png image
void _createAdaptiveBackgrounds(
Config config,
@@ -196,24 +245,6 @@ void _createAdaptiveBackgrounds(
flavor,
);
}
-
- // Creates the xml file required for the adaptive launcher icon
- // FILE LOCATED HERE: res/mipmap-anydpi/{icon-name-from-yaml-config}.xml
- if (config.isCustomAndroidFile) {
- File(
- constants.androidAdaptiveXmlFolder(flavor) + config.android + '.xml',
- ).create(recursive: true).then((File adaptiveIcon) {
- adaptiveIcon.writeAsString(xml_template.icLauncherDrawableBackgroundXml);
- });
- } else {
- File(
- constants.androidAdaptiveXmlFolder(flavor) +
- constants.androidDefaultIconName +
- '.xml',
- ).create(recursive: true).then((File adaptiveIcon) {
- adaptiveIcon.writeAsString(xml_template.icLauncherDrawableBackgroundXml);
- });
- }
}
/// Creates a colors.xml file if it was missing from android/app/src/main/res/values/colors.xml
diff --git a/lib/config/config.dart b/lib/config/config.dart
index db28cc559d..ba03809b68 100644
--- a/lib/config/config.dart
+++ b/lib/config/config.dart
@@ -27,6 +27,7 @@ class Config {
this.imagePathIOS,
this.adaptiveIconForeground,
this.adaptiveIconBackground,
+ this.adaptiveIconMonochrome,
this.minSdkAndroid = constants.androidDefaultAndroidMinSDK,
this.removeAlphaIOS = false,
this.backgroundColorIOS = '#ffffff',
@@ -116,7 +117,7 @@ class Config {
@JsonKey(name: 'image_path_ios')
final String? imagePathIOS;
- /// android adaptive icon foreground image
+ /// android adaptive_icon_foreground image
@JsonKey(name: 'adaptive_icon_foreground')
final String? adaptiveIconForeground;
@@ -124,6 +125,10 @@ class Config {
@JsonKey(name: 'adaptive_icon_background')
final String? adaptiveIconBackground;
+ /// android adaptive_icon_background image
+ @JsonKey(name: 'adaptive_icon_monochrome')
+ final String? adaptiveIconMonochrome;
+
/// Android min_sdk_android
@JsonKey(name: 'min_sdk_android')
final int minSdkAndroid;
@@ -157,6 +162,11 @@ class Config {
adaptiveIconForeground != null &&
adaptiveIconBackground != null;
+ /// whether or not there is configuration for monochrome icons for android
+ bool get hasAndroidAdaptiveMonochromeConfig {
+ return isNeedingNewAndroidIcon && adaptiveIconMonochrome != null;
+ }
+
/// Checks if contains any platform config
bool get hasPlatformConfig {
return ios != false ||
diff --git a/lib/config/config.g.dart b/lib/config/config.g.dart
index 82f2f481e9..2be66ae374 100644
--- a/lib/config/config.g.dart
+++ b/lib/config/config.g.dart
@@ -21,6 +21,8 @@ Config _$ConfigFromJson(Map json) => $checkedCreate(
$checkedConvert('adaptive_icon_foreground', (v) => v as String?),
adaptiveIconBackground:
$checkedConvert('adaptive_icon_background', (v) => v as String?),
+ adaptiveIconMonochrome:
+ $checkedConvert('adaptive_icon_monochrome', (v) => v as String?),
minSdkAndroid: $checkedConvert('min_sdk_android',
(v) => v as int? ?? constants.androidDefaultAndroidMinSDK),
removeAlphaIOS:
@@ -42,6 +44,7 @@ Config _$ConfigFromJson(Map json) => $checkedCreate(
'imagePathIOS': 'image_path_ios',
'adaptiveIconForeground': 'adaptive_icon_foreground',
'adaptiveIconBackground': 'adaptive_icon_background',
+ 'adaptiveIconMonochrome': 'adaptive_icon_monochrome',
'minSdkAndroid': 'min_sdk_android',
'removeAlphaIOS': 'remove_alpha_ios',
'backgroundColorIOS': 'background_color_ios',
@@ -59,6 +62,7 @@ Map _$ConfigToJson(Config instance) => {
'image_path_ios': instance.imagePathIOS,
'adaptive_icon_foreground': instance.adaptiveIconForeground,
'adaptive_icon_background': instance.adaptiveIconBackground,
+ 'adaptive_icon_monochrome': instance.adaptiveIconMonochrome,
'min_sdk_android': instance.minSdkAndroid,
'remove_alpha_ios': instance.removeAlphaIOS,
'background_color_ios': instance.backgroundColorIOS,
diff --git a/lib/constants.dart b/lib/constants.dart
index 9f51dab39b..6ef7d01c6b 100644
--- a/lib/constants.dart
+++ b/lib/constants.dart
@@ -24,6 +24,7 @@ const int androidDefaultAndroidMinSDK = 21;
const String androidFileName = 'ic_launcher.png';
const String androidAdaptiveForegroundFileName = 'ic_launcher_foreground.png';
const String androidAdaptiveBackgroundFileName = 'ic_launcher_background.png';
+const String androidAdaptiveMonochromeFileName = 'ic_launcher_monochrome.png';
String androidAdaptiveXmlFolder(String? flavor) =>
androidResFolder(flavor) + 'mipmap-anydpi-v26/';
const String androidDefaultIconName = 'ic_launcher';
diff --git a/lib/ios.dart b/lib/ios.dart
index 1339de35e3..5fad0e7da2 100644
--- a/lib/ios.dart
+++ b/lib/ios.dart
@@ -197,7 +197,7 @@ void modifyContentsFile(String newIconName) {
String generateContentsFileAsString(String newIconName) {
final Map contentJson = {
'images': createImageList(newIconName),
- 'info': ContentsInfoObject(version: 1, author: 'xcode').toJson()
+ 'info': ContentsInfoObject(version: 1, author: 'xcode').toJson(),
};
return json.encode(contentJson);
}
@@ -220,7 +220,7 @@ class ContentsImageObject {
'size': size,
'idiom': idiom,
'filename': filename,
- 'scale': scale
+ 'scale': scale,
};
}
}
@@ -390,7 +390,7 @@ List