1

I've been trying to change my app icon using CFBundleAlternateIcons, but nothing happens. I'm actually using a plugin for the Flutter SDK - flutter_dynamic_icon, when I change the icon using the plugin, it says 'App icon change successful' as if nothing's wrong.

After doing some troubleshooting, I've also tried resaving the icons in Preview to ensure they're PNG files, and removing their alpha channels, with no change in results.

What am I doing wrong? Is it an Info.plist issue? Are my icons saved incorrectly? Am I calling for the icon change incorrectly?

This is how I try to change the icon in dart lang:

try {
  if (await FlutterDynamicIcon.supportsAlternateIcons) {
    await FlutterDynamicIcon.setAlternateIconName("dark");
    print("App icon change successful");
    return;
  }
} on PlatformException {} catch (e) {
  print("icon couldn't be changed");
}

This is what I see, never mind if I click to change to dark icon or light icon.

false positive

Here's my Info.plist / file structure:

<key>CFBundleIcons</key>
<dict>
    <key>CFBundleAlternateIcons</key>
    <dict>
        <key>light</key>
        <dict>
            <key>UIPrerenderedIcon</key>
            <string>NO</string>
            <key>CFBundleIconFiles</key>
            <array>
                <string>light</string>
            </array>
        </dict>
        <key>dark</key>
        <dict>
            <key>UIPrerenderedIcon</key>
            <string>NO</string>
            <key>CFBundleIconFiles</key>
            <array>
                <string>dark</string>
            </array>
        </dict>
    </dict>
    <key>CFBundlePrimaryIcon</key>
    <dict>
        <key>CFBundleIconFiles</key>
        <array>
            <string>dark</string>
        </array>
        <key>UIPrerenderedIcon</key>
        <false/>
    </dict>
</dict>

info.plist - property list

file structure

Jake
  • 1,906
  • 9
  • 32
  • 60

1 Answers1

1

EDIT: I've now figured out my issue, despite online guides advising you to place the alternate icons in a separate folder, my case only works if I place said icons directly inside the Runner directory.


I fixed this by defining the CFBundleIconFiles in Info.plist as follows. It's a subtle change, but can make or break the process.

Before:

<key>CFBundleIcons</key>
<dict>
    <key>CFBundleAlternateIcons</key>
    <dict>
        <key>light</key>
        <dict>
            <key>UIPrerenderedIcon</key>
            <string>NO</string>
            <key>CFBundleIconFiles</key>
            <array>
                <string>light</string>
            </array>
        </dict>
        <key>dark</key>
        <dict>
            <key>UIPrerenderedIcon</key>
            <string>NO</string>
            <key>CFBundleIconFiles</key>
            <array>
                <string>dark</string>
            </array>
        </dict>
    </dict>
    <key>CFBundlePrimaryIcon</key>
    <dict>
        <key>CFBundleIconFiles</key>
        <array>
            <string>dark</string>
        </array>
        <key>UIPrerenderedIcon</key>
        <false/>
    </dict>
</dict>

After:

<key>CFBundleIcons</key>
<dict>
    <key>CFBundlePrimaryIcon</key>
    <dict>
        <key>CFBundleIconFiles</key>
        <array>
            <string>light</string>
        </array>
        <key>UIPrerenderedIcon</key>
        <false/>
    </dict>
    <key>CFBundleAlternateIcons</key>
    <dict>
        <key>light</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>light</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>
        <key>dark</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>dark</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>
    </dict>
</dict>

Property list:

property list, shows 'CFBundleAlternateIcons', with children 'dark' and 'light' for each alt icon type.

Xcode project directory:

enter image description here

Jake
  • 1,906
  • 9
  • 32
  • 60
  • Check the bounty comments to see why I set a bounty on a question which I have already answered. – Jake Jan 04 '21 at 03:26
  • Jake, can you provide additional screenshots or more context when you fixed this? I'm trying to do the same, but supportsAlternateIcons is always returning false for me. – Luke Irvin Apr 08 '22 at 21:52
  • I've added a couple screenshots you might find helpful. Also, I just created a fresh app with just this dependency and a simple if else test statement for `(await FlutterDynamicIcon.supportsAlternateIcons` with no edits to Xcode, and I'm getting `true`. Might you want to post a snippet down here for me to check? – Jake Apr 09 '22 at 18:15
  • 1
    Thanks, Jake! It's working for me when testing on a physical device. Still always returns false via Simulator though. Though the two main example apps work ok via Simulator. not sure what's going on as it works as expected on the device. I'll circle back on sim when I have time. – Luke Irvin Apr 10 '22 at 21:09
  • No problem, good to hear you've seen it works. That's interesting to hear about the simulator though. Also as you mention it, I remember my successful test the other day was on a physical device, it's not immediately obvious to me why this doesn't work on the sim but I'll have a look when I'm next at my workstation. – Jake Apr 10 '22 at 22:57
  • This doesn't really add anything, but its returning true on an iOS 15 sim. – Jake Apr 18 '22 at 10:00