NewiPhone Duo, live in your browser. Try it →
Vibeview
Pricing
Cloud Builds · Flutter

Build a Flutter iOS and Android app without a Mac

Rokas Kašinskas — Co-founder, VibeViewPublished 2026-10-16Updated 2026-10-16

A Flutter app targets two platforms from one codebase, but building it still means two toolchains: Xcode on a Mac for iOS, and the Android SDK with a JDK for Android. VibeView cloud builds run both for you. The CLI uploads your project source, the build runs in a clean environment, and the finished build lands next to your app, ready to run on a device you open in a browser tab.

This guide takes one Flutter app from source to a running build on both platforms, then to a signed Android release. It works the same from Windows, Linux or macOS.

What you need

  • A VibeView account and the CLI: npm install -g vibeview && vibeview login. CLI 0.42.0 or later suggests the Flutter commands; on an older CLI, type them in when it asks.
  • A Flutter app, with its ios/ and android/ folders checked in (the ones flutter create makes).

You don’t need Flutter, Xcode or the Android SDK locally for the cloud builds. Every plan includes cloud builds each month; builds beyond your plan’s allowance draw from usage credit. The pricing page has each plan’s numbers.

Part 1: debug builds on cloud devices

  1. Start the builds from your project root.

    vibeview build --cloud --platform all

    The first run asks for each platform’s build command and where the result lands, and saves the answers to vibeview.json. For a Flutter project the CLI suggests:

    {
      "defaultPlatform": "android",
      "platforms": {
        "android": {
          "build": {
            "command": "flutter build apk --debug",
            "artifact": "build/app/outputs/flutter-apk/app-debug.apk"
          }
        },
        "ios": {
          "build": {
            "command": "flutter build ios --simulator --debug",
            "artifact": "build/ios/iphonesimulator/Runner.app"
          }
        }
      }
    }

    --simulator is what makes the iOS build installable: without it Flutter builds for a physical iPhone, and that build can’t run on a simulator. There’s no install step, because flutter build fetches your packages itself. It also regenerates the files Flutter’s own .gitignore leaves out, such as the Android Gradle wrapper.

  2. Watch the logs. The CLI packs every file git tracks plus untracked files that .gitignore doesn’t exclude, uploads them, and streams each build’s output. The log starts with the toolchain versions, including the Flutter release the builder has. Add --no-wait to start the builds and leave; vibeview builds logs <id> --follow picks one back up.

  3. Run them. A succeeded build lands in the app’s Build history with a cloud badge. If the project had no app yet, the build creates one from the binary (name, bundle id and icon included) and the CLI writes its appId into vibeview.json. Open the build’s page and choose Run this build to start it on a cloud iPhone or Android emulator.

You’ll know it worked when the build page shows added to app builds on its timeline and the app opens on the device. A Flutter debug build runs there as it is: it doesn’t need flutter run or a debugger attached, so you can share it as a link, record tests on it, or let your coding agent tap through it.

Part 2: a signed .aab for Google Play

A production build is a different artifact with a different job: it is signed with your release key, it’s meant for the store, and it doesn’t install on a VibeView device. It shows up on the Builds page with a Download action instead of in Build history.

  1. Get a keystore. Upload the one you have with vibeview credentials add --platform android --file release.jks, or let VibeView make one with vibeview credentials generate --platform android --name release.

  2. Point Gradle at it. Flutter’s android/app/build.gradle.kts signs release builds with the debug key until you change it. Add this block at the end of its android { } section. VibeView sets the four properties only during a production build, so your local builds keep working as before:

    if (project.hasProperty("VIBEVIEW_STORE_FILE")) {
        signingConfigs {
            create("vibeview") {
                storeFile = file(project.property("VIBEVIEW_STORE_FILE") as String)
                storePassword = project.property("VIBEVIEW_STORE_PASSWORD") as String
                keyAlias = project.property("VIBEVIEW_KEY_ALIAS") as String
                keyPassword = project.property("VIBEVIEW_KEY_PASSWORD") as String
            }
        }
        buildTypes.getByName("release").signingConfig = signingConfigs.getByName("vibeview")
    }
  3. Build the release.

    vibeview build --cloud --production --platform android

    The first run offers flutter build appbundle --release, with the artifact at build/app/outputs/bundle/release/app-release.aab. Then vibeview submit --platform android --latest --track internal uploads it to Google Play; the Android cloud build guide covers the one-time Play Console setup.

Google Play refuses an upload that reuses a version code, and Flutter takes the code from the + part of version: in pubspec.yaml. Raise it before each release, or pass the number on the command line: with autoIncrement set, VibeView hands every production build the next number as VIBEVIEW_BUILD_NUMBER, so flutter build appbundle --release --build-number=$VIBEVIEW_BUILD_NUMBER uses it.

The CLI suggests no iOS production command for Flutter, so write your own. Flutter’s .gitignore leaves out files the iOS build needs, so the command starts with flutter build ios --config-only --release to regenerate them, runs pod install in ios/ if there’s a Podfile, then archives ios/Runner.xcworkspace with the signing settings App Signing lists.

When your project needs another Flutter release

The builders have a default Flutter release and a second one ready, and the Cloud Builds docs say which. They also have FVM. If your project pins its release in a committed .fvmrc, run Flutter as fvm flutter in the build command (fvm flutter build apk --debug), and the build uses the pinned release. With CLI 0.43.0 and later, the first vibeview build --cloud suggests those commands for you; a project set up earlier keeps its saved flutter build ... command until you change it in vibeview.json.

Without FVM, a project whose pubspec.yaml asks for a different Dart SDK fails with The current Dart SDK version is ... and version solving failed. Name the Flutter release you need in the build command:

fvm spawn 3.44.9 build apk --debug

Replace 3.44.9 with your release. A release the builders don’t have ready is downloaded during the build, which adds about two minutes, and on Android it may also download its own Android NDK and Gradle.

Troubleshooting

  • version solving failed and a Dart SDK version. Your project needs a different Flutter release than the builders’ default. Pin it with FVM or name it in the build command, as shown above.
  • The iOS build fails on code signing, or its artifact isn’t found. The command has no --simulator, so Flutter tried a device build, which needs signing and lands in build/ios/iphoneos/. Add the flag.
  • An artifact isn’t found on either platform. Run vibeview build from the project root, where pubspec.yaml is. The artifact paths start there.
  • Google Play says the bundle was signed in debug mode. The signing block above is missing, or sits before Flutter’s own buildTypes block, which then sets the debug key again.

Frequently asked questions

Frequently asked questions

Can I build a Flutter iOS app without a Mac?

Yes. The iOS cloud build runs on a macOS builder with Xcode and Flutter installed, and the simulator build it makes opens on a cloud iPhone in your browser. You still need an Apple Developer account to sign and publish a production build.

Do I need Flutter installed locally?

Not for cloud builds. The CLI reads your pubspec.yaml to recognize the project and uploads the source; the builders run flutter build. You’ll still want Flutter locally to develop the app.

Can I build for Apple TV or Android TV?

Flutter doesn’t support Apple TV. For Android TV the CLI suggests no development build command, so enter your own. Flutter builds no 32-bit x86 code, and VibeView’s Android TV devices are a mix of x86 and x86_64, so a Flutter app runs only on the x86_64 ones.

Next steps

Try it yourself

Open a live iOS simulator or Android emulator in your browser.

Start free