[{"data":1,"prerenderedAt":2037},["ShallowReactive",2],{"\u002Fblog\u002Fgoogle-play-16kb-page-size-flutter-android-2026\u002F":3,"\u002Fblog\u002Fgoogle-play-16kb-page-size-flutter-android-2026\u002F-related":454,"\u002Fblog\u002Fgoogle-play-16kb-page-size-flutter-android-2026\u002F-resources":2021},{"id":4,"title":5,"author":6,"body":10,"category":390,"createdAt":391,"description":392,"disclosure":393,"extension":394,"faq":395,"howTo":393,"lastVerified":393,"location":411,"meta":412,"navigation":418,"ogImage":393,"path":419,"primaryKeyword":420,"readingTime":421,"related":422,"seo":426,"sources":427,"stem":444,"tags":445,"takeaways":446,"updatedAt":391,"url":452,"__hash__":453},"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":8},"Simon Dziak",{"twitter":9},"@SzymonDziak",{"type":11,"value":12,"toc":379},"minimark",[13,21,24,30,35,94,97,100,105,125,129,132,177,181,192,250,254,292,295,298,341,359,363,375],[14,15,16,20],"p",{},[17,18,19],"strong",{},"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,22,23],{},"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,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. Google doesn't pay me for anything on this page.",[31,32,34],"h2",{"id":33},"the-requirement-and-the-dates","The requirement and the dates",[36,37,38,54],"table",{},[39,40,41],"thead",{},[42,43,44,48,51],"tr",{},[45,46,47],"th",{},"Date",[45,49,50],{},"What Google said",[45,52,53],{},"Source",[55,56,57,75],"tbody",{},[42,58,59,63,66],{},[60,61,62],"td",{},"May 2025",[60,64,65],{},"From November 1, 2025, new apps and updates targeting Android 15+ must support 16 KB page sizes",[60,67,68],{},[69,70,74],"a",{"href":71,"rel":72},"https:\u002F\u002Fandroid-developers.googleblog.com\u002F2025\u002F05\u002Fprepare-play-apps-for-devices-with-16kb-page-size.html",[73],"nofollow","Android Developers Blog",[42,76,77,82,87],{},[60,78,79],{},[17,80,81],{},"As of October 16, 2026",[60,83,84],{},[17,85,86],{},"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,88,89],{},[69,90,93],{"href":91,"rel":92},"https:\u002F\u002Fdeveloper.android.com\u002Fguide\u002Fpractices\u002Fpage-sizes",[73],"Google page-size guide",[14,95,96],{},"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,98,99],{},"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.",[101,102,104],"h3",{"id":103},"who-is-affected","Who is affected",[14,106,107,108,112,113,116,117,120,121,124],{},"Only apps with native code: ",[109,110,111],"code",{},".so"," files in the APK's ",[109,114,115],{},"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: ",[109,118,119],{},"libflutter.so"," for the engine and ",[109,122,123],{},"libapp.so"," for your compiled Dart code. Analyze APK, below, shows them.",[31,126,128],{"id":127},"check-your-app","Check your app",[14,130,131],{},"Google's guide lists three checks:",[133,134,135,145,153],"ol",{},[136,137,138,141,142,144],"li",{},[17,139,140],{},"Analyze APK in Android Studio."," Open Build > Analyze APK, pick the APK and look in the ",[109,143,115],{}," folder. The Alignment column shows warnings for files with alignment problems.",[136,146,147,152],{},[17,148,149],{},[109,150,151],{},"check_elf_alignment.sh"," on Linux or macOS. Run it on the APK. It reports whether each library is aligned.",[136,154,155,160,161],{},[17,156,157],{},[109,158,159],{},"zipalign"," for zip alignment. Google's example uses the copy in build-tools 35.0.0:",[162,163,168],"pre",{"className":164,"code":165,"language":166,"meta":167,"style":167},"language-console shiki shiki-themes github-light github-dark","zipalign -v -c -P 16 4 APK_NAME.apk\n","console","",[109,169,170],{"__ignoreMap":167},[171,172,175],"span",{"class":173,"line":174},"line",1,[171,176,165],{},[31,178,180],{"id":179},"fix-it","Fix it",[14,182,183,184,187,188,191],{},"Google's shortcut: if you update to ",[17,185,186],{},"AGP 8.5.1 or higher"," and ",[17,189,190],{},"NDK r28 or higher",", and your prebuilt dependencies are 16 KB compatible, the app is 16 KB compatible by default.",[36,193,194,204],{},[39,195,196],{},[42,197,198,201],{},[45,199,200],{},"If you're on",[45,202,203],{},"Google's guidance",[55,205,206,218,225,239],{},[42,207,208,211],{},[60,209,210],{},"AGP below 8.5.1",[60,212,213,214,217],{},"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 ",[109,215,216],{},"useLegacyPackaging"," setting",[42,219,220,222],{},[60,221,190],{},[60,223,224],{},"Compiles 16 KB-aligned by default",[42,226,227,230],{},[60,228,229],{},"NDK r27 or lower",[60,231,232,233,187,236],{},"Add the linker flags ",[109,234,235],{},"-Wl,-z,max-page-size=16384",[109,237,238],{},"-Wl,-z,common-page-size=16384",[42,240,241,247],{},[60,242,243,244,246],{},"Prebuilt ",[109,245,111],{}," files from an SDK",[60,248,249],{},"Get a 16 KB-compatible version from the vendor, or recompile them the same way",[31,251,253],{"id":252},"flutter-apps","Flutter apps",[36,255,256,270],{},[39,257,258],{},[42,259,260,263],{},[45,261,262],{},"Flutter version",[45,264,265,266,269],{},"Default ",[109,267,268],{},"ndkVersion"," in Flutter's source",[55,271,272,280],{},[42,273,274,277],{},[60,275,276],{},"3.35 (August 14, 2025)",[60,278,279],{},"27.0.12077973 (NDK r27)",[42,281,282,287],{},[60,283,284],{},[17,285,286],{},"3.38 (November 12, 2025)",[60,288,289],{},[17,290,291],{},"28.2.13676358 (NDK r28)",[14,293,294],{},"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,296,297],{},"What to do in a Flutter app:",[133,299,300,313,326,335],{},[136,301,302,305,306,308,309,312],{},[17,303,304],{},"Upgrade Flutter to 3.38 or later",", or set ",[109,307,268],{}," in ",[109,310,311],{},"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.",[136,314,315,308,318,321,322,325],{},[17,316,317],{},"Check the AGP version",[109,319,320],{},"android\u002Fsettings.gradle"," (or the ",[109,323,324],{},"buildscript"," block on older projects). It needs to be 8.5.1 or higher.",[136,327,328,331,332,334],{},[17,329,330],{},"Update plugins that ship native libraries."," My advice: after building, run Analyze APK and look at every ",[109,333,111],{}," file. A plugin with an old prebuilt library is the usual reason an app still fails after the Flutter upgrade.",[136,336,337,340],{},[17,338,339],{},"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,342,343,344,348,349,353,354,358],{},"If the Flutter upgrade breaks the Android build first, see the ",[69,345,347],{"href":346},"\u002Fblog\u002Fflutter-deleted-android-v1-embedding-build-failed-2026\u002F","v1 embedding fix"," and the ",[69,350,352],{"href":351},"\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 ",[69,355,357],{"href":356},"\u002Fblog\u002Fgoogle-play-target-api-36-android-16-requirement-2026\u002F","the target API 36 guide",".",[31,360,362],{"id":361},"need-a-hand","Need a hand?",[14,364,365,366,370,371,358],{},"If Play Console flags your app for 16 KB page sizes, or an update fails after the fix, the ",[69,367,369],{"href":368},"\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 ",[69,372,374],{"href":373},"\u002Fcontact\u002F","send me a short description",[376,377,378],"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":167,"searchDepth":380,"depth":380,"links":381},2,[382,386,387,388,389],{"id":33,"depth":380,"text":34,"children":383},[384],{"id":103,"depth":385,"text":104},3,{"id":127,"depth":380,"text":128},{"id":179,"depth":380,"text":180},{"id":252,"depth":380,"text":253},{"id":361,"depth":380,"text":362},"AI & Technology","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.",null,"md",[396,399,402,405,408],{"question":397,"answer":398},"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":400,"answer":401},"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":403,"answer":404},"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":406,"answer":407},"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":409,"answer":410},"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.","Boynton Beach, FL",{"readingTimeStats":413},{"text":414,"minutes":415,"time":416,"words":417},"5 min read",4.035,242100,807,true,"\u002Fblog\u002Fgoogle-play-16kb-page-size-flutter-android-2026","16 kb page size","7 min",[423,424,425],"google-play-target-api-36-android-16-requirement-2026","play-billing-library-7-deprecated-update-to-8-2026","flutter-uiscene-migration-xcode-27-app-wont-launch-2026",{"title":5,"description":392},[428,430,432,435,438,441],{"title":429,"url":91},"Android Developers, Support 16 KB page sizes (last updated October 16, 2026)",{"title":431,"url":71},"Android Developers Blog, \"Prepare your apps for Google Play's 16 KB page size compatibility requirement\" (May 2025)",{"title":433,"url":434},"Flutter blog, What's new in Flutter 3.38","https:\u002F\u002Fflutter.dev\u002Fblog\u002Fwhats-new-in-flutter-3-38",{"title":436,"url":437},"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":439,"url":440},"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":442,"url":443},"Flutter release archive (macOS)","https:\u002F\u002Fstorage.googleapis.com\u002Fflutter_infra_release\u002Freleases\u002Freleases_macos.json","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",[447,448,449,450,451],"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",[455,898,1387],{"id":456,"title":457,"author":458,"body":460,"category":390,"createdAt":845,"description":846,"disclosure":393,"extension":394,"faq":847,"howTo":393,"lastVerified":393,"location":411,"meta":863,"navigation":418,"ogImage":393,"path":868,"primaryKeyword":869,"readingTime":421,"related":870,"seo":873,"sources":874,"stem":888,"tags":889,"takeaways":890,"updatedAt":845,"url":896,"__hash__":897},"blog\u002Fblog\u002Fgoogle-play-target-api-36-android-16-requirement-2026.md","Google Play Requires Target API 36: The Android 16 Update",{"name":7,"social":459},{"twitter":9},{"type":11,"value":461,"toc":838},[462,472,475,479,483,523,532,535,556,560,569,643,650,652,670,712,715,718,779,792,796,799,829,831],[14,463,464,467,468,471],{},[17,465,466],{},"Since August 31, 2026, Google Play only accepts new apps and updates that target Android 16 (API level 36), and Google says you'll be able to request an extension to November 1, 2026."," Raising ",[109,469,470],{},"targetSdkVersion"," is one line, but it turns on Android 16 behavior: no edge-to-edge opt-out, predictive back by default, and no orientation lock on tablets. Test those three before you ship. In a Flutter app, the quickest path is usually Flutter 3.35 or later, which targets 36 by default.",[14,473,474],{},"The requirements below come from Google's target API page and its Android 16 behavior changes, and the Flutter defaults from Flutter's source code, as listed in the sources. I checked each one on October 18, 2026.",[14,476,477,29],{},[17,478,28],{},[31,480,482],{"id":481},"the-requirement","The requirement",[36,484,485,495],{},[39,486,487],{},[42,488,489,492],{},[45,490,491],{},"App type",[45,493,494],{},"Must target, for new apps and updates from August 31, 2026",[55,496,497,507,515],{},[42,498,499,502],{},[60,500,501],{},"Phone and tablet apps",[60,503,504],{},[17,505,506],{},"Android 16 (API level 36)",[42,508,509,512],{},[60,510,511],{},"Wear OS and Android Automotive OS",[60,513,514],{},"Android 15 (API level 35)",[42,516,517,520],{},[60,518,519],{},"Android TV and Android XR",[60,521,522],{},"Android 14 (API level 34)",[14,524,525,526,531],{},"Source: ",[69,527,530],{"href":528,"rel":529},"https:\u002F\u002Fdeveloper.android.com\u002Fgoogle\u002Fplay\u002Frequirements\u002Ftarget-sdk",[73],"Google Play target API level requirement",", last updated October 16, 2026.",[14,533,534],{},"Google's page also says:",[536,537,538,544,550],"ul",{},[136,539,540,543],{},[17,541,542],{},"Extension:"," if you need more time, you'll be able to request an extension to November 1, 2026. Google says the extension forms will be in Play Console \"later this year\", so check there for the form.",[136,545,546,549],{},[17,547,548],{},"Existing apps:"," to stay available to new users on devices running a newer Android version than the app targets, an existing app must target API 35 or higher. An app that targets API 34 or lower is only available on devices running that Android version or lower.",[136,551,552,555],{},[17,553,554],{},"Exception:"," permanently private apps for one organization's internal use.",[31,557,559],{"id":558},"what-changes-when-you-target-api-36","What changes when you target API 36",[14,561,562,563,568],{},"Google's ",[69,564,567],{"href":565,"rel":566},"https:\u002F\u002Fdeveloper.android.com\u002Fabout\u002Fversions\u002F16\u002Fbehavior-changes-16",[73],"Android 16 behavior changes"," apply to apps that target API 36 and run on Android 16 or higher. These are the three I'd test first:",[36,570,571,584],{},[39,572,573],{},[42,574,575,578,581],{},[45,576,577],{},"Change",[45,579,580],{},"What Google says",[45,582,583],{},"Temporary way out",[55,585,586,603,627],{},[42,587,588,593,600],{},[60,589,590],{},[17,591,592],{},"Edge-to-edge",[60,594,595,596,599],{},"Apps can no longer opt out of drawing behind the status and navigation bars. ",[109,597,598],{},"windowOptOutEdgeToEdgeEnforcement"," is deprecated and disabled",[60,601,602],{},"None for API 36",[42,604,605,610,621],{},[60,606,607],{},[17,608,609],{},"Predictive back",[60,611,612,613,616,617,620],{},"Predictive back animations are on by default. ",[109,614,615],{},"onBackPressed"," is not called and ",[109,618,619],{},"KEYCODE_BACK"," is not dispatched",[60,622,623,626],{},[109,624,625],{},"android:enableOnBackInvokedCallback=\"false\""," in the manifest",[42,628,629,634,637],{},[60,630,631],{},[17,632,633],{},"Large screens",[60,635,636],{},"On displays at least 600dp wide, orientation, resizability and aspect ratio restrictions are ignored, so the app fills the window",[60,638,639,642],{},[109,640,641],{},"PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY",". Google says it won't apply once you target API 37",[14,644,645,646,649],{},"The large-screen rule doesn't apply to games (based on ",[109,647,648],{},"android:appCategory","), to screens smaller than 600dp, or when users opt in to the app's default behavior in the device's aspect ratio settings.",[31,651,253],{"id":252},[14,653,654,655,308,658,661,662,665,666,669],{},"Flutter's project template sets the target from the Flutter version: ",[109,656,657],{},"targetSdk = flutter.targetSdkVersion",[109,659,660],{},"android\u002Fapp\u002Fbuild.gradle.kts"," in Flutter 3.35's template, and ",[109,663,664],{},"targetSdkVersion flutter.targetSdkVersion"," in older Groovy templates such as Flutter 3.10's. Flutter's ",[109,667,668],{},"FlutterExtension"," source sets it to:",[36,671,672,683],{},[39,673,674],{},[42,675,676,678],{},[45,677,262],{},[45,679,265,680],{},[109,681,682],{},"flutter.targetSdkVersion",[55,684,685,693,700],{},[42,686,687,690],{},[60,688,689],{},"3.29 (February 12, 2025)",[60,691,692],{},"35",[42,694,695,698],{},[60,696,697],{},"3.32 (May 20, 2025)",[60,699,692],{},[42,701,702,707],{},[60,703,704],{},[17,705,706],{},"3.35 (August 14, 2025) and later",[60,708,709],{},[17,710,711],{},"36",[14,713,714],{},"Release dates from Flutter's release archive.",[14,716,717],{},"What that means for a Flutter app:",[133,719,720,742,756,769],{},[136,721,722,731,732,734,735,738,739,741],{},[17,723,724,725,727,728,358],{},"Check ",[109,726,311],{}," or ",[109,729,730],{},"build.gradle.kts"," If it uses ",[109,733,682],{},", Flutter 3.35 or later gives you 36. If it has a hard-coded number, change it to 36 yourself (",[109,736,737],{},"targetSdk = 36"," in a ",[109,740,730],{}," file).",[136,743,744,747,748,751,752,755],{},[17,745,746],{},"Edge-to-edge."," My advice: Flutter draws its own UI, so the visible risk is content under the status or navigation bar. Check every screen with ",[109,749,750],{},"SafeArea"," or padding from ",[109,753,754],{},"MediaQuery",", including bottom sheets and screens with a bottom bar.",[136,757,758,761,762,764,765,768],{},[17,759,760],{},"Back navigation."," If the app or a plugin overrides ",[109,763,615],{}," in Android code, that override won't be called on Android 16. My advice: use ",[109,766,767],{},"PopScope"," on the Flutter side for back handling, and check plugins that intercept back.",[136,770,771,774,775,778],{},[17,772,773],{},"Tablets."," If the app locks orientation with ",[109,776,777],{},"SystemChrome.setPreferredOrientations"," or the manifest, test it on a tablet or a large emulator, because Google says that lock is ignored on screens 600dp or wider.",[14,780,781,782,348,784,786,787,791],{},"If an older app can't move to Flutter 3.35 because the Android build breaks first, the ",[69,783,347],{"href":346},[69,785,352],{"href":351}," cover the two errors Flutter 3.29 introduced. If the app sells in-app purchases, the ",[69,788,790],{"href":789},"\u002Fblog\u002Fplay-billing-library-7-deprecated-update-to-8-2026\u002F","Billing Library 8 deadline"," is due at the same time.",[31,793,795],{"id":794},"what-to-do-now","What to do now",[14,797,798],{},"This section is my advice, not Google's.",[133,800,801,811,817,823],{},[136,802,803,806,807,810],{},[17,804,805],{},"Check the target your last release used."," Look at ",[109,808,809],{},"targetSdk"," in the build file for that release, or the app bundle details in Play Console.",[136,812,813,816],{},[17,814,815],{},"Request the extension if the change won't ship in time,"," once the form appears in Play Console. As of October 18, 2026, the November 1 extension date is two weeks away.",[136,818,819,822],{},[17,820,821],{},"Raise the target, then test on an Android 16 device or emulator."," Go through every screen for edge-to-edge, try the back gesture everywhere, and rotate on a tablet-sized emulator.",[136,824,825,828],{},[17,826,827],{},"Ship to a closed testing track first."," Catch layout and back-gesture issues before your users do.",[31,830,362],{"id":361},[14,832,833,834,370,836,358],{},"If an app can't ship an update because of the target API requirement, or something broke after raising it, the ",[69,835,369],{"href":368},[69,837,374],{"href":373},{"title":167,"searchDepth":380,"depth":380,"links":839},[840,841,842,843,844],{"id":481,"depth":380,"text":482},{"id":558,"depth":380,"text":559},{"id":252,"depth":380,"text":253},{"id":794,"depth":380,"text":795},{"id":361,"depth":380,"text":362},"2026-10-18T23:45:00.000Z","Since August 31, 2026, Google Play requires new apps and updates to target Android 16 (API level 36), with an extension to November 1, 2026. What changes when you target API 36 (edge-to-edge, predictive back, large-screen orientation), which Flutter versions target it by default, and what to test, from Google's docs checked October 18, 2026.",[848,851,854,857,860],{"question":849,"answer":850},"What is the Google Play target API level requirement for 2026?","Google says that starting August 31, 2026, new apps and app updates must target Android 16 (API level 36) or higher. Wear OS and Android Automotive OS apps must target API 35, and Android TV and Android XR apps API 34. Google says you'll be able to request an extension to November 1, 2026.",{"question":852,"answer":853},"What happens to my app if it targets an older API level?","Google says existing apps must target API 35 or higher to stay available to new users on devices running a newer Android version than the app targets. An app that targets API 34 or lower is only available on devices running that Android version or lower. New apps and updates must target API 36 to be submitted.",{"question":855,"answer":856},"How do I set targetSdkVersion 36 in a Flutter app?","If android\u002Fapp\u002Fbuild.gradle uses targetSdkVersion flutter.targetSdkVersion, upgrading to Flutter 3.35 or later sets it to 36, per Flutter's FlutterExtension source. Otherwise set targetSdkVersion 36 (or targetSdk = 36 in build.gradle.kts) yourself, and check that compileSdk is at least 36.",{"question":858,"answer":859},"Why did the back button stop working after targeting Android 16?","Google says that for apps targeting API 36 on Android 16 devices, onBackPressed is not called and KeyEvent.KEYCODE_BACK is not dispatched. Move to the supported back navigation APIs, or opt out temporarily with android:enableOnBackInvokedCallback=\"false\" in the manifest.",{"question":861,"answer":862},"Can I still lock my app to portrait on tablets?","Not by default. Google says that for apps targeting API 36, orientation, resizability and aspect ratio restrictions don't apply on displays at least 600dp wide, except for games and when users opt in. A temporary manifest opt-out exists, but Google says it won't apply once you target API 37.",{"readingTimeStats":864},{"text":414,"minutes":865,"time":866,"words":867},4.145,248700,829,"\u002Fblog\u002Fgoogle-play-target-api-36-android-16-requirement-2026","target api level 36",[424,871,872],"flutter-gradle-plugin-applied-imperatively-fix-2026","flutter-deleted-android-v1-embedding-build-failed-2026",{"title":457,"description":846},[875,877,879,881,884,887],{"title":876,"url":528},"Android Developers, Meet Google Play's target API level requirement (last updated October 16, 2026)",{"title":878,"url":565},"Android Developers, Behavior changes: apps targeting Android 16 or higher (last updated October 16, 2026)",{"title":880,"url":437},"Flutter on GitHub, FlutterExtension.kt at 3.35.0",{"title":882,"url":883},"Flutter on GitHub, app build.gradle.kts template at 3.35.0","https:\u002F\u002Fgithub.com\u002Fflutter\u002Fflutter\u002Fblob\u002F3.35.0\u002Fpackages\u002Fflutter_tools\u002Ftemplates\u002Fapp\u002Fandroid-kotlin.tmpl\u002Fapp\u002Fbuild.gradle.kts.tmpl",{"title":885,"url":886},"Flutter on GitHub, app build.gradle template at 3.10.0","https:\u002F\u002Fgithub.com\u002Fflutter\u002Fflutter\u002Fblob\u002F3.10.0\u002Fpackages\u002Fflutter_tools\u002Ftemplates\u002Fapp_shared\u002Fandroid-kotlin.tmpl\u002Fapp\u002Fbuild.gradle.tmpl",{"title":442,"url":443},"blog\u002Fgoogle-play-target-api-36-android-16-requirement-2026","target api level 36, google play target sdk 36, android 16 target api requirement, targetSdkVersion 36 flutter, play console target api level warning, edge to edge opt out android 16, predictive back android 16, onBackPressed not called android 16, flutter targetSdkVersion default",[891,892,893,894,895],"Since August 31, 2026, Google Play requires new apps and app updates to target Android 16 (API level 36). Wear OS and Android Automotive OS apps need API 35, and Android TV and Android XR apps need API 34.","Google says you'll be able to request an extension to November 1, 2026, and that the extension forms will be in Play Console.","Existing apps must target API 35 or higher to stay available to new users on devices running a newer Android version than the app targets.","Targeting API 36 changes behavior on Android 16 devices: apps can no longer opt out of edge-to-edge, predictive back is on by default and onBackPressed is no longer called, and orientation and resizability limits are ignored on screens at least 600dp wide.","Flutter 3.35 and later set flutter.targetSdkVersion to 36. Flutter 3.29 and 3.32 set it to 35, so an app on those versions has to upgrade Flutter or set 36 itself.","https:\u002F\u002Fapp369.com\u002Fblog\u002Fgoogle-play-target-api-36-android-16-requirement-2026\u002F","IQ1ZDe02nMyEW91krtaNe5bo5GALwyHxNVZpM87q73w",{"id":899,"title":900,"author":901,"body":903,"category":390,"createdAt":1330,"description":1331,"disclosure":393,"extension":394,"faq":1332,"howTo":393,"lastVerified":393,"location":411,"meta":1351,"navigation":418,"ogImage":393,"path":1356,"primaryKeyword":1357,"readingTime":421,"related":1358,"seo":1360,"sources":1361,"stem":1377,"tags":1378,"takeaways":1379,"updatedAt":1330,"url":1385,"__hash__":1386},"blog\u002Fblog\u002Fplay-billing-library-7-deprecated-update-to-8-2026.md","Play Billing Library 7 Deprecated: Update to 8 by November 1",{"name":7,"social":902},{"twitter":9},{"type":11,"value":904,"toc":1323},[905,915,918,923,927,930,1008,1016,1019,1043,1047,1050,1131,1146,1150,1225,1228,1250,1252,1254,1314,1316],[14,906,907,910,911,914],{},[17,908,909],{},"If Play Console warns that your app uses an unsupported version of the Google Play Billing Library, version 7 is the likely cause: its deadline for new apps and updates was August 31, 2026, and Google says the extension it offers runs until November 1, 2026."," Google says existing apps keep working, and new apps and updates must use a supported version. In my reading, an app still on version 7 can't ship an update once the extension runs out. For a Flutter app, that usually means a newer ",[109,912,913],{},"in_app_purchase"," or RevenueCat package, and possibly a newer Flutter.",[14,916,917],{},"The deadlines below come from Google's Billing Library deprecation page and release notes, and the package versions from pub.dev and RevenueCat's changelog, as listed in the sources. I checked each one on October 18, 2026.",[14,919,920,922],{},[17,921,28],{}," App369 is my studio. I build and fix apps, including in-app purchases and subscriptions in Flutter, and the last section mentions what I sell. Google and RevenueCat don't pay me for anything on this page.",[31,924,926],{"id":925},"the-deadlines","The deadlines",[14,928,929],{},"Google gives every Billing Library version a two-year deprecation cycle. Its table:",[36,931,932,945],{},[39,933,934],{},[42,935,936,939,942],{},[45,937,938],{},"Version",[45,940,941],{},"New apps and updates must move by",[45,943,944],{},"Extension deadline",[55,946,947,958,969,986,997],{},[42,948,949,952,955],{},[60,950,951],{},"5",[60,953,954],{},"August 31, 2024",[60,956,957],{},"November 1, 2024",[42,959,960,963,966],{},[60,961,962],{},"6",[60,964,965],{},"August 31, 2025",[60,967,968],{},"November 1, 2025",[42,970,971,976,981],{},[60,972,973],{},[17,974,975],{},"7",[60,977,978],{},[17,979,980],{},"August 31, 2026",[60,982,983],{},[17,984,985],{},"November 1, 2026",[42,987,988,991,994],{},[60,989,990],{},"8",[60,992,993],{},"August 31, 2027",[60,995,996],{},"November 1, 2027",[42,998,999,1002,1005],{},[60,1000,1001],{},"9",[60,1003,1004],{},"August 31, 2028",[60,1006,1007],{},"November 1, 2028",[14,1009,525,1010,1015],{},[69,1011,1014],{"href":1012,"rel":1013},"https:\u002F\u002Fdeveloper.android.com\u002Fgoogle\u002Fplay\u002Fbilling\u002Fdeprecation-faq",[73],"Google Play Billing Library version deprecation",", last updated September 9, 2026.",[14,1017,1018],{},"Google's FAQ also says:",[536,1020,1021,1027,1037],{},[136,1022,1023,1026],{},[17,1024,1025],{},"Existing apps still work."," Unmaintained APKs don't need updates. The rule applies to new apps and updates.",[136,1028,1029,1032,1033,1036],{},[17,1030,1031],{},"The dependency check applies to APKs that use billing."," Google says these dependencies only appear in APKs that require the ",[109,1034,1035],{},"com.android.vending.BILLING"," permission.",[136,1038,1039,1042],{},[17,1040,1041],{},"The extension form is in Play Console."," An app on an unsupported version gets a warning. Open its details on the Policy status page to find the form.",[31,1044,1046],{"id":1045},"what-changed-in-version-8","What changed in version 8",[14,1048,1049],{},"Version 8.0.0 was released on June 30, 2025. Per Google's release notes, the changes most likely to break an older integration are:",[36,1051,1052,1062],{},[39,1053,1054],{},[42,1055,1056,1059],{},[45,1057,1058],{},"Change in 8.0.0",[45,1060,1061],{},"What to use instead",[55,1063,1064,1079,1091,1108,1120],{},[42,1065,1066,1072],{},[60,1067,1068,1071],{},[109,1069,1070],{},"queryPurchaseHistory()"," removed",[60,1073,1074,1075,1078],{},"Google lists ",[109,1076,1077],{},"queryPurchasesAsync()"," for acknowledged and pending purchases, says to track consumed purchases on your own servers, and points to the voided-purchases API for canceled ones",[42,1080,1081,1086],{},[60,1082,1083,1071],{},[109,1084,1085],{},"querySkuDetailsAsync()",[60,1087,1088],{},[109,1089,1090],{},"queryProductDetailsAsync()",[42,1092,1093,1099],{},[60,1094,1095,1098],{},[109,1096,1097],{},"enablePendingPurchases()"," with no arguments removed",[60,1100,1101,1104,1105],{},[109,1102,1103],{},"enablePendingPurchases(PendingPurchasesParams)",". The old call equals ",[109,1106,1107],{},"PendingPurchasesParams.newBuilder().enableOneTimeProducts().build()",[42,1109,1110,1115],{},[60,1111,1112,1071],{},[109,1113,1114],{},"queryPurchasesAsync(String skuType, ...)",[60,1116,1117],{},[109,1118,1119],{},"queryPurchasesAsync(QueryPurchasesParams, ...)",[42,1121,1122,1128],{},[60,1123,1124,1127],{},[109,1125,1126],{},"onProductDetailsResponse()"," signature changed",[60,1129,1130],{},"Handle the new result, which also lists products that couldn't be fetched",[14,1132,1133,1134,1137,1138,1141,1142,1145],{},"Version 8 also added optional automatic service reconnection (",[109,1135,1136],{},"enableAutoServiceReconnection()",") and sub-response codes on ",[109,1139,1140],{},"launchBillingFlow()",", such as ",[109,1143,1144],{},"PAYMENT_DECLINED_DUE_TO_INSUFFICIENT_FUNDS",". In-app items are now called one-time products.",[31,1147,1149],{"id":1148},"flutter-apps-which-package-versions-include-version-8","Flutter apps: which package versions include version 8",[36,1151,1152,1165],{},[39,1153,1154],{},[42,1155,1156,1159,1162],{},[45,1157,1158],{},"Package",[45,1160,1161],{},"First version on Billing Library 8",[45,1163,1164],{},"Notes, per its changelog or pubspec",[55,1166,1167,1190,1208],{},[42,1168,1169,1174,1180],{},[60,1170,1171],{},[109,1172,1173],{},"in_app_purchase_android",[60,1175,1176,1179],{},[17,1177,1178],{},"0.5.0"," (May 27, 2026)",[60,1181,1182,1183,1186,1187],{},"Updates from 7.1.1 to 8.0.0. Breaking: removes ",[109,1184,1185],{},"queryPurchaseHistory",", use ",[109,1188,1189],{},"queryPurchases",[42,1191,1192,1196,1202],{},[60,1193,1194],{},[109,1195,913],{},[60,1197,1198,1201],{},[17,1199,1200],{},"3.3.0"," (June 3, 2026)",[60,1203,1204,1205,1207],{},"Depends on ",[109,1206,1173],{}," ^0.5.0. Requires Flutter 3.38 or later and Dart 3.10",[42,1209,1210,1216,1222],{},[60,1211,1212,1215],{},[109,1213,1214],{},"purchases_flutter"," (RevenueCat)",[60,1217,1218,1221],{},[17,1219,1220],{},"9.0.0"," (July 18, 2025)",[60,1223,1224],{},"Billing Library 8. Version 10.0.0 moved to 8.3.0 and raised the Android minimum to API 23",[14,1226,1227],{},"Two things to watch:",[536,1229,1230,1244],{},[136,1231,1232,1237,1238,1240,1241,1243],{},[17,1233,1234,1236],{},[109,1235,913],{}," needs a recent Flutter."," Version 3.2.3, the last one on the old Android package, depended on ",[109,1239,1173],{}," ^0.4.0, which used Billing Library 7.1.1. To get version 8 through Flutter's own plugin, the app has to run on Flutter 3.38 or later. Flutter's release archive dates 3.38.0 November 12, 2025. Every ",[109,1242,1173],{}," release after 0.5.0 requires Flutter 3.44 or later, so on Flutter 3.38 to 3.43 pub can only use 0.5.0. My advice: if the app is on an older Flutter, plan the Flutter upgrade and the billing update as one job, because the upgrade can surface other build errors.",[136,1245,1246,1249],{},[17,1247,1248],{},"RevenueCat warns about consumables."," Its 9.0.0 notes say Billing Library 8 can no longer query expired subscriptions or consumed one-time products. If a lifetime purchase is set up as a consumable in the RevenueCat dashboard, RevenueCat will consume it, and users can't restore it. RevenueCat says to set those products up as non-consumables.",[31,1251,795],{"id":794},[14,1253,798],{},[133,1255,1256,1277,1283,1294,1300],{},[136,1257,1258,1261,1262,308,1265,1268,1269,727,1271,308,1273,1276],{},[17,1259,1260],{},"Find the version you ship."," In a native app, check ",[109,1263,1264],{},"com.android.billingclient:billing",[109,1266,1267],{},"build.gradle",". In Flutter, check ",[109,1270,1173],{},[109,1272,1214],{},[109,1274,1275],{},"pubspec.lock",", and compare with the table above.",[136,1278,1279,1282],{},[17,1280,1281],{},"Request the extension if you need time."," If you can't ship version 8 before your next update, use the form from the Play Console warning. Google's extension for version 7 ends on November 1, 2026, so as of October 18, 2026 it buys two weeks at most.",[136,1284,1285,1288,1289,1291,1292,358],{},[17,1286,1287],{},"Upgrade the package, then fix what broke."," Look for the removed calls in the version 8 table. In Flutter, replace ",[109,1290,1185],{}," with ",[109,1293,1189],{},[136,1295,1296,1299],{},[17,1297,1298],{},"Test purchases and restores before you ship."," Use Play Console license testers to buy, cancel and restore each product type, especially one-time products and anything users expect to restore after reinstalling.",[136,1301,1302,1305,1306,1309,1310,1313],{},[17,1303,1304],{},"Check the manifest if the warning stays."," Google says the merged ",[109,1307,1308],{},"AndroidManifest.xml"," must contain ",[109,1311,1312],{},"com.google.android.play.billingclient.version",". If it doesn't, check whether manifest merging removes it.",[31,1315,362],{"id":361},[14,1317,1318,1319,370,1321,358],{},"If an app can't ship an update because of the Billing Library deadline, or purchases broke after the upgrade, the ",[69,1320,369],{"href":368},[69,1322,374],{"href":373},{"title":167,"searchDepth":380,"depth":380,"links":1324},[1325,1326,1327,1328,1329],{"id":925,"depth":380,"text":926},{"id":1045,"depth":380,"text":1046},{"id":1148,"depth":380,"text":1149},{"id":794,"depth":380,"text":795},{"id":361,"depth":380,"text":362},"2026-10-18T23:30:00.000Z","Google Play Billing Library 7 hit its deadline on August 31, 2026: new apps and updates must use version 8 or later, and Google says its extension runs until November 1, 2026. What changed in version 8, which Flutter in_app_purchase and RevenueCat versions include it, and how to clear the Play Console warning, from Google's docs checked October 18, 2026.",[1333,1336,1339,1342,1345,1348],{"question":1334,"answer":1335},"When is Play Billing Library 7 deprecated?","Google's deprecation table sets August 31, 2026 as the deadline for new apps and updates on version 7, and November 1, 2026 as the extension deadline. Google's banner on the same page says that by August 31, 2026, new apps and updates must use version 8 or later.",{"question":1337,"answer":1338},"What happens if I don't update the Billing Library?","Google says existing apps still work and unmaintained APKs don't need updates, but new apps and updates must use a supported version. My reading: once your deadline passes, you can't publish an update to an app that uses version 7 or older.",{"question":1340,"answer":1341},"How do I get an extension to November 1, 2026?","Google says an app on an unsupported version gets a warning in Play Console. Open the warning's details on the Policy status page and use the extension form there. Google says the extension for version 7 runs until November 1, 2026.",{"question":1343,"answer":1344},"Which Flutter in_app_purchase version uses Billing Library 8?","in_app_purchase_android 0.5.0, published May 27, 2026, updated the Billing Library from 7.1.1 to 8.0.0. The in_app_purchase package depends on it from version 3.3.0, which requires Flutter 3.38 or later and Dart 3.10.",{"question":1346,"answer":1347},"I already updated. Why does Play Console still show the warning?","Google's FAQ says to check that your AndroidManifest.xml contains com.google.android.play.billingclient.version, and if it is missing, whether manifest merging removes it.",{"question":1349,"answer":1350},"Do I need to move to version 9?","Not for this deadline. Version 8 is supported until August 31, 2027, with an extension to November 1, 2027, per Google's table. Version 9 was released on May 19, 2026 and is supported a year longer.",{"readingTimeStats":1352},{"text":414,"minutes":1353,"time":1354,"words":1355},4.115,246900,823,"\u002Fblog\u002Fplay-billing-library-7-deprecated-update-to-8-2026","play billing library 7 deprecated",[1359,871,872],"revenuecat-stripe-firebase-monetization-stack-template369",{"title":900,"description":1331},[1362,1364,1367,1370,1373,1376],{"title":1363,"url":1012},"Android Developers, Google Play Billing Library version deprecation (last updated September 9, 2026)",{"title":1365,"url":1366},"Android Developers, Google Play Billing Library release notes","https:\u002F\u002Fdeveloper.android.com\u002Fgoogle\u002Fplay\u002Fbilling\u002Frelease-notes",{"title":1368,"url":1369},"pub.dev, in_app_purchase_android changelog","https:\u002F\u002Fpub.dev\u002Fpackages\u002Fin_app_purchase_android\u002Fchangelog",{"title":1371,"url":1372},"pub.dev, in_app_purchase versions","https:\u002F\u002Fpub.dev\u002Fpackages\u002Fin_app_purchase\u002Fversions",{"title":1374,"url":1375},"RevenueCat purchases-flutter changelog on GitHub","https:\u002F\u002Fgithub.com\u002FRevenueCat\u002Fpurchases-flutter\u002Fblob\u002Fmain\u002FCHANGELOG.md",{"title":442,"url":443},"blog\u002Fplay-billing-library-7-deprecated-update-to-8-2026","play billing library 7 deprecated, play billing library 8 migration, unsupported version of google play billing library, play console billing library warning, billing library extension november 1 2026, in_app_purchase_android billing 8, purchases_flutter billing library 8, querypurchasehistory removed, flutter in app purchase android update",[1380,1381,1382,1383,1384],"Every Google Play Billing Library version has a two-year deprecation cycle. For version 7, Google says the deadline for new apps and updates was August 31, 2026, and the extension deadline is November 1, 2026.","Version 8.0.0 (June 30, 2025) removed queryPurchaseHistory(), querySkuDetailsAsync(), the no-argument enablePendingPurchases() and the queryPurchasesAsync() overload that takes a SKU type, and changed the queryProductDetailsAsync() result.","Flutter's in_app_purchase_android moved to Billing Library 8.0.0 in version 0.5.0 (May 27, 2026). The app-facing in_app_purchase package uses it from 3.3.0, which needs Flutter 3.38 or later.","RevenueCat's purchases_flutter moved to Billing Library 8 in 9.0.0 (July 18, 2025). Its notes warn that one-time products wrongly set up as consumables can no longer be restored.","Google says existing apps keep working. The deadline applies to new apps and updates. My reading: an app on version 7 can't ship an update until it moves, once any extension runs out.","https:\u002F\u002Fapp369.com\u002Fblog\u002Fplay-billing-library-7-deprecated-update-to-8-2026\u002F","5n6ohencoIcRhkIOzQZqt84R1BDU1_moCs_avK-ktvg",{"id":1388,"title":1389,"author":1390,"body":1392,"category":390,"createdAt":1971,"description":1972,"disclosure":393,"extension":394,"faq":1973,"howTo":393,"lastVerified":393,"location":411,"meta":1989,"navigation":418,"ogImage":393,"path":1994,"primaryKeyword":1995,"readingTime":1996,"related":1997,"seo":1999,"sources":2000,"stem":2011,"tags":2012,"takeaways":2013,"updatedAt":1971,"url":2019,"__hash__":2020},"blog\u002Fblog\u002Fflutter-uiscene-migration-xcode-27-app-wont-launch-2026.md","Flutter UIScene Migration: Fix Launch Crashes on Xcode 27",{"name":7,"social":1391},{"twitter":9},{"type":11,"value":1393,"toc":1959},[1394,1412,1415,1420,1424,1531,1534,1537,1541,1558,1561,1565,1572,1576,1594,1669,1692,1696,1713,1727,1731,1742,1863,1881,1885,1901,1905,1908,1942,1944,1957],[14,1395,1396,1399,1400,1403,1404,1406,1407,187,1409,358],{},[17,1397,1398],{},"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 ",[109,1401,1402],{},"AppDelegate"," automatically. Apps with a custom ",[109,1405,1402],{},", or on an older Flutter, need a few manual changes to ",[109,1408,1402],{},[109,1410,1411],{},"Info.plist",[14,1413,1414],{},"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,1416,1417,1419],{},[17,1418,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,1421,1423],{"id":1422},"what-changed-and-when","What changed, and when",[36,1425,1426,1437],{},[39,1427,1428],{},[42,1429,1430,1432,1435],{},[45,1431,47],{},[45,1433,1434],{},"What happened",[45,1436,53],{},[55,1438,1439,1460,1478,1494,1509],{},[42,1440,1441,1444,1447],{},[60,1442,1443],{},"June 2025 (WWDC25)",[60,1445,1446],{},"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,1448,1449,1454,1455],{},[69,1450,1453],{"href":1451,"rel":1452},"https:\u002F\u002Fdocs.flutter.dev\u002Frelease\u002Fbreaking-changes\u002Fuiscenedelegate",[73],"Flutter docs",", ",[69,1456,1459],{"href":1457,"rel":1458},"https:\u002F\u002Fdeveloper.apple.com\u002Fdocumentation\u002Ftechnotes\u002Ftn3187-migrating-to-the-uikit-scene-based-life-cycle",[73],"Apple TN3187",[42,1461,1462,1465,1468],{},[60,1463,1464],{},"November 12, 2025",[60,1466,1467],{},"Flutter 3.38 adds UIScene support, with an experimental automatic migration",[60,1469,1470,1454,1474],{},[69,1471,1473],{"href":434,"rel":1472},[73],"Flutter 3.38 post",[69,1475,1477],{"href":443,"rel":1476},[73],"release archive",[42,1479,1480,1483,1486],{},[60,1481,1482],{},"February 11, 2026",[60,1484,1485],{},"Flutter 3.41: UIScene support is the default, and eligible apps are migrated automatically",[60,1487,1488,1454,1491],{},[69,1489,1453],{"href":1451,"rel":1490},[73],[69,1492,1477],{"href":443,"rel":1493},[73],[42,1495,1496,1499,1502],{},[60,1497,1498],{},"April 28, 2026",[60,1500,1501],{},"App Store Connect uploads must be built with Xcode 26 or later",[60,1503,1504],{},[69,1505,1508],{"href":1506,"rel":1507},"https:\u002F\u002Fdeveloper.apple.com\u002Fnews\u002Fupcoming-requirements\u002F",[73],"Apple upcoming requirements",[42,1510,1511,1516,1521],{},[60,1512,1513],{},[17,1514,1515],{},"September 14, 2026",[60,1517,1518],{},[17,1519,1520],{},"Xcode 27 released. Flutter apps built with it that haven't adopted UIScene fail to launch",[60,1522,1523,1454,1528],{},[69,1524,1527],{"href":1525,"rel":1526},"https:\u002F\u002Fdeveloper.apple.com\u002Fnews\u002Freleases\u002F",[73],"Apple releases",[69,1529,1453],{"href":1451,"rel":1530},[73],[14,1532,1533],{},"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,1535,1536],{},"Apple's technote says the requirement is to adopt the scene life cycle. Supporting multiple scenes is encouraged but not required.",[31,1538,1540],{"id":1539},"step-1-let-flutter-migrate-it","Step 1: let Flutter migrate it",[14,1542,1543,1544,1546,1547,727,1550,1553,1554,1557],{},"If the app is on Flutter 3.41 or later and its ",[109,1545,1402],{}," hasn't been customized, Flutter's docs say the CLI migrates it when you run ",[109,1548,1549],{},"flutter run",[109,1551,1552],{},"flutter build ios",". On success it prints ",[109,1555,1556],{},"Finished migration to UIScene lifecycle",". If it can't, it warns you and gives manual steps.",[14,1559,1560],{},"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,1562,1564],{"id":1563},"step-2-migrate-a-custom-appdelegate-by-hand","Step 2: migrate a custom AppDelegate by hand",[14,1566,1567,1568,358],{},"These steps follow Flutter's ",[69,1569,1571],{"href":1451,"rel":1570},[73],"UIScene page",[101,1573,1575],{"id":1574},"register-plugins-in-the-new-callback","Register plugins in the new callback",[14,1577,1578,1579,1582,1583,1585,1586,1589,1590,1593],{},"Plugins used to be registered in ",[109,1580,1581],{},"application:didFinishLaunchingWithOptions:",". Now the ",[109,1584,1402],{}," conforms to ",[109,1587,1588],{},"FlutterImplicitEngineDelegate"," and registers them in ",[109,1591,1592],{},"didInitializeImplicitFlutterEngine",":",[162,1595,1599],{"className":1596,"code":1597,"language":1598,"meta":167,"style":167},"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",[109,1600,1601,1606,1611,1616,1622,1628,1634,1640,1646,1652,1658,1663],{"__ignoreMap":167},[171,1602,1603],{"class":173,"line":174},[171,1604,1605],{},"@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {\n",[171,1607,1608],{"class":173,"line":380},[171,1609,1610],{},"  override func application(\n",[171,1612,1613],{"class":173,"line":385},[171,1614,1615],{},"    _ application: UIApplication,\n",[171,1617,1619],{"class":173,"line":1618},4,[171,1620,1621],{},"    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n",[171,1623,1625],{"class":173,"line":1624},5,[171,1626,1627],{},"  ) -> Bool {\n",[171,1629,1631],{"class":173,"line":1630},6,[171,1632,1633],{},"    return super.application(application, didFinishLaunchingWithOptions: launchOptions)\n",[171,1635,1637],{"class":173,"line":1636},7,[171,1638,1639],{},"  }\n",[171,1641,1643],{"class":173,"line":1642},8,[171,1644,1645],{"emptyLinePlaceholder":418},"\n",[171,1647,1649],{"class":173,"line":1648},9,[171,1650,1651],{},"  func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {\n",[171,1653,1655],{"class":173,"line":1654},10,[171,1656,1657],{},"    GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)\n",[171,1659,1661],{"class":173,"line":1660},11,[171,1662,1639],{},[171,1664,1666],{"class":173,"line":1665},12,[171,1667,1668],{},"}\n",[14,1670,1671,1672,1675,1676,1678,1679,1682,1683,308,1686,1688,1689,1691],{},"If you created method channels or platform views in ",[109,1673,1674],{},"didFinishLaunchingWithOptions",", move them into ",[109,1677,1592],{}," too, using ",[109,1680,1681],{},"engineBridge.applicationRegistrar.messenger()"," as the messenger. Flutter's docs warn that accessing the ",[109,1684,1685],{},"FlutterViewController",[109,1687,1674],{}," might crash your app, and say to use the ",[109,1690,1588],{}," protocol instead.",[101,1693,1695],{"id":1694},"move-ui-lifecycle-code-to-a-scene-delegate","Move UI lifecycle code to a scene delegate",[14,1697,1698,1699,1701,1702,1705,1706,1709,1710,358],{},"After the migration, UIKit no longer calls the ",[109,1700,1402],{}," methods tied to UI state, such as ",[109,1703,1704],{},"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 ",[109,1707,1708],{},"FlutterSceneDelegate"," or conform to ",[109,1711,1712],{},"FlutterSceneLifeCycleProvider",[14,1714,1715,1716,1718,1719,1722,1723,1726],{},"Flutter's page adds, in its plugin section, that after the migration the launch options passed to ",[109,1717,1674],{}," are ",[109,1720,1721],{},"nil",", and that logic relying on them moves to ",[109,1724,1725],{},"scene:willConnectToSession:options:",". My advice: look first at code that handles a notification or a URL the app was opened with.",[101,1728,1730],{"id":1729},"add-the-scene-manifest-to-infoplist","Add the scene manifest to Info.plist",[14,1732,1733,1734,1737,1738,1741],{},"Add this inside the top-level ",[109,1735,1736],{},"\u003Cdict>"," of ",[109,1739,1740],{},"ios\u002FRunner\u002FInfo.plist",", as shown on Flutter's page:",[162,1743,1747],{"className":1744,"code":1745,"language":1746,"meta":167,"style":167},"language-xml shiki shiki-themes github-light github-dark","\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","xml",[109,1748,1749,1754,1759,1764,1769,1774,1779,1784,1789,1794,1799,1804,1809,1815,1821,1827,1833,1839,1845,1851,1857],{"__ignoreMap":167},[171,1750,1751],{"class":173,"line":174},[171,1752,1753],{},"\u003Ckey>UIApplicationSceneManifest\u003C\u002Fkey>\n",[171,1755,1756],{"class":173,"line":380},[171,1757,1758],{},"\u003Cdict>\n",[171,1760,1761],{"class":173,"line":385},[171,1762,1763],{},"  \u003Ckey>UIApplicationSupportsMultipleScenes\u003C\u002Fkey>\n",[171,1765,1766],{"class":173,"line":1618},[171,1767,1768],{},"  \u003Cfalse\u002F>\n",[171,1770,1771],{"class":173,"line":1624},[171,1772,1773],{},"  \u003Ckey>UISceneConfigurations\u003C\u002Fkey>\n",[171,1775,1776],{"class":173,"line":1630},[171,1777,1778],{},"  \u003Cdict>\n",[171,1780,1781],{"class":173,"line":1636},[171,1782,1783],{},"    \u003Ckey>UIWindowSceneSessionRoleApplication\u003C\u002Fkey>\n",[171,1785,1786],{"class":173,"line":1642},[171,1787,1788],{},"    \u003Carray>\n",[171,1790,1791],{"class":173,"line":1648},[171,1792,1793],{},"      \u003Cdict>\n",[171,1795,1796],{"class":173,"line":1654},[171,1797,1798],{},"        \u003Ckey>UISceneClassName\u003C\u002Fkey>\n",[171,1800,1801],{"class":173,"line":1660},[171,1802,1803],{},"        \u003Cstring>UIWindowScene\u003C\u002Fstring>\n",[171,1805,1806],{"class":173,"line":1665},[171,1807,1808],{},"        \u003Ckey>UISceneDelegateClassName\u003C\u002Fkey>\n",[171,1810,1812],{"class":173,"line":1811},13,[171,1813,1814],{},"        \u003Cstring>FlutterSceneDelegate\u003C\u002Fstring>\n",[171,1816,1818],{"class":173,"line":1817},14,[171,1819,1820],{},"        \u003Ckey>UISceneConfigurationName\u003C\u002Fkey>\n",[171,1822,1824],{"class":173,"line":1823},15,[171,1825,1826],{},"        \u003Cstring>flutter\u003C\u002Fstring>\n",[171,1828,1830],{"class":173,"line":1829},16,[171,1831,1832],{},"        \u003Ckey>UISceneStoryboardFile\u003C\u002Fkey>\n",[171,1834,1836],{"class":173,"line":1835},17,[171,1837,1838],{},"        \u003Cstring>Main\u003C\u002Fstring>\n",[171,1840,1842],{"class":173,"line":1841},18,[171,1843,1844],{},"      \u003C\u002Fdict>\n",[171,1846,1848],{"class":173,"line":1847},19,[171,1849,1850],{},"    \u003C\u002Farray>\n",[171,1852,1854],{"class":173,"line":1853},20,[171,1855,1856],{},"  \u003C\u002Fdict>\n",[171,1858,1860],{"class":173,"line":1859},21,[171,1861,1862],{},"\u003C\u002Fdict>\n",[14,1864,1865,1866,1869,1870,1872,1873,1876,1877,1880],{},"If you made your own scene delegate subclass, Flutter's page says to put its name in ",[109,1867,1868],{},"UISceneDelegateClassName"," instead of ",[109,1871,1708],{},": ",[109,1874,1875],{},"$(PRODUCT_MODULE_NAME).SceneDelegate"," for Swift projects, ",[109,1878,1879],{},"SceneDelegate"," for Objective-C.",[31,1882,1884],{"id":1883},"plugins-and-add-to-app","Plugins and add-to-app",[536,1886,1887,1893],{},[136,1888,1889,1892],{},[17,1890,1891],{},"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.",[136,1894,1895,1898,1899,358],{},[17,1896,1897],{},"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 ",[109,1900,1708],{},[31,1902,1904],{"id":1903},"what-to-test","What to test",[14,1906,1907],{},"This section is my advice, not Flutter's or Apple's.",[133,1909,1910,1916,1925,1936],{},[136,1911,1912,1915],{},[17,1913,1914],{},"Build with Xcode 27 and launch on a device."," If it launches, open each screen once.",[136,1917,1918,1921,1922,1924],{},[17,1919,1920],{},"Cold start from a push notification and from a deep link."," Launch options are ",[109,1923,1721],{}," after the migration, so these are the paths most likely to break.",[136,1926,1927,1930,1931,727,1933,358],{},[17,1928,1929],{},"Background and foreground the app."," Check anything that used to run in ",[109,1932,1704],{},[109,1934,1935],{},"applicationWillResignActive",[136,1937,1938,1941],{},[17,1939,1940],{},"Ship through TestFlight first."," Check the same paths on a build installed the way users get it.",[31,1943,362],{"id":361},[14,1945,1946,1947,1949,1950,1954,1955,358],{},"If a Flutter iOS app won't launch after building with Xcode 27, or broke after the UIScene migration, the ",[69,1948,369],{"href":368}," 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 ",[69,1951,1953],{"href":1952},"\u002Fblog\u002Fflutter-ios-build-failed-after-upgrade-2026\u002F","Flutter iOS build failed after an upgrade",", or ",[69,1956,374],{"href":373},[376,1958,378],{},{"title":167,"searchDepth":380,"depth":380,"links":1960},[1961,1962,1963,1968,1969,1970],{"id":1422,"depth":380,"text":1423},{"id":1539,"depth":380,"text":1540},{"id":1563,"depth":380,"text":1564,"children":1964},[1965,1966,1967],{"id":1574,"depth":385,"text":1575},{"id":1694,"depth":385,"text":1695},{"id":1729,"depth":385,"text":1730},{"id":1883,"depth":380,"text":1884},{"id":1903,"depth":380,"text":1904},{"id":361,"depth":380,"text":362},"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.",[1974,1977,1980,1983,1986],{"question":1975,"answer":1976},"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":1978,"answer":1979},"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":1981,"answer":1982},"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":1984,"answer":1985},"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":1987,"answer":1988},"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":1990},{"text":414,"minutes":1991,"time":1992,"words":1993},4.405,264300,881,"\u002Fblog\u002Fflutter-uiscene-migration-xcode-27-app-wont-launch-2026","flutter uiscene migration","8 min",[1998,423,872],"flutter-ios-build-failed-after-upgrade-2026",{"title":1389,"description":1972},[2001,2003,2005,2007,2009,2010],{"title":2002,"url":1451},"Flutter docs, UIScene adoption (last updated September 14, 2026)",{"title":2004,"url":1457},"Apple Developer, TN3187: Migrating to the UIKit scene-based life cycle",{"title":2006,"url":1506},"Apple Developer, Upcoming requirements",{"title":2008,"url":1525},"Apple Developer, Releases",{"title":433,"url":434},{"title":442,"url":443},"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",[2014,2015,2016,2017,2018],"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",[2022,2024,2025,2028,2031,2034],{"keyword":5,"url":452,"title":5,"relevance":2023},75,{"keyword":457,"url":896,"title":457,"relevance":1859},{"keyword":2026,"url":2027,"title":2026,"relevance":1660},"JCenter Shutdown: Fixing Old Android and Flutter Builds","https:\u002F\u002Fapp369.com\u002Fblog\u002Fjcenter-bintray-shut-down-fix-android-flutter-builds-2026\u002F",{"keyword":2029,"url":2030,"title":2029,"relevance":1648},"Flutter \"Deleted Android v1 Embedding\" Build Error: The Fix","https:\u002F\u002Fapp369.com\u002Fblog\u002Fflutter-deleted-android-v1-embedding-build-failed-2026\u002F",{"keyword":2032,"url":2033,"title":2032,"relevance":1648},"Android Developer Verification: Dates and What to Do","https:\u002F\u002Fapp369.com\u002Fblog\u002Fandroid-developer-verification-requirement-2026\u002F",{"keyword":2035,"url":2036,"title":2035,"relevance":1648},"Android Things Shut Down: What to Run Your Device App On in 2026","https:\u002F\u002Fapp369.com\u002Fblog\u002Fandroid-things-shut-down-device-app-alternatives-2026\u002F",1792358634475]