Flutter - Can not change app icon programmatically using CFBundleAlternateIcons - ios

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 show a popup says 'You have changed the icon for MyApp' but nothing changes.
My question seems to be a repeat of this question: [https://stackoverflow.com/questions/64426880/xcode-ios-cfbundlealternateicons-not-changing] which already has an answer but it doesn't work for me.
I'm also trying to do the same as this article on medium: [https://medium.com/flutter-community/programatically-change-ios-app-icon-in-flutter-c9e84bc541a2] and the result is the same as when I used flutter_dynamic_icon.
Here is my info.plist:
<key>CFBundleIcons</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>teamfortress</key>
<dict>
<key>UIPrerenderedIcon</key>
<false/>
<key>CFBundleIconFiles</key>
<array>
<string>teamfortress</string>
</array>
</dict>
<key>chills</key>
<dict>
<key>UIPrerenderedIcon</key>
<false/>
<key>CFBundleIconFiles</key>
<array>
<string>chills</string>
</array>
</dict>
<key>photos</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>photos</string>
</array>
</dict>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
I think something is wrong with my info.plist.
Has anyone experienced this problem?. Please help me, thanks a lot.

I've figured out the answer recently, for some reasons, my app can only be able to change app icon dynamically when I add icon images directly in Runner folder in Xcode and run flutter project from it.
Hope it's helpful for you if you're encountering with above problem.

Related

Registering new extension that opens in own iOS-App

I created my own filetype "dmate". Assume I exported a .dmate file to iPhones Files. When clicking on that file, it is looking like this - the JSON-Content is displayed:
Now I can click on the share button and open the file in my App DietMate - which works fine:
Problem: I do not want the user to see JSON text but want the Files-App and WhatsApp and so on to open the file immediately in my App without doing a preview.
Here is the relevant part of my plist.info
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Food</string>
<key>CFBundleTypeIconFiles</key>
<array>
<string>dmate.ft.png</string>
<string>dmate.ft.png</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>de.example.app.food.dmate</string>
</array>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.json</string>
</array>
<key>UTTypeDescription</key>
<string>Food</string>
<key>UTTypeIdentifier</key>
<string>de.example.app.food.dmate</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>dmate</string>
<key>public.mime-type</key>
<string>food/x-dmate</string>
</dict>
</dict>
</array>
Does anyone know, how to open my custom filetype in my own app?
If you want your app to launch right away after tapping the file in the Files app, try adding this key-value pair to your Info.plist:
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
Another thing you could try is to set "Conforms To" to public.data instead of public.json. This means that the system will no longer assume that your data is JSON, and hopefully stop displaying it that way. It might have some implications on what sharing channels are supported, and I haven’t yet managed to fully wrap my head around this.

How the app icon is added inside my iOS app?

When I look my Info.plist their is nothing about icon in it, but after I deployed the app, I look in it for the the Info.plist and I can see that it's contain :
<key>CFBundleIcons</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AppIcon60x60</string>
</array>
<key>CFBundleIconName</key>
<string>AppIcon</string>
</dict>
</dict>
<key>CFBundleIcons~ipad</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AppIcon60x60</string>
<string>AppIcon76x76</string>
</array>
<key>CFBundleIconName</key>
<string>AppIcon</string>
</dict>
</dict>
I can see that also the root folder of my app contain 2 files :
AppIcon60x60#2x.png
AppIcon76x76#2x~ipad.png
but nothing in my project, in deployment option, is speaking about those 2 icons. so where they are coming from ? what process add the CFBundleIconFiles key value to the info.plist ?
I want to specify myself the icon (and not from the ide of delphi, I want to update myself the info.plist, and i want to deploy myself the icon), how can I do ?
I only have a partial answer but hopefully will point you in the right direction.
The default info.plist.TemplateiOS.xml contains:
<%VersionInfoPListKeys%>
<%ExtraInfoPListKeys%>
<%StoryboardInfoPListKey%>
Each of these is expanded with information from your project settings. By deleting the corresponding key, you can replace it with your own settings. It might take some trial and error to determine which one inserts the icons.

ITMS-90892: Missing recommended icon error from Apple App Store

I get this error when submitting my app to the App Store recently.
ITMS-90892: Missing recommended icon - The bundle does not contain an alternate app icon for iPad of exactly '167x167' pixels, in .png format for iOS versions supporting iPad Pro. To support older operating systems, the icon may be required in the bundle outside of an asset catalog. Make sure the Info.plist file includes appropriate entries referencing the file. See
It's related to the alternate icons in the app structure and the names I think but has nothing to do with the assets catalog. In my app a user can choose and icon for the Home Screen.
I have 4 icons to choose and 4 sizes for each icon named e.g. - AA_appIcon#2x, AA_appIcon#2x~iPad, AA_appIcon#3x, AA_appIcon83.5#2x~iPad and it used to work fine, but now I get this error for the one name AA_appIcon83.5#2x~iPad.
It is in the correct size 167x167, so not sure what the problem is.
It just happen in the last few days, didn't happen on my previous submission a month ago.
The naming format must have recently changed or something.
Is anyone able to spot the error?
This is the info.plist
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>AA</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AA_appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<string>No</string>
</dict>
<key>Cake</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>Cake_appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<string>No</string>
</dict>
<key>NA</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>NA_appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<string>No</string>
</dict>
<key>OA</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>OA_appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<string>No</string>
</dict>
</dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>Cake_appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>AA</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AA_appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<string>No</string>
</dict>
<key>Cake</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>Cake_appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<string>No</string>
</dict>
<key>NA</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>NA_appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<string>No</string>
</dict>
<key>OA</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>OA_appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<string>No</string>
</dict>
</dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>Cake_appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
Here's what you need as of late 2021 if you're getting error ITMS-90890 or ITMS-90892, etc.
File Name
size
IconName#2x.png
120x120
IconName#3x.png
180x180
IconName#2x~ipad.png
152x152
IconName#3x~ipad.png
167x167
*Note the lack of capitalization on ~ipad!
Based on #Warpling answer, here is everything you need to setup alternate icon correctly:
1. Create the icon files
First, you'll have to create a folder named AlternateAppIcons inside your main project (where the info.plist file is located).
Now, inside the folder you've created, add the files with the names and sizes that described in the table:
File Name
Size
IconName#2x.png
120x120
IconName#3x.png
180x180
IconName#2x~ipad.png
152x152
IconName#3x~ipad.png
167x167
I'd recommend you to use Icon Set Creator to generate all sizes, then
Make sure that the file names are exactly the same (case sensitive) after the #.
When you change IconName, make sure to change it as well in the info.plist.
2. Configure info.plist
You'll have to add this to the info.plist:
<key>CFBundleIcons</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>IconName</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>IconName</string>
</array>
</dict>
</dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array/>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
<key>CFBundleIcons~ipad</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>IconName</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>IconName</string>
</array>
</dict>
</dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array/>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
3. Change the icon programmatically
All you have to do is to validate that the app supports alternate icons and change it:
guard UIApplication.shared.supportsAlternateIcons else { return }
UIApplication.shared.setAlternateIconName("IconName")
*You may want to create some enum helper like this.
Nevermind
I just renamed the icon from AA_appIcon83.5#2x~iPad.png to AA_appIcon#3x~ipad.png and the error went away and the icon picker still works from within the app.

Why is my iOS app not suggested in the "Open in..." dialog?

I am currently working on a "share" feature in my app. I have custom objects that I am parsing to JSON and I currently have a working implementation to export them as a "___.blueprint" file. So I have created my own custom extension and I have set up everything when it comes to the UTIs and all.
Exporting works well and I have no issue when sending it via email. I can easy tap the mail attachment and select my own app. Importing and handling the data inside the app works as well.
However, When I send the file via AirDrop or messages, iOS doesn't know what to do with it. It doesn't suggest my app as an option to open it with. My info.plist looks like this:
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Blueprint Data</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.ferdinandgoeldner.breadme.blueprint</string>
</array>
</dict>
</array>
...
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Blueprint Data</string>
<key>UTTypeIconFiles</key>
<array/>
<key>UTTypeIdentifier</key>
<string>com.ferdinandgoeldner.breadme.blueprint</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>blueprint</string>
</array>
<key>public.mime-type</key>
<array>
<string>blueprint</string>
</array>
</dict>
</dict>
</array>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Blueprint Data</string>
<key>UTTypeIconFiles</key>
<array/>
<key>UTTypeIdentifier</key>
<string>com.ferdinandgoeldner.breadme.blueprint</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>blueprint</string>
</array>
<key>public.mime-type</key>
<array>
<string>blueprint</string>
</array>
</dict>
</dict>
</array>
I am really lost as to why iOS does allow me to direct the file to my app which can clearly handle the format, but does not think of letting me "open" the file in my application. What am I missing?
I got it to work!
I am not entirely sure what solved it, though.
Here are the steps I performed that made it work.
I chose a more specific UTI type.
Deinstalled all versions of my app.
I created a UTI with a shorter extension (.bmb)
I am pretty sure that .blueprint is a datatype that is not super unique, so I chose an extension that's more unique.
I also carefully ready this page of the Apple Developer Documentation. That also seemed to help me get a better grasp of how to make this stuff happen and what was going on under the hood.
I am still partially unsure of what solved the issue but tweaking several parameters made it happen.
To whoever finds this thread: Good luck. It is possible even though it seems like nothing helps. Keep experimenting and try the steps I described above. ;)

How to create Check option in settings.bundle in ios app

Hi I would like to implement check option like html radio button behavior where only one option is selectable at a time. I would like to implement this in ios app settings (Settings.bundle). I couldn't find a single example anywhere but I do see other apps have this implemented. Please see screenshot below.
Ok PSMultiValueSpecifier was the word that helped me. Thank you Rudedog.
To further add so it can help others. You can use below plist code to achieve. I got it from https://github.com/allanalves/Environment-Manager-iOS/blob/master/Settings.bundle/Root.plist
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Server</string>
<key>FooterText</key>
<string>Don&apos;t forget to choose the "Custom URL" option if you want to specify an URL above.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Environment</string>
<key>Key</key>
<string>environment</string>
<key>DefaultValue</key>
<string>production</string>
<key>Values</key>
<array>
<string>production</string>
<string>homologation</string>
<string>development</string>
<string>custom</string>
</array>
<key>Titles</key>
<array>
<string>Production</string>
<string>Homologation</string>
<string>Development</string>
<string>Custom URL</string>
</array>
</dict>

Resources