You bought a Flutter template, swapped the logo, and ran it on your phone. Then you open android/app/build.gradle.kts and the app is still called com.example.something, or worse, the original author's ID. Before anything goes to Google Play or the App Store, you need to change the Flutter package name to one you own. This article walks through every file involved, in order, and what to check after each step.
Before you start: you only get to pick this once
On Android the ID is the applicationId. Google is blunt about it: once you publish, you should never change it, and if you do, Google Play treats the upload as a completely different app. On iOS the bundle ID can't be changed in App Store Connect after you upload a build. So choose it now, deliberately.
The usual pattern is reverse domain: com.yourcompany.yourapp. Android's rules are stricter than they look: at least two segments separated by dots, each segment starting with a letter, and only letters, digits and underscores. No hyphens.
If you haven't settled the app name, brand colours and accounts yet, go through the app reskin checklist first. The package name is one item on it, and it's easier to decide alongside the rest.
The names involved, and the one to leave alone
Five different things get called the package name in a Flutter project. Four of them change; one stays.
| Name | Where it lives | What it does | Change it? |
|---|---|---|---|
applicationId |
android/app/build.gradle.kts (or build.gradle) |
The ID Google Play and Android devices use to identify the app | Yes |
namespace |
Same file, android block |
Kotlin/Java package for generated classes like R and BuildConfig |
Yes, keep it equal to applicationId |
MainActivity package |
android/app/src/main/kotlin/... or .../java/... |
The package line and folder path of the activity Flutter starts |
Yes, must match namespace |
PRODUCT_BUNDLE_IDENTIFIER |
ios/Runner.xcodeproj/project.pbxproj |
The iOS bundle ID | Yes |
name: |
pubspec.yaml |
The Dart package name used in package: imports |
Usually no (see below) |
Android lets namespace and applicationId differ, but recommends keeping them the same. One detail matters here: if applicationId isn't set explicitly, it takes the namespace value, so changing one silently changes the other.
Step 1: Commit or back up the project
Commit the untouched template to Git (or copy the folder) so you can diff every change and roll back if the build breaks.
git init
git add .
git commit -m "Template as purchased"
Step 2: Change the Flutter package name in Gradle
Open android/app/build.gradle.kts. Current Flutter templates use the Kotlin DSL; older projects have android/app/build.gradle (Groovy) instead. Change both values to your new ID:
android {
namespace = "com.yourcompany.yourapp"
defaultConfig {
applicationId = "com.yourcompany.yourapp"
// minSdk, targetSdk, versionCode etc. stay as they are
}
}
In a Groovy build.gradle the syntax is namespace "com.yourcompany.yourapp" and applicationId "com.yourcompany.yourapp".
Step 3: Move MainActivity and fix its package line
Flutter's own deployment docs say that when you change applicationId and namespace, you must also update the package statement in MainActivity and move the file into the matching folder.
Check which folder your template uses: android/app/src/main/kotlin/ or android/app/src/main/java/. For Kotlin, the result should be:
android/app/src/main/kotlin/com/yourcompany/yourapp/MainActivity.kt
with this first line:
package com.yourcompany.yourapp
Then delete the old, now empty folders (com/example/... or whatever the author used). If the template has other native Kotlin or Java files in that package, move them too and update their package lines.
Step 4: Search for the old ID everywhere else
Templates hide the old ID in places you won't think of: an older AndroidManifest.xml with a package attribute, deep-link intent filters, a ProGuard rules file, a method channel name, or a hardcoded string in Dart. Search the whole project for it:
grep -rn "com.example.oldapp" --exclude-dir=build --exclude-dir=.dart_tool .
On Windows PowerShell, Select-String does the same job:
Get-ChildItem -Recurse -File | Where-Object { $_.FullName -notmatch '\\build\\|\\.dart_tool\\' } | Select-String "com.example.oldapp"
Replace each hit unless it's clearly unrelated. If you find package="..." in AndroidManifest.xml, remove that attribute. Android Gradle Plugin 8.0 and later requires the namespace to be set in the build file, not the manifest.
Step 5: Change the iOS bundle identifier
The easiest route is Xcode. Open the workspace (not the project):
open ios/Runner.xcworkspace
Select the Runner target, go to General, and set Bundle Identifier under Identity. The value must match the bundle ID you register in your Apple Developer account under App IDs, and the one you pick when creating the app record in App Store Connect.
If you're not on a Mac yet, you can edit ios/Runner.xcodeproj/project.pbxproj in a text editor. A project generated by flutter create has six PRODUCT_BUNDLE_IDENTIFIER lines: three for the Runner target (Debug, Release, Profile) and three for the RunnerTests target, which carry a .RunnerTests suffix:
PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.yourapp;
PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.yourapp.RunnerTests;
Keep the suffix on the test target. Also open ios/Runner/Info.plist: if CFBundleIdentifier holds a literal ID instead of $(PRODUCT_BUNDLE_IDENTIFIER), change it by hand. Stacklyn's mobile templates target Android and iOS only; if your project also ships macos/ or linux/, the Step 4 search shows where their IDs live.
Step 6: Regenerate Firebase config, if your app uses Firebase
None of Stacklyn's Flutter product pages lists Firebase as a dependency, so for our templates this step usually doesn't apply. It does if you added Firebase yourself or bought a template that ships google-services.json or GoogleService-Info.plist.
Firebase ties each registered app to its package name, and that name can't be changed after registration. Register new Android and iOS apps with the new IDs in the Firebase console, run flutterfire configure again and select them, then check that lib/firebase_options.dart and any Firebase config files reference the new IDs.
Optional: let a package do the edits
Two packages on pub.dev automate parts of this. Neither does everything, so still run the search from Step 4 afterwards.
change_app_package_name |
rename |
|
|---|---|---|
| Version checked | 1.5.0 (Feb 2025) | 3.1.0 (May 2025) |
| Android | Replaces the old applicationId string throughout the Gradle file, updates manifests, moves MainActivity |
Rewrites the applicationId line only; no namespace, no MainActivity move |
| iOS | Replaces the old bundle ID in project.pbxproj |
Sets every PRODUCT_BUNDLE_IDENTIFIER line to one value |
| Known limits | Custom CFBundleIdentifier in Info.plist isn't updated |
Author warns it may not work with flavors |
Usage for each:
flutter pub add -d change_app_package_name
dart run change_app_package_name:main com.yourcompany.yourapp
flutter pub global activate rename
rename setBundleId --targets android,ios --value "com.yourcompany.yourapp"
Two things to check after either tool. From reading change_app_package_name's source, namespace only changes if it held the same string as the old applicationId (it does in a fresh Flutter project, but templates vary). And rename's iOS editor writes the same value into every bundle ID line, which can strip the .RunnerTests suffix; put it back by hand.
Step 7: Clean, rebuild and test on a real device
Old build output still contains the previous ID, so clear it first:
flutter clean
flutter pub get
flutter run
Test on a physical phone. Because the ID changed, Android installs it as a separate app next to the old one; uninstall the old copy. Open every screen that uses a plugin (notifications, file storage, sharing), since that's where a missed ID shows up. Then run flutter build appbundle, and flutter build ipa on a Mac, to confirm release builds work too.
Why the Dart package name usually stays
The name: field in pubspec.yaml is the Dart package name. Every file in the template that imports another file with import 'package:<name>/...' depends on it. Change it and each of those imports breaks until you rewrite them all.
Users never see this name, and neither store reads it; they use applicationId and the bundle ID. Leave it alone unless you have a specific reason, and if you do change it, use only lowercase letters, digits and underscores, then find and replace every package:oldname/ import in lib/ and test/.
Renaming touches Gradle, the manifest, Kotlin folders and Xcode, and a single missed line usually means an evening of reading build errors. If you'd rather not, we change the package name and bundle ID as part of a Flutter app reskin, along with signing and the rest of the branding.
Troubleshooting
Build fails with "Namespace not specified". The namespace line is missing from android/app/build.gradle.kts. Add it inside the android block (Step 2). This happens after deleting the manifest package attribute without adding the namespace.
App installs, then crashes on launch with a class-not-found error naming MainActivity. The package line in MainActivity.kt doesn't match namespace, or the file is still in the old folder. Recheck Step 3.
Build fails with "No matching client found for package name". This comes from the Google services Gradle plugin: your google-services.json doesn't contain the new ID. Register the new ID in Firebase and replace the file (Step 6). If you use a build flavor or an ID suffix, the JSON must contain that suffixed ID too.
Xcode reports a signing or provisioning error. The bundle ID in Xcode doesn't match one registered in your Apple Developer account, or the selected team doesn't own it. Register the ID under App IDs and select your team in Signing & Capabilities.
iOS tests fail to build after using a rename tool. Check the three RunnerTests lines in project.pbxproj and restore the .RunnerTests suffix.
Push notifications or analytics stop with no error. Usually a Firebase app still registered under the old ID. Repeat Step 6.
If something here doesn't match what you see in your template, the Stacklyn Help Center has the other setup guides for our products.