[{"data":1,"prerenderedAt":2260},["ShallowReactive",2],{"\u002Fblog\u002Fapple-privacy-manifest-itms-91053-itms-91061-flutter-fix-2026\u002F":3,"\u002Fblog\u002Fapple-privacy-manifest-itms-91053-itms-91061-flutter-fix-2026\u002F-related":711,"\u002Fblog\u002Fapple-privacy-manifest-itms-91053-itms-91061-flutter-fix-2026\u002F-resources":2247},{"id":4,"title":5,"author":6,"body":10,"category":631,"createdAt":632,"description":633,"disclosure":634,"extension":635,"faq":636,"howTo":634,"lastVerified":634,"location":652,"meta":653,"navigation":659,"ogImage":634,"path":660,"primaryKeyword":661,"readingTime":662,"related":663,"seo":667,"sources":668,"stem":701,"tags":702,"takeaways":703,"updatedAt":632,"url":709,"__hash__":710},"blog\u002Fblog\u002Fapple-privacy-manifest-itms-91053-itms-91061-flutter-fix-2026.md","ITMS-91053 and ITMS-91061: Fix Privacy Manifest Emails",{"name":7,"social":8},"Simon Dziak",{"twitter":9},"@SzymonDziak",{"type":11,"value":12,"toc":621},"minimark",[13,21,24,30,35,80,97,101,173,176,185,189,192,264,267,271,335,338,342,345,362,365,368,516,519,522,526,580,584,595,598,601,605,617],[14,15,16,20],"p",{},[17,18,19],"strong",{},"If App Store Connect emailed you ITMS-91053 or ITMS-91061, a PrivacyInfo.xcprivacy file is missing or incomplete, either in your own code or in a third-party SDK."," ITMS-91053 is about required reason APIs used without a declared reason. ITMS-91061 is about a commonly used SDK, such as Flutter itself, that ships without a privacy manifest. In a Flutter app the fix is usually to upgrade Flutter and your plugins first, and to add your own manifest only for native code you wrote.",[14,22,23],{},"The facts below come from Apple's developer documentation, Apple's SDK requirements page, the Flutter team's comments on GitHub and the plugin manifests listed in the sources. I checked each one on October 18, 2026.",[14,25,26,29],{},[17,27,28],{},"Disclosure:"," App369 is my studio. I build and fix Android and iOS apps, mostly in Flutter, and the last section mentions what I sell. Apple doesn't pay me for anything on this page.",[31,32,34],"h2",{"id":33},"what-the-two-errors-mean","What the two errors mean",[36,37,38,54],"table",{},[39,40,41],"thead",{},[42,43,44,48,51],"tr",{},[45,46,47],"th",{},"Code",[45,49,50],{},"What the email says",[45,52,53],{},"What it means",[55,56,57,69],"tbody",{},[42,58,59,63,66],{},[60,61,62],"td",{},"ITMS-91053",[60,64,65],{},"\"Missing API declaration\": your app's code references APIs that require reasons, and names categories such as NSPrivacyAccessedAPICategoryFileTimestamp or NSPrivacyAccessedAPICategoryUserDefaults",[60,67,68],{},"Code in your app or an SDK uses a required reason API, and no privacy manifest gives an approved reason for it",[42,70,71,74,77],{},[60,72,73],{},"ITMS-91061",[60,75,76],{},"\"Missing privacy manifest\": your app includes an SDK that was identified as a commonly used third-party SDK, for example Frameworks\u002FFlutter.framework\u002FFlutter",[60,78,79],{},"That SDK has no privacy manifest file",[14,81,82,83,90,91,96],{},"The wording comes from emails quoted in Flutter issues ",[84,85,89],"a",{"href":86,"rel":87},"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fflutter\u002Fissues\u002F145269",[88],"nofollow","145269"," and ",[84,92,95],{"href":93,"rel":94},"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fflutter\u002Fissues\u002F163455",[88],"163455",". Your email may differ a little, so read the file name it gives. That name is your first clue.",[31,98,100],{"id":99},"the-dates","The dates",[36,102,103,116],{},[39,104,105],{},[42,106,107,110,113],{},[45,108,109],{},"Date",[45,111,112],{},"What Apple or the email said",[45,114,115],{},"Source",[55,117,118,141,156],{},[42,119,120,125,128],{},[60,121,122],{},[17,123,124],{},"May 1, 2024",[60,126,127],{},"Apps that don't describe their use of required reason APIs in their privacy manifest aren't accepted by App Store Connect. Apple's upcoming requirements page says you need approved reasons, including for third-party SDK code, to upload a new or updated app",[60,129,130,135,136],{},[84,131,134],{"href":132,"rel":133},"https:\u002F\u002Fdeveloper.apple.com\u002Fdocumentation\u002Fbundleresources\u002Fdescribing-use-of-required-reason-api",[88],"Apple, required reason API",", ",[84,137,140],{"href":138,"rel":139},"https:\u002F\u002Fdeveloper.apple.com\u002Fnews\u002Fupcoming-requirements\u002F",[88],"Apple, upcoming requirements",[42,142,143,146,149],{},[60,144,145],{},"November 12, 2024",[60,147,148],{},"An ITMS-91061 email posted in a Flutter issue says that from this date a new privacy-impacting SDK must include a manifest",[60,150,151],{},[84,152,155],{"href":153,"rel":154},"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fflutter\u002Fissues\u002F156141",[88],"Flutter issue 156141",[42,157,158,163,166],{},[60,159,160],{},[17,161,162],{},"February 12, 2025",[60,164,165],{},"Apple says apps submitted for review in App Store Connect must contain a valid privacy manifest for a certain number of commonly used third-party SDKs",[60,167,168],{},[84,169,172],{"href":170,"rel":171},"https:\u002F\u002Fdeveloper.apple.com\u002Fdocumentation\u002Fbundleresources\u002Fadding-a-privacy-manifest-to-your-app-or-third-party-sdk",[88],"Apple, adding a privacy manifest",[14,174,175],{},"Apple's SDK page says you must include the manifest for any listed SDK when you submit a new app that includes it, or an update that adds it. It also says signatures are required where the listed SDKs are used as binary dependencies, and that any version of a listed SDK is covered. That page didn't state a date when I read it, so I rely on the other Apple page for February 12, 2025.",[14,177,178,179,184],{},"The list includes Flutter, FirebaseCore, FirebaseAuth, FirebaseMessaging, path_provider, shared_preferences_ios, url_launcher, image_picker_ios, sqflite and many more. Check ",[84,180,183],{"href":181,"rel":182},"https:\u002F\u002Fdeveloper.apple.com\u002Fsupport\u002Fthird-party-SDK-requirements\u002F",[88],"Apple's list"," for the plugins in your app.",[31,186,188],{"id":187},"the-five-required-reason-api-categories","The five required reason API categories",[14,190,191],{},"Apple describes these APIs as ones that could be misused to fingerprint a device or user. Each category goes in the NSPrivacyAccessedAPITypes array with one or more reason codes. These are the categories and the codes I read in Apple's documentation:",[36,193,194,207],{},[39,195,196],{},[42,197,198,201,204],{},[45,199,200],{},"Category key",[45,202,203],{},"What it covers",[45,205,206],{},"Reason codes from Apple",[55,208,209,220,231,242,253],{},[42,210,211,214,217],{},[60,212,213],{},"NSPrivacyAccessedAPICategoryFileTimestamp",[60,215,216],{},"File timestamps and metadata (fstat, lstat, getattrlist and similar)",[60,218,219],{},"DDA9.1 display to the user, C617.1 files inside the app container, 3B52.1 files the user granted access to, 0A2A.1 third-party SDK wrapper",[42,221,222,225,228],{},[60,223,224],{},"NSPrivacyAccessedAPICategorySystemBootTime",[60,226,227],{},"System boot time, such as mach_absolute_time",[60,229,230],{},"35F9.1 measure elapsed time within the app, 8FFB.1 absolute timestamps for events in the app, 3D61.1 optional bug report",[42,232,233,236,239],{},[60,234,235],{},"NSPrivacyAccessedAPICategoryDiskSpace",[60,237,238],{},"Available disk space (statfs, volume capacity keys and similar)",[60,240,241],{},"85F4.1 display to the user, E174.1 check space before writing files, 7D9E.1 optional bug report, B728.1 health research apps",[42,243,244,247,250],{},[60,245,246],{},"NSPrivacyAccessedAPICategoryActiveKeyboards",[60,248,249],{},"List of active keyboards",[60,251,252],{},"3EC4.1 custom keyboard apps, 54BD.1 customize the UI based on the active keyboard",[42,254,255,258,261],{},[60,256,257],{},"NSPrivacyAccessedAPICategoryUserDefaults",[60,259,260],{},"UserDefaults",[60,262,263],{},"CA92.1 data only the app itself can access, 1C8F.1 data shared in the same App Group, C56D.1 third-party SDK wrapper, AC6B.1 managed app configuration set by MDM",[14,265,266],{},"Each reason comes with limits. For example, Apple says information accessed for several of these reasons may not be sent off-device. Read the full text for your code before you pick one.",[31,268,270],{"id":269},"find-which-sdk-or-plugin-triggers-it","Find which SDK or plugin triggers it",[272,273,274,281,297,311,325],"ol",{},[275,276,277,280],"li",{},[17,278,279],{},"Read the email."," It names the file. \"Runner\" means your app target, or a plugin built statically into it. A path like Frameworks\u002FFlutter.framework\u002FFlutter means that framework.",[275,282,283,286,287,291,292,296],{},[17,284,285],{},"Upgrade first."," The Flutter team's guidance in ",[84,288,290],{"href":86,"rel":289},[88],"issue 145269"," (comment dated April 22, 2024) starts with ",[293,294,295],"code",{},"flutter pub upgrade",", because many plugins added their manifests after the rules came out.",[275,298,299,302,303,306,307,310],{},[17,300,301],{},"Look at what your build contains."," The same guidance says to run ",[293,304,305],{},"find build\u002Fios\u002Fiphoneos -name \"*.xcprivacy\""," and look at each ",[293,308,309],{},"PrivacyInfo.xcprivacy"," inside the plugin bundles. Compare their declarations with the categories in your email. If all of them together don't cover the email, at least one dependency has no manifest.",[275,312,313,316,317,320,321,324],{},[17,314,315],{},"Try packaging plugins as frameworks."," The same guidance says adding the ",[293,318,319],{},"use_frameworks!"," line from Flutter's Podfile template can change a warning from \"Runner\" to a named framework. Then you know which plugin to contact. Plugins that set ",[293,322,323],{},"static_framework = true"," override it.",[275,326,327,330,331,334],{},[17,328,329],{},"Search your own code."," In ",[293,332,333],{},"ios\u002FRunner.xcworkspace",", use Find in Workspace for the APIs listed in the flagged category, and check whether the matches are in code you wrote or in a plugin.",[14,336,337],{},"The Flutter team also noted a bug in App Store Connect, at least as of April 2024, that could produce a warning for static frameworks that do declare their reasons. If your plugins all have manifests and the warning still names Runner, that comment is worth reading.",[31,339,341],{"id":340},"add-or-edit-privacyinfoxcprivacy-in-xcode","Add or edit PrivacyInfo.xcprivacy in Xcode",[14,343,344],{},"Do this only for code in your own app, or if an SDK can't be updated. Apple's steps:",[272,346,347,353,356,359],{},[275,348,349,350,352],{},"Open ",[293,351,333],{}," in Xcode.",[275,354,355],{},"Choose File > New File.",[275,357,358],{},"Scroll to the Resource section and select the App Privacy File type, then click Next.",[275,360,361],{},"Check the Runner target in the Targets list and click Create.",[14,363,364],{},"The file is named PrivacyInfo.xcprivacy by default, and that is the required name. Apple says the file must be in the target's resources for Xcode to use it, and that for an iOS app Xcode places it at the root of the app bundle.",[14,366,367],{},"A minimal manifest for an app whose own code reads and writes UserDefaults for itself looks like this. It matches the structure in Flutter's own plugin manifests:",[369,370,375],"pre",{"className":371,"code":372,"language":373,"meta":374,"style":374},"language-xml shiki shiki-themes github-light github-dark","\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003C!DOCTYPE plist PUBLIC \"-\u002F\u002FApple\u002F\u002FDTD PLIST 1.0\u002F\u002FEN\" \"http:\u002F\u002Fwww.apple.com\u002FDTDs\u002FPropertyList-1.0.dtd\">\n\u003Cplist version=\"1.0\">\n\u003Cdict>\n    \u003Ckey>NSPrivacyTracking\u003C\u002Fkey>\n    \u003Cfalse\u002F>\n    \u003Ckey>NSPrivacyTrackingDomains\u003C\u002Fkey>\n    \u003Carray\u002F>\n    \u003Ckey>NSPrivacyCollectedDataTypes\u003C\u002Fkey>\n    \u003Carray\u002F>\n    \u003Ckey>NSPrivacyAccessedAPITypes\u003C\u002Fkey>\n    \u003Carray>\n        \u003Cdict>\n            \u003Ckey>NSPrivacyAccessedAPIType\u003C\u002Fkey>\n            \u003Cstring>NSPrivacyAccessedAPICategoryUserDefaults\u003C\u002Fstring>\n            \u003Ckey>NSPrivacyAccessedAPITypeReasons\u003C\u002Fkey>\n            \u003Carray>\n                \u003Cstring>CA92.1\u003C\u002Fstring>\n            \u003C\u002Farray>\n        \u003C\u002Fdict>\n    \u003C\u002Farray>\n\u003C\u002Fdict>\n\u003C\u002Fplist>\n","xml","",[293,376,377,385,391,397,403,409,415,421,427,433,438,444,450,456,462,468,474,480,486,492,498,504,510],{"__ignoreMap":374},[378,379,382],"span",{"class":380,"line":381},"line",1,[378,383,384],{},"\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",[378,386,388],{"class":380,"line":387},2,[378,389,390],{},"\u003C!DOCTYPE plist PUBLIC \"-\u002F\u002FApple\u002F\u002FDTD PLIST 1.0\u002F\u002FEN\" \"http:\u002F\u002Fwww.apple.com\u002FDTDs\u002FPropertyList-1.0.dtd\">\n",[378,392,394],{"class":380,"line":393},3,[378,395,396],{},"\u003Cplist version=\"1.0\">\n",[378,398,400],{"class":380,"line":399},4,[378,401,402],{},"\u003Cdict>\n",[378,404,406],{"class":380,"line":405},5,[378,407,408],{},"    \u003Ckey>NSPrivacyTracking\u003C\u002Fkey>\n",[378,410,412],{"class":380,"line":411},6,[378,413,414],{},"    \u003Cfalse\u002F>\n",[378,416,418],{"class":380,"line":417},7,[378,419,420],{},"    \u003Ckey>NSPrivacyTrackingDomains\u003C\u002Fkey>\n",[378,422,424],{"class":380,"line":423},8,[378,425,426],{},"    \u003Carray\u002F>\n",[378,428,430],{"class":380,"line":429},9,[378,431,432],{},"    \u003Ckey>NSPrivacyCollectedDataTypes\u003C\u002Fkey>\n",[378,434,436],{"class":380,"line":435},10,[378,437,426],{},[378,439,441],{"class":380,"line":440},11,[378,442,443],{},"    \u003Ckey>NSPrivacyAccessedAPITypes\u003C\u002Fkey>\n",[378,445,447],{"class":380,"line":446},12,[378,448,449],{},"    \u003Carray>\n",[378,451,453],{"class":380,"line":452},13,[378,454,455],{},"        \u003Cdict>\n",[378,457,459],{"class":380,"line":458},14,[378,460,461],{},"            \u003Ckey>NSPrivacyAccessedAPIType\u003C\u002Fkey>\n",[378,463,465],{"class":380,"line":464},15,[378,466,467],{},"            \u003Cstring>NSPrivacyAccessedAPICategoryUserDefaults\u003C\u002Fstring>\n",[378,469,471],{"class":380,"line":470},16,[378,472,473],{},"            \u003Ckey>NSPrivacyAccessedAPITypeReasons\u003C\u002Fkey>\n",[378,475,477],{"class":380,"line":476},17,[378,478,479],{},"            \u003Carray>\n",[378,481,483],{"class":380,"line":482},18,[378,484,485],{},"                \u003Cstring>CA92.1\u003C\u002Fstring>\n",[378,487,489],{"class":380,"line":488},19,[378,490,491],{},"            \u003C\u002Farray>\n",[378,493,495],{"class":380,"line":494},20,[378,496,497],{},"        \u003C\u002Fdict>\n",[378,499,501],{"class":380,"line":500},21,[378,502,503],{},"    \u003C\u002Farray>\n",[378,505,507],{"class":380,"line":506},22,[378,508,509],{},"\u003C\u002Fdict>\n",[378,511,513],{"class":380,"line":512},23,[378,514,515],{},"\u003C\u002Fplist>\n",[14,517,518],{},"Use this as a shape, not as an answer. The Flutter team warns that a manifest is an attestation to Apple that you use data and APIs only in the ways it describes, and that copying arbitrary text could misrepresent your app. Set NSPrivacyTracking to true and list domains only if your app tracks as Apple defines it. Fill NSPrivacyCollectedDataTypes to match what you collect.",[14,520,521],{},"Apple also says App Store Connect rejects submissions with invalid manifests, so use only the keys and values Apple documents.",[31,523,525],{"id":524},"update-flutter-plugins-and-pods","Update Flutter, plugins and pods",[527,528,529,544,553,574],"ul",{},[275,530,531,534,535,90,539,543],{},[17,532,533],{},"Flutter itself."," Flutter's engine source has a PrivacyInfo.xcprivacy for the iOS framework. A maintainer replied to someone on Flutter 2.5.3 that the version is more than three years old and predates framework privacy manifests, so it can't be published as a new app under Apple's rules. If your ITMS-91061 names Flutter, upgrade Flutter. My advice: if the upgrade breaks the iOS build, see ",[84,536,538],{"href":537},"\u002Fblog\u002Fflutter-ios-build-failed-after-upgrade-2026\u002F","the iOS build-failed-after-upgrade guide",[84,540,542],{"href":541},"\u002Fblog\u002Fflutter-uiscene-migration-xcode-27-app-wont-launch-2026\u002F","the UIScene migration guide",".",[275,545,546,549,550,552],{},[17,547,548],{},"Plugins."," Run ",[293,551,295],{},", then check the plugins on Apple's list against their changelogs. The shared_preferences iOS plugin, for example, declares UserDefaults with reason 1C8F.1 in its own manifest.",[275,554,555,558,559,562,563,566,567,90,570,573],{},[17,556,557],{},"Pods."," After a plugin update, run ",[293,560,561],{},"pod install"," from ",[293,564,565],{},"ios\u002F"," and rebuild. My advice: delete ",[293,568,569],{},"Pods",[293,571,572],{},"Podfile.lock"," first if CocoaPods keeps the old versions.",[275,575,576,579],{},[17,577,578],{},"A plugin with no update."," Ask its maintainer to add a manifest, replace the plugin, or as a last resort, declare its usage in your own manifest. Apple's documentation says an SDK can't rely on an app's manifest to report its own use, so this is a stopgap.",[31,581,583],{"id":582},"check-the-archive-and-re-upload","Check the archive and re-upload",[272,585,586,589,592],{},[275,587,588],{},"In Xcode, choose Product > Archive.",[275,590,591],{},"In the Organizer, Control-click the archive and choose Generate Privacy Report.",[275,593,594],{},"Choose where to save it and open the report in Preview.",[14,596,597],{},"Apple says the report aggregates the privacy manifests from your app and the third-party SDKs it links to, and that Xcode won't generate it correctly if you define your own collected data types or purposes instead of Apple's listed values. Then upload again and wait for the processing email.",[14,599,600],{},"If Apple's email points at an invalid manifest inside an SDK, Apple's documentation says to choose Window > Organizer, click Archives, Control-click your archive and choose Show in Finder, then Control-click it in the Finder and choose Show Package Contents. My advice: contact the SDK's developer first rather than editing a signed framework.",[31,602,604],{"id":603},"need-a-hand","Need a hand?",[14,606,607,608,612,613,543],{},"If App Store Connect keeps rejecting your upload with ITMS-91053 or ITMS-91061, the ",[84,609,611],{"href":610},"\u002Ffixed-price\u002Fflutter-firebase-bug-fix\u002F","App Fix Ticket"," covers it in two fixed-price steps. A $450 Diagnosis gives you the root cause with evidence and a fixed repair quote within 3 business days, credited toward the fix. If you go ahead, the $1,200 Fix takes 5 business days and comes as a pull request. Or ",[84,614,616],{"href":615},"\u002Fcontact\u002F","send me a short description",[618,619,620],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":374,"searchDepth":387,"depth":387,"links":622},[623,624,625,626,627,628,629,630],{"id":33,"depth":387,"text":34},{"id":99,"depth":387,"text":100},{"id":187,"depth":387,"text":188},{"id":269,"depth":387,"text":270},{"id":340,"depth":387,"text":341},{"id":524,"depth":387,"text":525},{"id":582,"depth":387,"text":583},{"id":603,"depth":387,"text":604},"AI & Technology","2026-10-18T19:30:00.000Z","App Store Connect emails ITMS-91053 (missing API declaration) and ITMS-91061 (missing privacy manifest) mean your app or an SDK in it lacks a PrivacyInfo.xcprivacy. The dates, the five required reason API categories, how to find the culprit and how to fix a Flutter or native iOS app, from Apple's and Flutter's sources checked October 18, 2026.",null,"md",[637,640,643,646,649],{"question":638,"answer":639},"What does ITMS-91053 Missing API declaration mean?","It means your app's code, or code in an SDK, references an API that Apple calls a required reason API, such as file timestamps or user defaults, and the privacy manifest doesn't give an approved reason for it. Apple says that starting May 1, 2024, apps that don't describe that use aren't accepted by App Store Connect.",{"question":641,"answer":642},"What does ITMS-91061 Missing privacy manifest mean?","It means your app includes a third-party SDK from Apple's list of commonly used SDKs, and that SDK has no privacy manifest. For Flutter apps, the email I found in Flutter's issue tracker names Frameworks\u002FFlutter.framework\u002FFlutter. Upgrading to a Flutter version that ships a manifest is the usual fix.",{"question":644,"answer":645},"Do I need my own PrivacyInfo.xcprivacy in a Flutter app?","Only if your own native code in ios\u002FRunner uses required reason APIs, or an SDK without its own manifest forces you to. The Flutter team's guidance is that if every SDK in your dependency tree has its own manifest, your app's manifest should only need to describe usage directly in your app's code.",{"question":647,"answer":648},"Which reason code do I use for UserDefaults?","Apple lists CA92.1 for reading and writing information that is only accessible to the app itself, and 1C8F.1 for apps, extensions and App Clips in the same App Group. Pick the one that matches what your code does. Don't copy a code just because another project used it.",{"question":650,"answer":651},"How do I check what my archive declares?","In Xcode, choose Product > Archive, then Control-click the archive in the Organizer and choose Generate Privacy Report. Apple says it aggregates the privacy manifests from your app and the third-party SDKs it links to. For the file-level check, Flutter's guidance is to search the built app for .xcprivacy files.","Boynton Beach, FL",{"readingTimeStats":654},{"text":655,"minutes":656,"time":657,"words":658},"8 min read",7.36,441600,1472,true,"\u002Fblog\u002Fapple-privacy-manifest-itms-91053-itms-91061-flutter-fix-2026","itms-91053","7 min",[664,665,666],"flutter-uiscene-migration-xcode-27-app-wont-launch-2026","flutter-ios-build-failed-after-upgrade-2026","google-play-16kb-page-size-flutter-android-2026",{"title":5,"description":633},[669,671,674,677,679,682,684,686,688,691,693,695,698],{"title":670,"url":132},"Apple Developer, Describing use of required reason API",{"title":672,"url":673},"Apple Developer, NSPrivacyAccessedAPIType (categories and reason codes)","https:\u002F\u002Fdeveloper.apple.com\u002Fdocumentation\u002Fbundleresources\u002Fapp-privacy-configuration\u002Fnsprivacyaccessedapitypes\u002Fnsprivacyaccessedapitype",{"title":675,"url":676},"Apple Developer, Privacy manifest files","https:\u002F\u002Fdeveloper.apple.com\u002Fdocumentation\u002Fbundleresources\u002Fprivacy-manifest-files",{"title":678,"url":170},"Apple Developer, Adding a privacy manifest to your app or third-party SDK",{"title":680,"url":681},"Apple Developer, Describing data use in privacy manifests (privacy report)","https:\u002F\u002Fdeveloper.apple.com\u002Fdocumentation\u002Fbundleresources\u002Fdescribing-data-use-in-privacy-manifests",{"title":683,"url":181},"Apple Developer, Third-party SDK requirements",{"title":685,"url":138},"Apple Developer, Upcoming requirements (Approved reasons for APIs, since May 1, 2024)",{"title":687,"url":86},"Flutter on GitHub, issue 145269 (ITMS-91053 email text and the Flutter team's guidance)",{"title":689,"url":690},"Flutter on GitHub, issue 131940 (privacy manifests in packages, and the warning about copying manifests)","https:\u002F\u002Fgithub.com\u002Fflutter\u002Fflutter\u002Fissues\u002F131940",{"title":692,"url":153},"Flutter on GitHub, issue 156141 (ITMS-91061 email text, November 12, 2024)",{"title":694,"url":93},"Flutter on GitHub, issue 163455 (ITMS-91061 email text, February 12, 2025)",{"title":696,"url":697},"Flutter on GitHub, engine PrivacyInfo.xcprivacy for the iOS framework","https:\u002F\u002Fraw.githubusercontent.com\u002Fflutter\u002Fflutter\u002Fmaster\u002Fengine\u002Fsrc\u002Fflutter\u002Fshell\u002Fplatform\u002Fdarwin\u002Fios\u002Fframework\u002FPrivacyInfo.xcprivacy",{"title":699,"url":700},"flutter\u002Fpackages on GitHub, shared_preferences_foundation PrivacyInfo.xcprivacy","https:\u002F\u002Fraw.githubusercontent.com\u002Fflutter\u002Fpackages\u002Fmain\u002Fpackages\u002Fshared_preferences\u002Fshared_preferences_foundation\u002Fdarwin\u002Fshared_preferences_foundation\u002FSources\u002Fshared_preferences_foundation\u002FResources\u002FPrivacyInfo.xcprivacy","blog\u002Fapple-privacy-manifest-itms-91053-itms-91061-flutter-fix-2026","itms-91053, itms-91061, itms-91053 missing api declaration, itms-91061 missing privacy manifest, privacyinfo.xcprivacy flutter, privacy manifest flutter, required reason api, nsprivacyaccessedapitypes, ca92.1 user defaults, app store connect privacy manifest email",[704,705,706,707,708],"ITMS-91053 means code in your app or an SDK uses a required reason API without a reason in its privacy manifest. Apple says that since May 1, 2024, apps that don't describe that use aren't accepted by App Store Connect.","ITMS-91061 means a commonly used third-party SDK in your app, such as Flutter, shipped without a privacy manifest. Apple says that starting February 12, 2025, apps submitted for review must contain a valid manifest for a certain number of those SDKs.","Apple's required reason APIs fall into five categories: file timestamp, system boot time, disk space, active keyboards and user defaults. Each needs one or more approved reason codes.","Most Flutter fixes start with upgrading Flutter and running flutter pub upgrade, because many plugins added their manifests after the rules were announced. You only add your own PrivacyInfo.xcprivacy for code you wrote.","Never paste a privacy manifest from the internet. The Flutter team says a manifest is an attestation to Apple that you use data and APIs only in the ways it describes.","https:\u002F\u002Fapp369.com\u002Fblog\u002Fapple-privacy-manifest-itms-91053-itms-91061-flutter-fix-2026\u002F","k5SC1R0BWFgag3CQKKDpo2CjfNhlGmmpR7NilLiCJLc",[712,1328,1849],{"id":713,"title":714,"author":715,"body":717,"category":631,"createdAt":1274,"description":1275,"disclosure":634,"extension":635,"faq":1276,"howTo":634,"lastVerified":634,"location":652,"meta":1292,"navigation":659,"ogImage":634,"path":1298,"primaryKeyword":1299,"readingTime":1300,"related":1301,"seo":1304,"sources":1305,"stem":1318,"tags":1319,"takeaways":1320,"updatedAt":1274,"url":1326,"__hash__":1327},"blog\u002Fblog\u002Fflutter-uiscene-migration-xcode-27-app-wont-launch-2026.md","Flutter UIScene Migration: Fix Launch Crashes on Xcode 27",{"name":7,"social":716},{"twitter":9},{"type":11,"value":718,"toc":1262},[719,737,740,745,749,856,859,862,866,884,887,891,898,903,921,987,1011,1015,1032,1046,1050,1061,1167,1185,1189,1205,1209,1212,1246,1248,1260],[14,720,721,724,725,728,729,731,732,90,734,543],{},[17,722,723],{},"If your Flutter iOS app fails to launch after you build it with Xcode 27, the first thing to check is whether it has adopted Apple's UIScene lifecycle."," Flutter's docs say Flutter apps built with Xcode 27 (the iOS 27 SDK) that haven't adopted UIScene fail to launch on startup. From Flutter 3.41, the Flutter CLI migrates apps with an unmodified ",[293,726,727],{},"AppDelegate"," automatically. Apps with a custom ",[293,730,727],{},", or on an older Flutter, need a few manual changes to ",[293,733,727],{},[293,735,736],{},"Info.plist",[14,738,739],{},"The facts below come from Flutter's UIScene page, Apple's technote TN3187 and Apple's release and requirements pages, as listed in the sources. I checked each one on October 18, 2026.",[14,741,742,744],{},[17,743,28],{}," App369 is my studio. I build and fix Flutter apps on iOS and Android, and the last section mentions what I sell. Google and Apple don't pay me for anything on this page.",[31,746,748],{"id":747},"what-changed-and-when","What changed, and when",[36,750,751,762],{},[39,752,753],{},[42,754,755,757,760],{},[45,756,109],{},[45,758,759],{},"What happened",[45,761,115],{},[55,763,764,784,804,820,834],{},[42,765,766,769,772],{},[60,767,768],{},"June 2025 (WWDC25)",[60,770,771],{},"Apple announces that in the release after iOS 26, UIKit apps built with the latest SDK must use the UIScene life cycle, or they won't launch",[60,773,774,135,779],{},[84,775,778],{"href":776,"rel":777},"https:\u002F\u002Fdocs.flutter.dev\u002Frelease\u002Fbreaking-changes\u002Fuiscenedelegate",[88],"Flutter docs",[84,780,783],{"href":781,"rel":782},"https:\u002F\u002Fdeveloper.apple.com\u002Fdocumentation\u002Ftechnotes\u002Ftn3187-migrating-to-the-uikit-scene-based-life-cycle",[88],"Apple TN3187",[42,785,786,789,792],{},[60,787,788],{},"November 12, 2025",[60,790,791],{},"Flutter 3.38 adds UIScene support, with an experimental automatic migration",[60,793,794,135,799],{},[84,795,798],{"href":796,"rel":797},"https:\u002F\u002Fflutter.dev\u002Fblog\u002Fwhats-new-in-flutter-3-38",[88],"Flutter 3.38 post",[84,800,803],{"href":801,"rel":802},"https:\u002F\u002Fstorage.googleapis.com\u002Fflutter_infra_release\u002Freleases\u002Freleases_macos.json",[88],"release archive",[42,805,806,809,812],{},[60,807,808],{},"February 11, 2026",[60,810,811],{},"Flutter 3.41: UIScene support is the default, and eligible apps are migrated automatically",[60,813,814,135,817],{},[84,815,778],{"href":776,"rel":816},[88],[84,818,803],{"href":801,"rel":819},[88],[42,821,822,825,828],{},[60,823,824],{},"April 28, 2026",[60,826,827],{},"App Store Connect uploads must be built with Xcode 26 or later",[60,829,830],{},[84,831,833],{"href":138,"rel":832},[88],"Apple upcoming requirements",[42,835,836,841,846],{},[60,837,838],{},[17,839,840],{},"September 14, 2026",[60,842,843],{},[17,844,845],{},"Xcode 27 released. Flutter apps built with it that haven't adopted UIScene fail to launch",[60,847,848,135,853],{},[84,849,852],{"href":850,"rel":851},"https:\u002F\u002Fdeveloper.apple.com\u002Fnews\u002Freleases\u002F",[88],"Apple releases",[84,854,778],{"href":776,"rel":855},[88],[14,857,858],{},"On October 18, 2026, Apple's upcoming requirements page still listed Xcode 26 as the minimum for uploads and gave no date for Xcode 27. In my reading, you can still ship with Xcode 26 for now, but the app won't launch the first time you build it with Xcode 27 unless it has migrated.",[14,860,861],{},"Apple's technote says the requirement is to adopt the scene life cycle. Supporting multiple scenes is encouraged but not required.",[31,863,865],{"id":864},"step-1-let-flutter-migrate-it","Step 1: let Flutter migrate it",[14,867,868,869,871,872,875,876,879,880,883],{},"If the app is on Flutter 3.41 or later and its ",[293,870,727],{}," hasn't been customized, Flutter's docs say the CLI migrates it when you run ",[293,873,874],{},"flutter run"," or ",[293,877,878],{},"flutter build ios",". On success it prints ",[293,881,882],{},"Finished migration to UIScene lifecycle",". If it can't, it warns you and gives manual steps.",[14,885,886],{},"My advice: if the app is on an older Flutter, upgrade to the current stable first and see whether the automatic migration covers it, before changing native code by hand.",[31,888,890],{"id":889},"step-2-migrate-a-custom-appdelegate-by-hand","Step 2: migrate a custom AppDelegate by hand",[14,892,893,894,543],{},"These steps follow Flutter's ",[84,895,897],{"href":776,"rel":896},[88],"UIScene page",[899,900,902],"h3",{"id":901},"register-plugins-in-the-new-callback","Register plugins in the new callback",[14,904,905,906,909,910,912,913,916,917,920],{},"Plugins used to be registered in ",[293,907,908],{},"application:didFinishLaunchingWithOptions:",". Now the ",[293,911,727],{}," conforms to ",[293,914,915],{},"FlutterImplicitEngineDelegate"," and registers them in ",[293,918,919],{},"didInitializeImplicitFlutterEngine",":",[369,922,926],{"className":923,"code":924,"language":925,"meta":374,"style":374},"language-swift shiki shiki-themes github-light github-dark","@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {\n  override func application(\n    _ application: UIApplication,\n    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n  ) -> Bool {\n    return super.application(application, didFinishLaunchingWithOptions: launchOptions)\n  }\n\n  func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {\n    GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)\n  }\n}\n","swift",[293,927,928,933,938,943,948,953,958,963,968,973,978,982],{"__ignoreMap":374},[378,929,930],{"class":380,"line":381},[378,931,932],{},"@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {\n",[378,934,935],{"class":380,"line":387},[378,936,937],{},"  override func application(\n",[378,939,940],{"class":380,"line":393},[378,941,942],{},"    _ application: UIApplication,\n",[378,944,945],{"class":380,"line":399},[378,946,947],{},"    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n",[378,949,950],{"class":380,"line":405},[378,951,952],{},"  ) -> Bool {\n",[378,954,955],{"class":380,"line":411},[378,956,957],{},"    return super.application(application, didFinishLaunchingWithOptions: launchOptions)\n",[378,959,960],{"class":380,"line":417},[378,961,962],{},"  }\n",[378,964,965],{"class":380,"line":423},[378,966,967],{"emptyLinePlaceholder":659},"\n",[378,969,970],{"class":380,"line":429},[378,971,972],{},"  func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {\n",[378,974,975],{"class":380,"line":435},[378,976,977],{},"    GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)\n",[378,979,980],{"class":380,"line":440},[378,981,962],{},[378,983,984],{"class":380,"line":446},[378,985,986],{},"}\n",[14,988,989,990,993,994,996,997,1000,1001,1004,1005,1007,1008,1010],{},"If you created method channels or platform views in ",[293,991,992],{},"didFinishLaunchingWithOptions",", move them into ",[293,995,919],{}," too, using ",[293,998,999],{},"engineBridge.applicationRegistrar.messenger()"," as the messenger. Flutter's docs warn that accessing the ",[293,1002,1003],{},"FlutterViewController"," in ",[293,1006,992],{}," might crash your app, and say to use the ",[293,1009,915],{}," protocol instead.",[899,1012,1014],{"id":1013},"move-ui-lifecycle-code-to-a-scene-delegate","Move UI lifecycle code to a scene delegate",[14,1016,1017,1018,1020,1021,1024,1025,1028,1029,543],{},"After the migration, UIKit no longer calls the ",[293,1019,727],{}," methods tied to UI state, such as ",[293,1022,1023],{},"applicationDidBecomeActive",". If you used them, create a scene delegate and move that code to scene events. Flutter's docs say your own scene delegate must subclass ",[293,1026,1027],{},"FlutterSceneDelegate"," or conform to ",[293,1030,1031],{},"FlutterSceneLifeCycleProvider",[14,1033,1034,1035,1037,1038,1041,1042,1045],{},"Flutter's page adds, in its plugin section, that after the migration the launch options passed to ",[293,1036,992],{}," are ",[293,1039,1040],{},"nil",", and that logic relying on them moves to ",[293,1043,1044],{},"scene:willConnectToSession:options:",". My advice: look first at code that handles a notification or a URL the app was opened with.",[899,1047,1049],{"id":1048},"add-the-scene-manifest-to-infoplist","Add the scene manifest to Info.plist",[14,1051,1052,1053,1056,1057,1060],{},"Add this inside the top-level ",[293,1054,1055],{},"\u003Cdict>"," of ",[293,1058,1059],{},"ios\u002FRunner\u002FInfo.plist",", as shown on Flutter's page:",[369,1062,1064],{"className":371,"code":1063,"language":373,"meta":374,"style":374},"\u003Ckey>UIApplicationSceneManifest\u003C\u002Fkey>\n\u003Cdict>\n  \u003Ckey>UIApplicationSupportsMultipleScenes\u003C\u002Fkey>\n  \u003Cfalse\u002F>\n  \u003Ckey>UISceneConfigurations\u003C\u002Fkey>\n  \u003Cdict>\n    \u003Ckey>UIWindowSceneSessionRoleApplication\u003C\u002Fkey>\n    \u003Carray>\n      \u003Cdict>\n        \u003Ckey>UISceneClassName\u003C\u002Fkey>\n        \u003Cstring>UIWindowScene\u003C\u002Fstring>\n        \u003Ckey>UISceneDelegateClassName\u003C\u002Fkey>\n        \u003Cstring>FlutterSceneDelegate\u003C\u002Fstring>\n        \u003Ckey>UISceneConfigurationName\u003C\u002Fkey>\n        \u003Cstring>flutter\u003C\u002Fstring>\n        \u003Ckey>UISceneStoryboardFile\u003C\u002Fkey>\n        \u003Cstring>Main\u003C\u002Fstring>\n      \u003C\u002Fdict>\n    \u003C\u002Farray>\n  \u003C\u002Fdict>\n\u003C\u002Fdict>\n",[293,1065,1066,1071,1075,1080,1085,1090,1095,1100,1104,1109,1114,1119,1124,1129,1134,1139,1144,1149,1154,1158,1163],{"__ignoreMap":374},[378,1067,1068],{"class":380,"line":381},[378,1069,1070],{},"\u003Ckey>UIApplicationSceneManifest\u003C\u002Fkey>\n",[378,1072,1073],{"class":380,"line":387},[378,1074,402],{},[378,1076,1077],{"class":380,"line":393},[378,1078,1079],{},"  \u003Ckey>UIApplicationSupportsMultipleScenes\u003C\u002Fkey>\n",[378,1081,1082],{"class":380,"line":399},[378,1083,1084],{},"  \u003Cfalse\u002F>\n",[378,1086,1087],{"class":380,"line":405},[378,1088,1089],{},"  \u003Ckey>UISceneConfigurations\u003C\u002Fkey>\n",[378,1091,1092],{"class":380,"line":411},[378,1093,1094],{},"  \u003Cdict>\n",[378,1096,1097],{"class":380,"line":417},[378,1098,1099],{},"    \u003Ckey>UIWindowSceneSessionRoleApplication\u003C\u002Fkey>\n",[378,1101,1102],{"class":380,"line":423},[378,1103,449],{},[378,1105,1106],{"class":380,"line":429},[378,1107,1108],{},"      \u003Cdict>\n",[378,1110,1111],{"class":380,"line":435},[378,1112,1113],{},"        \u003Ckey>UISceneClassName\u003C\u002Fkey>\n",[378,1115,1116],{"class":380,"line":440},[378,1117,1118],{},"        \u003Cstring>UIWindowScene\u003C\u002Fstring>\n",[378,1120,1121],{"class":380,"line":446},[378,1122,1123],{},"        \u003Ckey>UISceneDelegateClassName\u003C\u002Fkey>\n",[378,1125,1126],{"class":380,"line":452},[378,1127,1128],{},"        \u003Cstring>FlutterSceneDelegate\u003C\u002Fstring>\n",[378,1130,1131],{"class":380,"line":458},[378,1132,1133],{},"        \u003Ckey>UISceneConfigurationName\u003C\u002Fkey>\n",[378,1135,1136],{"class":380,"line":464},[378,1137,1138],{},"        \u003Cstring>flutter\u003C\u002Fstring>\n",[378,1140,1141],{"class":380,"line":470},[378,1142,1143],{},"        \u003Ckey>UISceneStoryboardFile\u003C\u002Fkey>\n",[378,1145,1146],{"class":380,"line":476},[378,1147,1148],{},"        \u003Cstring>Main\u003C\u002Fstring>\n",[378,1150,1151],{"class":380,"line":482},[378,1152,1153],{},"      \u003C\u002Fdict>\n",[378,1155,1156],{"class":380,"line":488},[378,1157,503],{},[378,1159,1160],{"class":380,"line":494},[378,1161,1162],{},"  \u003C\u002Fdict>\n",[378,1164,1165],{"class":380,"line":500},[378,1166,509],{},[14,1168,1169,1170,1173,1174,1176,1177,1180,1181,1184],{},"If you made your own scene delegate subclass, Flutter's page says to put its name in ",[293,1171,1172],{},"UISceneDelegateClassName"," instead of ",[293,1175,1027],{},": ",[293,1178,1179],{},"$(PRODUCT_MODULE_NAME).SceneDelegate"," for Swift projects, ",[293,1182,1183],{},"SceneDelegate"," for Objective-C.",[31,1186,1188],{"id":1187},"plugins-and-add-to-app","Plugins and add-to-app",[527,1190,1191,1197],{},[275,1192,1193,1196],{},[17,1194,1195],{},"Plugins:"," Flutter's page has a separate guide for plugins that use iOS application lifecycle events. My advice: update every plugin to its latest version, then test anything that reacts to the app opening, resuming or receiving a link, such as push notifications, deep links, sign-in and payments.",[275,1198,1199,1202,1203,543],{},[17,1200,1201],{},"Add-to-app:"," if Flutter is embedded in a native iOS app, Flutter's page has its own section, including what to do if you can't subclass ",[293,1204,1027],{},[31,1206,1208],{"id":1207},"what-to-test","What to test",[14,1210,1211],{},"This section is my advice, not Flutter's or Apple's.",[272,1213,1214,1220,1229,1240],{},[275,1215,1216,1219],{},[17,1217,1218],{},"Build with Xcode 27 and launch on a device."," If it launches, open each screen once.",[275,1221,1222,1225,1226,1228],{},[17,1223,1224],{},"Cold start from a push notification and from a deep link."," Launch options are ",[293,1227,1040],{}," after the migration, so these are the paths most likely to break.",[275,1230,1231,1234,1235,875,1237,543],{},[17,1232,1233],{},"Background and foreground the app."," Check anything that used to run in ",[293,1236,1023],{},[293,1238,1239],{},"applicationWillResignActive",[275,1241,1242,1245],{},[17,1243,1244],{},"Ship through TestFlight first."," Check the same paths on a build installed the way users get it.",[31,1247,604],{"id":603},[14,1249,1250,1251,1253,1254,1257,1258,543],{},"If a Flutter iOS app won't launch after building with Xcode 27, or broke after the UIScene migration, the ",[84,1252,611],{"href":610}," covers it in two fixed-price steps. A $450 Diagnosis gives you the root cause with evidence and a fixed repair quote within 3 business days, credited toward the fix. If you go ahead, the $1,200 Fix takes 5 business days and comes as a pull request. If the iOS build itself fails, see ",[84,1255,1256],{"href":537},"Flutter iOS build failed after an upgrade",", or ",[84,1259,616],{"href":615},[618,1261,620],{},{"title":374,"searchDepth":387,"depth":387,"links":1263},[1264,1265,1266,1271,1272,1273],{"id":747,"depth":387,"text":748},{"id":864,"depth":387,"text":865},{"id":889,"depth":387,"text":890,"children":1267},[1268,1269,1270],{"id":901,"depth":393,"text":902},{"id":1013,"depth":393,"text":1014},{"id":1048,"depth":393,"text":1049},{"id":1187,"depth":387,"text":1188},{"id":1207,"depth":387,"text":1208},{"id":603,"depth":387,"text":604},"2026-10-18T23:55:00.000Z","Xcode 27 shipped on September 14, 2026, and Flutter's docs say Flutter iOS apps built with it that haven't adopted the UIScene lifecycle fail to launch. Which Flutter versions migrate automatically, the manual AppDelegate and Info.plist changes, and what plugins need, from Flutter's and Apple's docs checked October 18, 2026.",[1277,1280,1283,1286,1289],{"question":1278,"answer":1279},"Why does my Flutter app crash on launch when built with Xcode 27?","Flutter's UIScene page says Flutter apps built with Xcode 27 (iOS 27 SDK) that haven't adopted the UIScene lifecycle fail to launch on startup. Apple announced at WWDC25 that UIKit apps built with the SDK after iOS 26 must use the UIScene life cycle. The fix is the UIScene migration.",{"question":1281,"answer":1282},"Does Flutter migrate to UIScene automatically?","From Flutter 3.41, yes, if your AppDelegate is unmodified. Run flutter run or flutter build ios, and Flutter's docs say the CLI prints \"Finished migration to UIScene lifecycle\" when it succeeds. With a custom AppDelegate, or on a Flutter version before 3.41, you migrate by hand.",{"question":1284,"answer":1285},"How do I migrate a Flutter app to UIScene by hand?","Per Flutter's docs: make AppDelegate conform to FlutterImplicitEngineDelegate, move GeneratedPluginRegistrant registration and any method channels into didInitializeImplicitFlutterEngine, move UI lifecycle logic to a scene delegate, and add a UIApplicationSceneManifest to Info.plist with FlutterSceneDelegate as the delegate class.",{"question":1287,"answer":1288},"Do I have to upload with Xcode 27 now?","Not yet, as of October 18, 2026. Apple's upcoming requirements page lists Xcode 26 with an iOS 26 SDK as the minimum for App Store Connect uploads since April 28, 2026, and doesn't name a date for Xcode 27. The crash happens as soon as you build with Xcode 27, so the migration is needed before you switch.",{"question":1290,"answer":1291},"Can I turn UIScene off temporarily?","Flutter's docs say you can, by putting an underscore in front of Application Scene Manifest in Info.plist, and that the pubspec setting enable-uiscene-migration: false hides the CLI warning. In my view, both only make sense while you build with Xcode 26, because an app built with Xcode 27 without UIScene won't launch.",{"readingTimeStats":1293},{"text":1294,"minutes":1295,"time":1296,"words":1297},"5 min read",4.405,264300,881,"\u002Fblog\u002Fflutter-uiscene-migration-xcode-27-app-wont-launch-2026","flutter uiscene migration","8 min",[665,1302,1303],"google-play-target-api-36-android-16-requirement-2026","flutter-deleted-android-v1-embedding-build-failed-2026",{"title":714,"description":1275},[1306,1308,1310,1312,1314,1316],{"title":1307,"url":776},"Flutter docs, UIScene adoption (last updated September 14, 2026)",{"title":1309,"url":781},"Apple Developer, TN3187: Migrating to the UIKit scene-based life cycle",{"title":1311,"url":138},"Apple Developer, Upcoming requirements",{"title":1313,"url":850},"Apple Developer, Releases",{"title":1315,"url":796},"Flutter blog, What's new in Flutter 3.38",{"title":1317,"url":801},"Flutter release archive (macOS)","blog\u002Fflutter-uiscene-migration-xcode-27-app-wont-launch-2026","flutter uiscene migration, flutter app crashes on launch xcode 27, uiscene lifecycle required ios 27, FlutterSceneDelegate, FlutterImplicitEngineDelegate, didInitializeImplicitFlutterEngine, UIApplicationSceneManifest flutter, enable-uiscene-migration, TN3187 flutter",[1321,1322,1323,1324,1325],"Apple said at WWDC25 that in the release after iOS 26, UIKit apps built with the latest SDK must use the UIScene life cycle, or they won't launch. Xcode 27, with the iOS 27 SDK, was released on September 14, 2026.","Flutter's docs say Flutter iOS apps built with Xcode 27 that haven't adopted UIScene fail to launch on startup.","Flutter 3.38 added UIScene support. From Flutter 3.41 (February 11, 2026), it is the default, and the Flutter CLI migrates apps with an unmodified AppDelegate automatically when you build or run.","A custom AppDelegate needs manual changes: register plugins in didInitializeImplicitFlutterEngine instead of didFinishLaunchingWithOptions, and add an Application Scene Manifest that uses FlutterSceneDelegate to Info.plist.","Plugins that rely on app lifecycle events such as applicationDidBecomeActive have to move to scene events, because UIKit stops calling the UI-related AppDelegate methods after the migration.","https:\u002F\u002Fapp369.com\u002Fblog\u002Fflutter-uiscene-migration-xcode-27-app-wont-launch-2026\u002F","phTA1gotzUIgpRjpnHOwLVRzoK6pYZ4Ej6vy9OhVEKM",{"id":1329,"title":1330,"author":1331,"body":1333,"category":631,"createdAt":1835,"description":1836,"disclosure":634,"extension":635,"faq":634,"howTo":634,"lastVerified":634,"location":652,"meta":1837,"navigation":659,"ogImage":634,"path":1843,"primaryKeyword":634,"readingTime":662,"related":634,"seo":1844,"sources":634,"stem":1845,"tags":1846,"takeaways":634,"updatedAt":1835,"url":1847,"__hash__":1848},"blog\u002Fblog\u002Fflutter-ios-build-failed-after-upgrade-2026.md","Flutter iOS Build Failed After an Upgrade? Fix CocoaPods and Xcode Errors (2026)",{"name":7,"social":1332},{"twitter":9},{"type":11,"value":1334,"toc":1818},[1335,1341,1352,1356,1359,1392,1395,1451,1455,1485,1489,1498,1524,1528,1535,1578,1655,1671,1675,1687,1720,1724,1733,1736,1740,1743,1747,1753,1757,1761,1775,1779,1791,1795,1798,1802,1808,1812,1815],[14,1336,1337,1340],{},[17,1338,1339],{},"When a Flutter iOS build breaks right after an upgrade, the cause is almost always one of four things: a stale CocoaPods lock, a deployment target that is too low, FlutterFire plugins on mismatched versions, or an Xcode that no longer matches the SDKs you depend on."," The error Xcode shows first is rarely the real one. This guide is the order to work in, from reading the actual failure to the fixes that cover most upgrade breakages.",[14,1342,1343,1344,1347,1348,543],{},"It is the same approach Simon uses on Workspace369, his production Flutter and Firebase SaaS, and it is the iOS build part of App369's ",[84,1345,1346],{"href":610},"fixed-price Flutter & Firebase Fix Ticket",". For the wider method, see ",[84,1349,1351],{"href":1350},"\u002Fblog\u002Fhow-to-debug-a-flutter-firebase-bug-2026\u002F","how to debug a Flutter and Firebase bug",[31,1353,1355],{"id":1354},"step-1-read-the-real-error","Step 1: Read the real error",[14,1357,1358],{},"Don't start by deleting folders. First get the full output.",[272,1360,1361,1368,1382],{},[275,1362,1363,1364,1367],{},"Run ",[293,1365,1366],{},"flutter doctor -v"," and fix anything it flags under Xcode or CocoaPods.",[275,1369,1363,1370,1373,1374,1377,1378,1381],{},[293,1371,1372],{},"flutter build ios -v"," (or ",[293,1375,1376],{},"flutter run -v",") and read from the first line that says ",[293,1379,1380],{},"error:",", not the last line. The final \"Xcode build failed\" message is a summary.",[275,1383,1384,1385,1387,1388,1391],{},"If the failure happens in Xcode itself, open ",[293,1386,333],{}," (never ",[293,1389,1390],{},"Runner.xcodeproj",") and use the Report navigator to open the build log. Filter for errors and read the first one.",[14,1393,1394],{},"Where the error appears tells you which step failed:",[36,1396,1397,1407],{},[39,1398,1399],{},[42,1400,1401,1404],{},[45,1402,1403],{},"Where it fails",[45,1405,1406],{},"Likely area",[55,1408,1409,1419,1427,1435,1443],{},[42,1410,1411,1416],{},[60,1412,1413,1415],{},[293,1414,561],{}," output, before compiling",[60,1417,1418],{},"CocoaPods resolution, Podfile, specs",[42,1420,1421,1424],{},[60,1422,1423],{},"\"Compiling for iOS X, but module requires iOS Y\"",[60,1425,1426],{},"Deployment target too low",[42,1428,1429,1432],{},[60,1430,1431],{},"Swift or Objective-C compile errors inside a plugin",[60,1433,1434],{},"Plugin and Xcode or SDK version mismatch",[42,1436,1437,1440],{},[60,1438,1439],{},"Linking or \"framework not found\"",[60,1441,1442],{},"Stale Pods or build cache",[42,1444,1445,1448],{},[60,1446,1447],{},"Code signing messages",[60,1449,1450],{},"Signing and provisioning, covered at the end",[31,1452,1454],{"id":1453},"step-2-check-your-xcode-and-cocoapods-versions","Step 2: Check your Xcode and CocoaPods versions",[14,1456,1457,1458,1463,1464,90,1467,1470,1471,1476,1477,1480,1481,1484],{},"Upgrades often fail because the Firebase SDK moved its minimum requirements. The ",[84,1459,1462],{"href":1460,"rel":1461},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fios\u002Finstallation-methods",[88],"Firebase Apple platforms installation docs"," list the current Xcode requirement and say the CocoaPods distribution needs CocoaPods 1.12.0 or higher. Check yours with ",[293,1465,1466],{},"pod --version",[293,1468,1469],{},"xcodebuild -version",", and update if either is below what your plugins need. Flutter's own ",[84,1472,1475],{"href":1473,"rel":1474},"https:\u002F\u002Fdocs.flutter.dev\u002Fplatform-integration\u002Fios\u002Fsetup",[88],"iOS setup page"," covers pointing the command-line tools at the right Xcode (",[293,1478,1479],{},"xcode-select",") and accepting licenses (",[293,1482,1483],{},"sudo xcodebuild -license","); a second Xcode installed on the machine is a common reason a build uses the wrong toolchain.",[31,1486,1488],{"id":1487},"step-3-fix-the-ios-deployment-target","Step 3: Fix the iOS deployment target",[14,1490,1491,1492,1497],{},"A plugin upgrade can raise the minimum iOS version. The ",[84,1493,1496],{"href":1494,"rel":1495},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fflutter\u002Fsetup",[88],"Firebase Flutter setup page"," lists iOS 15 or later as the Apple requirement for the FlutterFire plugins. Check three places and make them agree:",[527,1499,1500,1510,1513],{},[275,1501,1502,1505,1506,1509],{},[293,1503,1504],{},"ios\u002FPodfile",": the line ",[293,1507,1508],{},"platform :ios, '15.0'"," (use the minimum your plugins ask for; if the line is commented out, uncomment it).",[275,1511,1512],{},"Xcode: Runner target, General tab, \"Minimum Deployments\".",[275,1514,1515,1516,1519,1520,1523],{},"The ",[293,1517,1518],{},"post_install"," block in the Podfile, if you have one that sets ",[293,1521,1522],{},"IPHONEOS_DEPLOYMENT_TARGET"," on every pod. A value there that is lower than a pod's own minimum produces the \"module requires iOS Y\" error.",[31,1525,1527],{"id":1526},"step-4-refresh-cocoapods-then-clean-it-out","Step 4: Refresh CocoaPods, then clean it out",[14,1529,1530,1531,1534],{},"Work from least to most destructive. Run these inside the ",[293,1532,1533],{},"ios"," folder.",[272,1536,1537,1545,1572],{},[275,1538,1539,1544],{},[17,1540,1541],{},[293,1542,1543],{},"pod install --repo-update"," refreshes the local spec repository and then installs. It is the right first move after upgrading a plugin, because a stale local spec list can't find the new version.",[275,1546,1547,1552,1553,1555,1556,1561,1562,1564,1565,1567,1568,1571],{},[17,1548,1549],{},[293,1550,1551],{},"pod update PODNAME"," if one pod needs to move to a newer version than ",[293,1554,572],{}," allows. As the ",[84,1557,1560],{"href":1558,"rel":1559},"https:\u002F\u002Fguides.cocoapods.org\u002Fusing\u002Fpod-install-vs-update.html",[88],"CocoaPods guide"," explains, ",[293,1563,561],{}," respects the versions in ",[293,1566,572],{},", while ",[293,1569,1570],{},"pod update"," ignores the lock and fetches the newest version your constraints allow.",[275,1573,1574,1577],{},[17,1575,1576],{},"A clean reinstall."," If it is still broken, remove the generated pieces and rebuild them:",[369,1579,1583],{"className":1580,"code":1581,"language":1582,"meta":374,"style":374},"language-bash shiki shiki-themes github-light github-dark","cd ios\nrm -rf Pods Podfile.lock\ncd ..\nflutter clean\nflutter pub get\ncd ios && pod install --repo-update\n","bash",[293,1584,1585,1595,1610,1617,1625,1635],{"__ignoreMap":374},[378,1586,1587,1591],{"class":380,"line":381},[378,1588,1590],{"class":1589},"sj4cs","cd",[378,1592,1594],{"class":1593},"sZZnC"," ios\n",[378,1596,1597,1601,1604,1607],{"class":380,"line":387},[378,1598,1600],{"class":1599},"sScJk","rm",[378,1602,1603],{"class":1589}," -rf",[378,1605,1606],{"class":1593}," Pods",[378,1608,1609],{"class":1593}," Podfile.lock\n",[378,1611,1612,1614],{"class":380,"line":393},[378,1613,1590],{"class":1589},[378,1615,1616],{"class":1593}," ..\n",[378,1618,1619,1622],{"class":380,"line":399},[378,1620,1621],{"class":1599},"flutter",[378,1623,1624],{"class":1593}," clean\n",[378,1626,1627,1629,1632],{"class":380,"line":405},[378,1628,1621],{"class":1599},[378,1630,1631],{"class":1593}," pub",[378,1633,1634],{"class":1593}," get\n",[378,1636,1637,1639,1642,1646,1649,1652],{"class":380,"line":411},[378,1638,1590],{"class":1589},[378,1640,1641],{"class":1593}," ios",[378,1643,1645],{"class":1644},"sVt8B"," && ",[378,1647,1648],{"class":1599},"pod",[378,1650,1651],{"class":1593}," install",[378,1653,1654],{"class":1589}," --repo-update\n",[14,1656,1657,1658,1660,1661,1663,1664,1666,1667,1670],{},"Deleting ",[293,1659,569],{}," is safe because it is generated. Deleting ",[293,1662,572],{}," is also safe for a one-off repair, but it lets every pod re-resolve, so you may get newer versions than before. The CocoaPods guide recommends committing ",[293,1665,572],{},", so review the diff after the reinstall and commit the new one once the build passes. If you only suspect Xcode's cache, you can also delete ",[293,1668,1669],{},"~\u002FLibrary\u002FDeveloper\u002FXcode\u002FDerivedData","; it only holds build products, and Xcode recreates it.",[31,1672,1674],{"id":1673},"step-5-upgrade-the-flutterfire-plugins-together","Step 5: Upgrade the FlutterFire plugins together",[14,1676,1677,135,1680,135,1683,1686],{},[293,1678,1679],{},"firebase_core",[293,1681,1682],{},"cloud_firestore",[293,1684,1685],{},"firebase_auth"," and the other FlutterFire plugins are versioned together and each one depends on a specific Firebase SDK release. Upgrading one and leaving the others behind is a common source of build errors, including duplicate or conflicting native pods.",[527,1688,1689,1699,1714],{},[275,1690,1363,1691,1694,1695,1698],{},[293,1692,1693],{},"flutter pub outdated"," to see the gap, then upgrade the whole FlutterFire family in one ",[293,1696,1697],{},"pubspec.yaml"," change.",[275,1700,1701,1702,1705,1706,1710,1711,543],{},"Re-run ",[293,1703,1704],{},"flutterfire configure"," if you added a Firebase service or platform; the ",[84,1707,1709],{"href":1494,"rel":1708},[88],"Firebase docs"," say re-running it keeps your configuration current. Install the tool with ",[293,1712,1713],{},"dart pub global activate flutterfire_cli",[275,1715,1716,1717,1719],{},"If you pin a Firebase SDK version in the Podfile, remove the pin and let the plugins choose it. A manual pin that disagrees with ",[293,1718,1679],{}," is a classic conflict.",[31,1721,1723],{"id":1722},"step-6-know-that-cocoapods-is-being-phased-out","Step 6: Know that CocoaPods is being phased out",[14,1725,1726,1727,1732],{},"This matters for upgrades in late 2026. Firebase's docs warn that it will stop publishing new versions to CocoaPods in October 2026 and recommend Swift Package Manager. Flutter's ",[84,1728,1731],{"href":1729,"rel":1730},"https:\u002F\u002Fdocs.flutter.dev\u002Fpackages-and-plugins\u002Fswift-package-manager\u002Ffor-app-developers",[88],"Swift Package Manager page"," says SwiftPM support is on by default as of Flutter 3.44, that Flutter falls back to CocoaPods for plugins that don't support it yet, and that the CocoaPods registry becomes read-only on December 2, 2026.",[14,1734,1735],{},"In practice: after a Flutter upgrade, the first build may modify your Xcode project to add SwiftPM integration. Commit that change rather than reverting it, and if a build error mentions a Swift package, read it the same way as a pod error: find the first real failure.",[31,1737,1739],{"id":1738},"step-7-signing-errors-briefly","Step 7: Signing errors, briefly",[14,1741,1742],{},"If it compiles but fails to archive, it is usually signing. In Xcode, open the Runner target, Signing & Capabilities, and check that a team is selected, the bundle identifier matches your App Store Connect app, and \"Automatically manage signing\" is on unless you manage profiles yourself. Flutter's iOS setup page notes a signed developer certificate is needed even for device testing.",[31,1744,1746],{"id":1745},"when-to-get-help","When to get help",[14,1748,1749,1750,1752],{},"If an iOS build has eaten more than a day and the steps above haven't moved it, App369's ",[84,1751,1346],{"href":610}," covers build failures after a Flutter or FlutterFire upgrade. The $450 Diagnosis delivers the root cause with evidence and a fixed repair quote within 3 business days, and the $450 is credited toward the fix. The $1,200 Fix delivers the scoped defect as a pull request with a regression test within 5 business days. App Store approval isn't something anyone can guarantee; the ticket covers the code defect itself.",[31,1754,1756],{"id":1755},"frequently-asked-questions","Frequently Asked Questions",[899,1758,1760],{"id":1759},"why-did-my-flutter-ios-build-fail-after-upgrading-flutter","Why did my Flutter iOS build fail after upgrading Flutter?",[14,1762,1763,1764,1766,1767,1769,1770,1772,1773,543],{},"Most often the Podfile or Xcode project still has an old iOS deployment target, ",[293,1765,572],{}," pins old pod versions, or plugin versions no longer match each other. Run ",[293,1768,1372],{},", find the first ",[293,1771,1380],{}," line, then work through the deployment target and ",[293,1774,1543],{},[899,1776,1778],{"id":1777},"is-it-safe-to-delete-podfilelock-and-the-pods-folder","Is it safe to delete Podfile.lock and the Pods folder?",[14,1780,1781,1782,1784,1785,1787,1788,1790],{},"Yes, for a repair. ",[293,1783,569],{}," is generated and ",[293,1786,572],{}," is rebuilt by ",[293,1789,561],{},". The catch is that pods may resolve to newer versions, so check the new lock file and commit it once the build works.",[899,1792,1794],{"id":1793},"what-does-pod-install-repo-update-do","What does \"pod install --repo-update\" do?",[14,1796,1797],{},"It refreshes CocoaPods' local list of available pod versions before installing. Use it when a newly upgraded plugin needs a pod version your machine's spec list doesn't know about yet.",[899,1799,1801],{"id":1800},"should-i-upgrade-only-one-flutterfire-plugin","Should I upgrade only one FlutterFire plugin?",[14,1803,1804,1805,1807],{},"Avoid it. FlutterFire plugins depend on matching Firebase SDK releases, so upgrade ",[293,1806,1679],{}," and the other FlutterFire packages together and rebuild.",[899,1809,1811],{"id":1810},"do-i-need-to-switch-from-cocoapods-to-swift-package-manager","Do I need to switch from CocoaPods to Swift Package Manager?",[14,1813,1814],{},"Flutter handles it for you in recent versions and falls back to CocoaPods for plugins that don't support SwiftPM yet. Given Firebase's announced CocoaPods change, keep your plugins current rather than pinning old versions.",[618,1816,1817],{},"html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":374,"searchDepth":387,"depth":387,"links":1819},[1820,1821,1822,1823,1824,1825,1826,1827,1828],{"id":1354,"depth":387,"text":1355},{"id":1453,"depth":387,"text":1454},{"id":1487,"depth":387,"text":1488},{"id":1526,"depth":387,"text":1527},{"id":1673,"depth":387,"text":1674},{"id":1722,"depth":387,"text":1723},{"id":1738,"depth":387,"text":1739},{"id":1745,"depth":387,"text":1746},{"id":1755,"depth":387,"text":1756,"children":1829},[1830,1831,1832,1833,1834],{"id":1759,"depth":393,"text":1760},{"id":1777,"depth":393,"text":1778},{"id":1793,"depth":393,"text":1794},{"id":1800,"depth":393,"text":1801},{"id":1810,"depth":393,"text":1811},"2026-10-12T18:00:00.000Z","Flutter iOS build failing after upgrading Flutter, FlutterFire or Xcode? How to read the real error, then fix CocoaPods, deployment target and plugin version mismatches.",{"readingTimeStats":1838},{"text":1839,"minutes":1840,"time":1841,"words":1842},"6 min read",5.995,359700,1199,"\u002Fblog\u002Fflutter-ios-build-failed-after-upgrade-2026",{"title":1330,"description":1836},"blog\u002Fflutter-ios-build-failed-after-upgrade-2026","flutter ios build failed, cocoapods error, pod install failed, flutterfire upgrade, xcode build error, flutter build ios, firebase ios","https:\u002F\u002Fapp369.com\u002Fblog\u002Fflutter-ios-build-failed-after-upgrade-2026\u002F","j_nFje3qmyZUdc4vyGtG-sRzwIjhUzh5-9fXsxoyaZA",{"id":1850,"title":1851,"author":1852,"body":1854,"category":631,"createdAt":2196,"description":2197,"disclosure":634,"extension":635,"faq":2198,"howTo":634,"lastVerified":634,"location":652,"meta":2214,"navigation":659,"ogImage":634,"path":2219,"primaryKeyword":2220,"readingTime":662,"related":2221,"seo":2223,"sources":2224,"stem":2237,"tags":2238,"takeaways":2239,"updatedAt":2196,"url":2245,"__hash__":2246},"blog\u002Fblog\u002Fgoogle-play-16kb-page-size-flutter-android-2026.md","Google Play 16 KB Page Size: Fixing Flutter and Android Apps",{"name":7,"social":1853},{"twitter":9},{"type":11,"value":1855,"toc":2187},[1856,1862,1865,1870,1874,1923,1926,1929,1933,1952,1956,1959,1997,2001,2011,2069,2073,2111,2114,2117,2159,2176,2178,2185],[14,1857,1858,1861],{},[17,1859,1860],{},"If Play Console warns that your app doesn't support 16 KB memory page sizes, the fix is usually a newer Android Gradle Plugin and NDK, plus updated native dependencies."," Google requires apps targeting Android 15 and higher to support 16 KB pages on 64-bit devices, and says that starting February 1, 2027, updates without it can't be released. In my experience every Flutter Android app ships native code, so Flutter apps are in scope, and Flutter 3.38 is the first version that defaults to the NDK Google's fix needs.",[14,1863,1864],{},"The facts below come from Google's page-size guide, Google's May 2025 announcement, Flutter's 3.38 release post and Flutter's source code, as listed in the sources. I checked each one on October 18, 2026.",[14,1866,1867,1869],{},[17,1868,28],{}," App369 is my studio. I build and fix Android and iOS apps, mostly in Flutter, and the last section mentions what I sell. Google doesn't pay me for anything on this page.",[31,1871,1873],{"id":1872},"the-requirement-and-the-dates","The requirement and the dates",[36,1875,1876,1887],{},[39,1877,1878],{},[42,1879,1880,1882,1885],{},[45,1881,109],{},[45,1883,1884],{},"What Google said",[45,1886,115],{},[55,1888,1889,1904],{},[42,1890,1891,1894,1897],{},[60,1892,1893],{},"May 2025",[60,1895,1896],{},"From November 1, 2025, new apps and updates targeting Android 15+ must support 16 KB page sizes",[60,1898,1899],{},[84,1900,1903],{"href":1901,"rel":1902},"https:\u002F\u002Fandroid-developers.googleblog.com\u002F2025\u002F05\u002Fprepare-play-apps-for-devices-with-16kb-page-size.html",[88],"Android Developers Blog",[42,1905,1906,1911,1916],{},[60,1907,1908],{},[17,1909,1910],{},"As of October 16, 2026",[60,1912,1913],{},[17,1914,1915],{},"Apps targeting Android 15+ must support 16 KB pages on 64-bit devices. From February 1, 2027, updates that don't can't be released",[60,1917,1918],{},[84,1919,1922],{"href":1920,"rel":1921},"https:\u002F\u002Fdeveloper.android.com\u002Fguide\u002Fpractices\u002Fpage-sizes",[88],"Google page-size guide",[14,1924,1925],{},"The guide, last updated October 16, 2026, is the newer source, so I'd plan around February 1, 2027 and check Play Console for any warning on your own app.",[14,1927,1928],{},"Google's guide also explains why: devices with more memory are moving to 16 KB pages, and without recompiling, apps won't work on 16 KB devices in future Android releases. On a 16 KB device today, an app with 4 KB-aligned .so files that are stored uncompressed in the APK can run in a backcompat mode that shows a warning when it first launches.",[899,1930,1932],{"id":1931},"who-is-affected","Who is affected",[14,1934,1935,1936,1939,1940,1943,1944,1947,1948,1951],{},"Only apps with native code: ",[293,1937,1938],{},".so"," files in the APK's ",[293,1941,1942],{},"lib"," folder. That includes apps that use native code through an SDK or library, not just apps you wrote C or C++ for. In my experience, every Flutter Android release build has native libraries in that folder: ",[293,1945,1946],{},"libflutter.so"," for the engine and ",[293,1949,1950],{},"libapp.so"," for your compiled Dart code. Analyze APK, below, shows them.",[31,1953,1955],{"id":1954},"check-your-app","Check your app",[14,1957,1958],{},"Google's guide lists three checks:",[272,1960,1961,1970,1978],{},[275,1962,1963,1966,1967,1969],{},[17,1964,1965],{},"Analyze APK in Android Studio."," Open Build > Analyze APK, pick the APK and look in the ",[293,1968,1942],{}," folder. The Alignment column shows warnings for files with alignment problems.",[275,1971,1972,1977],{},[17,1973,1974],{},[293,1975,1976],{},"check_elf_alignment.sh"," on Linux or macOS. Run it on the APK. It reports whether each library is aligned.",[275,1979,1980,1985,1986],{},[17,1981,1982],{},[293,1983,1984],{},"zipalign"," for zip alignment. Google's example uses the copy in build-tools 35.0.0:",[369,1987,1991],{"className":1988,"code":1989,"language":1990,"meta":374,"style":374},"language-console shiki shiki-themes github-light github-dark","zipalign -v -c -P 16 4 APK_NAME.apk\n","console",[293,1992,1993],{"__ignoreMap":374},[378,1994,1995],{"class":380,"line":381},[378,1996,1989],{},[31,1998,2000],{"id":1999},"fix-it","Fix it",[14,2002,2003,2004,90,2007,2010],{},"Google's shortcut: if you update to ",[17,2005,2006],{},"AGP 8.5.1 or higher",[17,2008,2009],{},"NDK r28 or higher",", and your prebuilt dependencies are 16 KB compatible, the app is 16 KB compatible by default.",[36,2012,2013,2023],{},[39,2014,2015],{},[42,2016,2017,2020],{},[45,2018,2019],{},"If you're on",[45,2021,2022],{},"Google's guidance",[55,2024,2025,2037,2044,2058],{},[42,2026,2027,2030],{},[60,2028,2029],{},"AGP below 8.5.1",[60,2031,2032,2033,2036],{},"Upgrade to 8.5.1 or higher. Google notes that with AGP 8.3 to 8.5, an app can seem to work but fail to install when Play builds it from a bundle. If you can't upgrade, Google gives a ",[293,2034,2035],{},"useLegacyPackaging"," setting",[42,2038,2039,2041],{},[60,2040,2009],{},[60,2042,2043],{},"Compiles 16 KB-aligned by default",[42,2045,2046,2049],{},[60,2047,2048],{},"NDK r27 or lower",[60,2050,2051,2052,90,2055],{},"Add the linker flags ",[293,2053,2054],{},"-Wl,-z,max-page-size=16384",[293,2056,2057],{},"-Wl,-z,common-page-size=16384",[42,2059,2060,2066],{},[60,2061,2062,2063,2065],{},"Prebuilt ",[293,2064,1938],{}," files from an SDK",[60,2067,2068],{},"Get a 16 KB-compatible version from the vendor, or recompile them the same way",[31,2070,2072],{"id":2071},"flutter-apps","Flutter apps",[36,2074,2075,2089],{},[39,2076,2077],{},[42,2078,2079,2082],{},[45,2080,2081],{},"Flutter version",[45,2083,2084,2085,2088],{},"Default ",[293,2086,2087],{},"ndkVersion"," in Flutter's source",[55,2090,2091,2099],{},[42,2092,2093,2096],{},[60,2094,2095],{},"3.35 (August 14, 2025)",[60,2097,2098],{},"27.0.12077973 (NDK r27)",[42,2100,2101,2106],{},[60,2102,2103],{},[17,2104,2105],{},"3.38 (November 12, 2025)",[60,2107,2108],{},[17,2109,2110],{},"28.2.13676358 (NDK r28)",[14,2112,2113],{},"Flutter's 3.38 post calls upgrading \"essential preparation\" for the 16 KB requirement and says NDK r28 is the minimum for the alignment.",[14,2115,2116],{},"What to do in a Flutter app:",[272,2118,2119,2131,2144,2153],{},[275,2120,2121,2124,2125,1004,2127,2130],{},[17,2122,2123],{},"Upgrade Flutter to 3.38 or later",", or set ",[293,2126,2087],{},[293,2128,2129],{},"android\u002Fapp\u002Fbuild.gradle"," to an r28 version if you can't upgrade yet. My advice: upgrading is safer, because Flutter's 3.38 post lists a set of Gradle, AGP and Kotlin versions that Flutter tested together.",[275,2132,2133,1004,2136,2139,2140,2143],{},[17,2134,2135],{},"Check the AGP version",[293,2137,2138],{},"android\u002Fsettings.gradle"," (or the ",[293,2141,2142],{},"buildscript"," block on older projects). It needs to be 8.5.1 or higher.",[275,2145,2146,2149,2150,2152],{},[17,2147,2148],{},"Update plugins that ship native libraries."," My advice: after building, run Analyze APK and look at every ",[293,2151,1938],{}," file. A plugin with an old prebuilt library is the usual reason an app still fails after the Flutter upgrade.",[275,2154,2155,2158],{},[17,2156,2157],{},"Test on a 16 KB emulator."," Google's guide covers Android 15 emulator images with 16 KB page sizes. My advice: install a build there and make sure it starts without the compatibility warning.",[14,2160,2161,2162,2166,2167,2171,2172,543],{},"If the Flutter upgrade breaks the Android build first, see the ",[84,2163,2165],{"href":2164},"\u002Fblog\u002Fflutter-deleted-android-v1-embedding-build-failed-2026\u002F","v1 embedding fix"," and the ",[84,2168,2170],{"href":2169},"\u002Fblog\u002Fflutter-gradle-plugin-applied-imperatively-fix-2026\u002F","Gradle plugin fix",". Google Play also requires new apps and updates to target API 36 since August 31, 2026: see ",[84,2173,2175],{"href":2174},"\u002Fblog\u002Fgoogle-play-target-api-36-android-16-requirement-2026\u002F","the target API 36 guide",[31,2177,604],{"id":603},[14,2179,2180,2181,612,2183,543],{},"If Play Console flags your app for 16 KB page sizes, or an update fails after the fix, the ",[84,2182,611],{"href":610},[84,2184,616],{"href":615},[618,2186,620],{},{"title":374,"searchDepth":387,"depth":387,"links":2188},[2189,2192,2193,2194,2195],{"id":1872,"depth":387,"text":1873,"children":2190},[2191],{"id":1931,"depth":393,"text":1932},{"id":1954,"depth":387,"text":1955},{"id":1999,"depth":387,"text":2000},{"id":2071,"depth":387,"text":2072},{"id":603,"depth":387,"text":604},"2026-10-18T23:58:00.000Z","Google Play requires apps targeting Android 15 and higher to support 16 KB memory page sizes on 64-bit devices, and Google says that from February 1, 2027 updates without it can't be released. How to check an APK, the AGP and NDK versions that fix it, and why Flutter 3.38 matters, from Google's and Flutter's docs checked October 18, 2026.",[2199,2202,2205,2208,2211],{"question":2200,"answer":2201},"What is the Google Play 16 KB page size requirement?","Google says all apps targeting Android 15 (API level 35) and higher must support 16 KB memory page sizes on 64-bit devices on Google Play, and that starting February 1, 2027, app updates that don't support 16 KB page sizes can't be released.",{"question":2203,"answer":2204},"Does my Flutter app need to change for 16 KB pages?","In my experience Flutter apps ship native libraries, so they are in scope. Flutter's 3.38 release notes say 3.38 moved the default NDK to r28, the minimum Flutter names for 16 KB alignment. On an older Flutter, upgrade, or set a newer ndkVersion, and check every plugin that ships its own native libraries.",{"question":2206,"answer":2207},"How do I check whether my APK supports 16 KB pages?","Google lists three ways: Android Studio's Analyze APK shows alignment warnings for .so files in the lib folder, the check_elf_alignment.sh script checks ELF alignment on Linux or macOS, and zipalign -v -c -P 16 4 checks zip alignment.",{"question":2209,"answer":2210},"Which AGP and NDK versions do I need?","Google says AGP 8.5.1 or higher and NDK r28 or higher make an app 16 KB compatible by default, as long as prebuilt dependencies are 16 KB compatible too. With NDK r27 or lower, Google gives linker flags to set a 16 KB max page size.",{"question":2212,"answer":2213},"What happened to the November 1, 2025 date?","Google's May 2025 Android Developers Blog post said that from November 1, 2025, new apps and updates targeting Android 15+ must support 16 KB pages. Google's page-size guide, last updated October 16, 2026, says that starting February 1, 2027, updates without 16 KB support can't be released. Check Play Console for the dates that apply to your app.",{"readingTimeStats":2215},{"text":1294,"minutes":2216,"time":2217,"words":2218},4.035,242100,807,"\u002Fblog\u002Fgoogle-play-16kb-page-size-flutter-android-2026","16 kb page size",[1302,2222,664],"play-billing-library-7-deprecated-update-to-8-2026",{"title":1851,"description":2197},[2225,2227,2229,2230,2233,2236],{"title":2226,"url":1920},"Android Developers, Support 16 KB page sizes (last updated October 16, 2026)",{"title":2228,"url":1901},"Android Developers Blog, \"Prepare your apps for Google Play's 16 KB page size compatibility requirement\" (May 2025)",{"title":1315,"url":796},{"title":2231,"url":2232},"Flutter on GitHub, FlutterExtension.kt at 3.35.0 (default ndkVersion)","https:\u002F\u002Fgithub.com\u002Fflutter\u002Fflutter\u002Fblob\u002F3.35.0\u002Fpackages\u002Fflutter_tools\u002Fgradle\u002Fsrc\u002Fmain\u002Fkotlin\u002FFlutterExtension.kt",{"title":2234,"url":2235},"Flutter on GitHub, FlutterExtension.kt at 3.38.0 (default ndkVersion)","https:\u002F\u002Fgithub.com\u002Fflutter\u002Fflutter\u002Fblob\u002F3.38.0\u002Fpackages\u002Fflutter_tools\u002Fgradle\u002Fsrc\u002Fmain\u002Fkotlin\u002FFlutterExtension.kt",{"title":1317,"url":801},"blog\u002Fgoogle-play-16kb-page-size-flutter-android-2026","16 kb page size, google play 16 kb page size requirement, flutter 16kb page size, android 15 16 kb, ndk r28 16 kb alignment, agp 8.5.1 16 kb, check_elf_alignment, zipalign -P 16, play console 16 kb warning, 16 kb backcompat mode",[2240,2241,2242,2243,2244],"Google Play requires apps targeting Android 15 (API level 35) and higher to support 16 KB memory page sizes on 64-bit devices. Google says that starting February 1, 2027, updates that don't support 16 KB page sizes can't be released.","Only apps with native code are affected: .so files inside the APK. In my experience every Flutter Android release build ships native libraries, so Flutter apps are in scope.","Google says apps built with AGP 8.5.1 or higher and NDK r28 or higher, with 16 KB-compatible prebuilt dependencies, are 16 KB compatible by default.","Flutter 3.38 (November 12, 2025) moved the default NDK to r28, which Flutter calls the minimum for 16 KB alignment. Flutter 3.35 still defaulted to NDK r27.","On a 16 KB device, an app with 4 KB-aligned .so files that are stored uncompressed in the APK can run in a backcompat mode that shows a warning on first launch. Google says that without recompiling, apps won't work on 16 KB devices in future Android releases.","https:\u002F\u002Fapp369.com\u002Fblog\u002Fgoogle-play-16kb-page-size-flutter-android-2026\u002F","IsA4Wql8Qv-tdssu-PAyNveCANbZeSd7FIw4eqFW-LU",[2248,2250,2253,2254,2257],{"keyword":5,"url":709,"title":5,"relevance":2249},75,{"keyword":2251,"url":2252,"title":2251,"relevance":429},"Flutter vs Native in 2026: An Honest Decision Guide","https:\u002F\u002Fapp369.com\u002Fblog\u002Fflutter-vs-native-app-development-2026\u002F",{"keyword":714,"url":1326,"title":714,"relevance":411},{"keyword":2255,"url":2256,"title":2255,"relevance":411},"ITMS-90683: Fix Missing Purpose String in Info.plist","https:\u002F\u002Fapp369.com\u002Fblog\u002Fitms-90683-missing-purpose-string-info-plist-flutter-2026\u002F",{"keyword":2258,"url":2259,"title":2258,"relevance":411},"ITMS-90725 SDK Version Issue: Fix in Flutter (Xcode 26)","https:\u002F\u002Fapp369.com\u002Fblog\u002Fitms-90725-sdk-version-issue-xcode-26-flutter-2026\u002F",1792361352615]