Skip to content

iOS Setup

Oguzhan Atalay edited this page Jan 24, 2026 · 1 revision

iOS Setup (CarPlay)

Prerequisites

  • Xcode 14+
  • iOS 14.0+ deployment target
  • CarPlay entitlement from Apple (required for App Store)

⚠️ You need to request a CarPlay entitlement from Apple before submitting to the App Store. For development and testing, you can use the CarPlay Simulator.

Step 1: Update Info.plist

Add the CarPlay scene configuration to your ios/Runner/Info.plist:

<key>UIApplicationSceneManifest</key>
<dict>
  <key>UIApplicationSupportsMultipleScenes</key>
  <true/>
  <key>UISceneConfigurations</key>
  <dict>
    <!-- CarPlay Scene -->
    <key>CPTemplateApplicationSceneSessionRoleApplication</key>
    <array>
      <dict>
        <key>UISceneConfigurationName</key>
        <string>CarPlay Configuration</string>
        <key>UISceneDelegateClassName</key>
        <string>flutter_carplay.FlutterCarPlaySceneDelegate</string>
      </dict>
    </array>
    <!-- Main App Scene -->
    <key>UIWindowSceneSessionRoleApplication</key>
    <array>
      <dict>
        <key>UISceneConfigurationName</key>
        <string>Default Configuration</string>
        <key>UISceneDelegateClassName</key>
        <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
        <key>UISceneStoryboardFile</key>
        <string>Main</string>
      </dict>
    </array>
  </dict>
</dict>

Step 2: Create SceneDelegate.swift

Create ios/Runner/SceneDelegate.swift:

import UIKit
import Flutter

@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = scene as? UIWindowScene else { return }

        window = UIWindow(windowScene: windowScene)
        
        let controller = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
        window?.rootViewController = controller
        window?.makeKeyAndVisible()
    }
}

Step 3: Update AppDelegate.swift

Update your ios/Runner/AppDelegate.swift to use a shared Flutter engine:

import UIKit
import Flutter

// Global Flutter engine for sharing between app and CarPlay
let flutterEngine = FlutterEngine(name: "SharedEngine", project: nil, allowHeadlessExecution: true)

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // Start the Flutter engine
        flutterEngine.run()
        GeneratedPluginRegistrant.register(with: flutterEngine)
        
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

Step 4: Add Entitlements (for App Store)

Create or update ios/Runner/Runner.entitlements:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.carplay-audio</key>
    <true/>
</dict>
</plist>

Available entitlements (request from Apple):

  • com.apple.developer.carplay-audio β€” Audio apps
  • com.apple.developer.carplay-messaging β€” Messaging apps
  • com.apple.developer.carplay-navigation β€” Navigation apps
  • com.apple.developer.carplay-parking β€” Parking apps
  • com.apple.developer.carplay-quick-ordering β€” Quick food ordering
  • com.apple.developer.carplay-charging β€” EV charging apps

Testing with CarPlay Simulator

  1. Open Xcode
  2. Run your app on a simulator
  3. Go to I/O β†’ External Displays β†’ CarPlay
  4. The CarPlay window will appear

Or use the standalone CarPlay Simulator:

  1. Open Xcode
  2. Go to Xcode β†’ Open Developer Tool β†’ CarPlay Simulator

Running CarPlay Without Opening the App

The package supports launching CarPlay even when the app isn't running on the phone. This is handled automatically when you configure the shared Flutter engine as shown above.

To force update the template after connection:

_flutterCarplay.forceUpdateRootTemplate();

Troubleshooting

See Troubleshooting for common iOS setup issues.

Clone this wiki locally