Muse AI docs
v2.0.0
Live demoConsole demo Get help
● Ship · Android and iOS

Release build.
Your ids, your signing, the store checklist.

What to change before your first upload, how to sign the Android and iOS builds, and what the stores ask of an AI chat app. A release build is the file you upload to Google Play or the App Store. Do the ids first: Firebase and the stores register your app under them.

Replace com.mikodes.museaikey.propertiesYour Xcode teamcheck_ad_ids.sh --release

01Ids to replace before publishing

WhatWhere
Application id / bundle id com.mikodes.museaiAndroid: namespace and applicationId in android/app/build.gradle.kts, and move android/app/src/main/kotlin/com/mikodes/museai/MainActivity.kt to the folder of your id with the matching package line. iOS: Xcode → Runner target → General → Bundle Identifier (PRODUCT_BUNDLE_IDENTIFIER; the test target uses <your id>.RunnerTests). Then run flutterfire configure again, which rewrites lib/firebase_options.dart.
App name under the iconandroid:label in AndroidManifest.xml, CFBundleDisplayName in Info.plist, web/index.html, web/manifest.json
Icons/usr/bin/python3 tool/gen_icons.py or your own PNGs (Customization)
Google sign-in URL scheme (iOS)ios/Runner/Info.plist → CFBundleURLTypes: replace com.googleusercontent.apps.REPLACE-WITH-YOUR-REVERSED-CLIENT-ID with your REVERSED_CLIENT_ID (iOS sign-in)
AdMob app idsAndroidManifest.xml and Info.plist (Ads), then tool/check_ad_ids.sh --release
Store product idsSet in the console, not in the code: plan products on Plans (example plan pro_monthly, pro_yearly), and remove_ads, credits_small, credits_medium, credits_large on Store & purchases (In-app purchases)
Versionversion: 2.0.0+200 in pubspec.yaml (name + build number). Raise the build number for every upload.

If you publish this as an update of an app you already have in the stores, keep your existing ids instead (Upgrading from 1.x).

02Android signing

  1. Create an upload key(once, keep it and its passwords safe; losing it blocks updates until Google resets it):
    keytool -genkey -v -keystore android/app/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload

    Terminal: macOS or Linux as shown; on Windows use WSL or Git Bash (how).

  2. Create app/android/key.properties(git-ignored, never commit it):
    storePassword=<your store password>
    keyPassword=<your key password>
    keyAlias=upload
    storeFile=upload-keystore.jks
  3. Build
    flutter build appbundle --release --dart-define=API_BASE_URL=https://<region>-<project-id>.cloudfunctions.net/api

    Terminal: macOS or Linux as shown; on Windows use WSL or Git Bash (how).

    The bundle is in build/app/outputs/bundle/release/.

build.gradle.kts signs release builds with key.properties. Without the file it falls back to the debug key: fine for flutter run --release, but Google Play refuses such a build.

Google sign-in on Android needs the SHA-1 and SHA-256 fingerprints of your keys in Firebase console → Project settings → your Android app (add the upload key and, after the first upload, the app signing key from Play Console → Setup → App signing). Print the upload key's with keytool -list -v -keystore android/app/upload-keystore.jks -alias upload.

03iOS signing and capabilities

  1. Open the workspaceopen ios/Runner.xcworkspace (not the .xcodeproj).
  2. TeamRunner target → Signing & Capabilities → pick your own team. The source ships without one.
  3. CapabilitiesAdd Push Notifications (Background Modes → Remote notifications is already in Info.plist) and, if Apple sign-in is on, Sign in with Apple. Sign in with Apple also needs the Apple provider configured in Firebase Authentication.
  4. Build
    flutter build ipa --release --dart-define=API_BASE_URL=https://<region>-<project-id>.cloudfunctions.net/api

    Terminal: macOS or Linux as shown; on Windows use WSL or Git Bash (how).

    Upload the .ipa from build/ios/ipa/ with Xcode's Organizer or Transporter. iOS builds need a Mac.

04iOS sign-in: Google URL scheme and Apple

On iOS the app signs in with Google through Firebase Authentication (signInWithProvider): a Google sign-in page opens and then returns to the app through a URL scheme. Without your scheme in Info.plist the page cannot return and Google sign-in fails or crashes. Android needs no URL scheme (it needs the SHA fingerprints above).

  1. Enable Google firstFirebase console → Authentication → Sign-in method → Google → Enable (Installation). Enabling it creates the iOS OAuth client. If you ran flutterfire configure before that, run it again so that ios/Runner/GoogleService-Info.plist contains the client.
  2. Copy REVERSED_CLIENT_IDOpen app/ios/Runner/GoogleService-Info.plist (any text editor, or Xcode) and copy the value of the key REVERSED_CLIENT_ID. It looks like com.googleusercontent.apps.1234567890-abcdefg. The same file is also in Firebase console → Project settings → General → your iOS app → GoogleService-Info.plist (download).
  3. Paste it into Info.plistOpen app/ios/Runner/Info.plist, find CFBundleURLTypes (the entry named google-sign-in) and replace the placeholder com.googleusercontent.apps.REPLACE-WITH-YOUR-REVERSED-CLIENT-ID with your value. Keep only one value per line; the source ships with this placeholder and no real id.
  4. Or in XcodeThe same entry is in Xcode → Runner target → Info tab → URL Types → the entry with identifier google-sign-in → URL Schemes. Editing it there writes the same Info.plist.
  5. If your file has no REVERSED_CLIENT_IDGoogle is not enabled in Firebase yet, or the plist is older than that: do step 1 and download it again. Firebase also accepts the iOS app's Encoded App ID (Firebase console → Project settings → your iOS app, it starts with app-1-) as the URL scheme; add it as a second string under CFBundleURLSchemes if Firebase asks for it in an error message.
  6. CheckBuild, tap Continue with Google: the Google page opens and comes back to the app signed in. "Custom URL scheme ... is not registered" in the Xcode console means the value does not match REVERSED_CLIENT_ID.

Sign in with Apple needs no URL scheme on iOS: it uses Apple's native sheet. It needs the Sign in with Apple capability (Runner target → Signing & Capabilities, see above) and the Apple provider enabled in Firebase Authentication. E-mail and password sign-in needs nothing on iOS. The app opens no other app by URL scheme, so LSApplicationQueriesSchemes is not needed.

05Push notifications

  • iOS: create an APNs authentication key (Apple Developer → Certificates, IDs & Profiles → Keys, enable Apple Push Notifications service) and upload it in Firebase console → Project settings → Cloud Messaging → your iOS app.
  • Android: no extra step; google-services.json from flutterfire configure is enough.
  • The app registers its token with the backend and subscribes to the topics all and pro (any plan) or free. Campaigns from the console go to those topics.

06Permission texts (iOS)

Info.plist carries the texts iOS shows when the app asks for access: microphone and speech recognition (dictation, voice mode, voice notes, recordings), camera and photo library (attachments, importing videos, saving images and exported videos), and tracking (ads consent). Adjust the wording to your app; keep them accurate, because App Review checks them.

07Store checklist for an AI chat and image app

  • tool/check_ad_ids.sh --release passes (or you do not use AdMob).
  • The build uses your API_BASE_URL and not DEMO_MODE.
  • Console: Terms and Privacy URLs set, Status has no blockers, at least one free model live.
  • Age rating in both stores matches the console's Minimum age (default 17+, the App Store rating for unrestricted AI chat). The in-app age check is a self-confirmation checkbox; do not describe it as age verification in your listing.
  • Video export, auto captions and natural voices tested on a real Android and iOS device (export does not run on the web).
  • Your privacy policy names the AI, voice and video providers you use, says conversations stay on the device and that message text, prompts and audio are forwarded to the provider, that image and video prompts are stored with the generated files, and describes what account deletion keeps (Privacy).
  • App Store privacy labels and the Google Play Data safety form match: user id, purchase history, usage data, and advertising data if ads are on.
  • Report button and review queue in place (they are): stores expect a way to report AI content and your review of reports.
  • Account deletion inside the app (Settings → Delete account) is present, as both stores require.
  • App name, icon and store texts use no third-party AI trademark.
  • If you sell plans or credits: products created, verification set up (In-app purchases), Restore purchases works.
  • If Discover is on: you checked each enabled feed publisher's terms (Discover).