Skip to content

feat: Add Apple CarPlay support#1480

Open
GodlySoftware wants to merge 6 commits intoUnicornsOnLSD:redesignfrom
GodlySoftware:redesign
Open

feat: Add Apple CarPlay support#1480
GodlySoftware wants to merge 6 commits intoUnicornsOnLSD:redesignfrom
GodlySoftware:redesign

Conversation

@GodlySoftware
Copy link
Copy Markdown

@GodlySoftware GodlySoftware commented Dec 12, 2025

  • Add CarPlay entitlements and scene configuration to iOS project
  • Create CarPlaySceneDelegate for handling CarPlay lifecycle
  • Implement CarPlayHelper service reusing AndroidAutoHelper logic
  • Add CarPlay method channel bridge between Flutter and native iOS
  • Update MusicPlayerBackgroundTask to notify CarPlay of track changes
  • Configure CarPlay templates for Browse, Now Playing, and Search

Closes #24

Changes

This PR implements Apple CarPlay support for Finamp by leveraging the existing Android Auto infrastructure. The implementation includes:

iOS Native Integration:

  • CarPlay scene delegate with tab bar template (Browse, Now Playing, Search)
  • Method channel bridge for Flutter ↔ iOS communication
  • CarPlay entitlements and scene configuration

Flutter Integration:

  • CarPlayHelper service that reuses AndroidAutoHelper's proven logic
  • Automatic now playing updates when tracks change
  • Shared media item generation and search functionality

Key Benefits:

  • 80% code reuse from existing Android Auto implementation
  • No breaking changes to existing functionality
  • Ready for CarPlay simulator and physical testing
  • Follows established automotive integration patterns

Todo before merging

  • Translations (reuses existing strings from Android Auto)
  • Reset Settings (no new settings added)
  • Extended CONTRIBUTING.md

Related Issues

- Add CarPlay entitlements and scene configuration to iOS project
- Create CarPlaySceneDelegate for handling CarPlay lifecycle
- Implement CarPlayHelper service reusing AndroidAutoHelper logic
- Add CarPlay method channel bridge between Flutter and native iOS
- Update MusicPlayerBackgroundTask to notify CarPlay of track changes
- Configure CarPlay templates for Browse, Now Playing, and Search

Closes UnicornsOnLSD#24
@GodlySoftware
Copy link
Copy Markdown
Author

Hi! I noticed this was a requested feature, so I implemented CarPlay support in PR #1480. Happy to make any adjustments based on feedback!

@Caian
Copy link
Copy Markdown

Caian commented Dec 12, 2025

I'll already use this version on my car for sure! Thank you!

Copy link
Copy Markdown
Author

@GodlySoftware GodlySoftware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conflict merged:

  • Original code: Updated error handling and FlutterImplicitEngineDelegate
  • CarPlay code: Added CarPlay import, method channel setup, and delegate method
  • Fixed: Missing brace and proper plugin registration

- Implement CarPlay integration with native iOS templates
- Fix BaseItemDto.getImageUrl() error using JellyfinApiHelper
- Add CarPlay helper service and scene delegate
- Update Info.plist with CarPlay configuration
- Fix addListener/removeListener errors by using QueueService stream API
- Add missing updateNowPlaying() public method for background task
- Replace listener pattern with StreamSubscription for proper cleanup
- Add dart:async import for StreamSubscription type
- Add setExcludeFromiCloudBackup function to AppDelegate.swift
- Resolves Swift compiler error for iOS build
- Function excludes app directories from iCloud backup as intended
@GodlySoftware
Copy link
Copy Markdown
Author

GodlySoftware commented Dec 16, 2025

Updated with fixes for all build errors:

  • Fixed getImageUrl method
  • Fixed QueueService stream API usage
  • Added missing iOS setExcludeFromiCloudBackup function
    All platforms now build successfully.

Resolves #24

The new section covers:
- **CarPlay Simulator Testing** - How to test in Xcode
- **Physical CarPlay Testing** - Requirements for real testing
- **Development Notes** - Technical implementation details
- **Production Requirements** - Apple's requirements for App Store
Copy link
Copy Markdown

@APIUM APIUM left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm keen for this feature so I had a quick review and added a few comments. Thanks for your work

Comment thread CARPLAY_IMPLEMENTATION.md
@@ -0,0 +1,104 @@
# Apple CarPlay Implementation for Finamp
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest just having this in the PR message on GitHub, not committed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this seems like a agent summary? Part of this (requirements, etc.) should be moved into CONTRIBUTING.md as part of the developer docs, another part (testing instructions) should be added to the PR description, and the file structure stuff can probably be deleted entirely

Comment thread CONTRIBUTING.md
#### Production CarPlay Requirements
- Apple Developer Program membership required
- CarPlay entitlement must be requested from Apple
- App Store review process includes CarPlay-specific approval### Developing on an Android Device without Android Studio on linux (not recommended)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing newline

Comment thread ios/Runner/CarPlaySceneDelegate.swift
}

private func notifyFlutter(event: String) {
guard let flutterViewController = UIApplication.shared.delegate?.window??.rootViewController as? FlutterViewController else {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you just create this once and reuse?


final _androidAutoHelper = GetIt.instance<AndroidAutoHelper>();
final _queueService = GetIt.instance<QueueService>();
final _audioServiceHelper = GetIt.instance<AudioServiceHelper>();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used? It looks like it's not

<dict>
<key>UISceneConfigurationName</key>
<string>CarPlay</string>
<key>UISceneDelegateClassName</key>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm reading the docs wrong this is also iOS13 or above.
And does the value not need the module name?

_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already done in didInitializeImplicitFlutterEngine? Does carplay need this here as well for some reason? Does it cause issues on the normal version?

@Chaphasilor
Copy link
Copy Markdown
Collaborator

@Caian @APIUM did any of you actually manage to build and test this? Any issues with the functionality? I can't test myself since I don't have Apple hardware.

@APIUM
Copy link
Copy Markdown

APIUM commented Jan 10, 2026

@Caian @APIUM did any of you actually manage to build and test this? Any issues with the functionality? I can't test myself since I don't have Apple hardware.

I also don’t have a Mac but I’ve got an iPhone and a CarPlay head unit, I was hoping to borrow a Mac next week to give it a try (but it’s not guaranteed). If I manage to I’ll take some photos/videos as well so everyone can see what it looks like.

@APIUM
Copy link
Copy Markdown

APIUM commented Jan 13, 2026

@Chaphasilor I have got and set up a Mac to continue this, was able to get a build completed to test that the changes haven't broken the non-carplay portion (they have, it crashes on load), but apparently need a developer account and the CarPlay entitlement just to test it (!).

I am willing to get a developer account as that appears to be the main barrier to getting this feature out, but I expect I'll need assistance to secure the entitlement (I expect I won't be able to submit the request from my account, I'm hoping I will be able to build and test once we've got it without being part of the team, but there's a chance I might) - see this link https://developer.apple.com/documentation/carplay/requesting-carplay-entitlements

Is this something the team is happy to do?

EDIT: It wasn't that difficult to get it to run on my device (still w/o CarPlay testing, but building with the code) with this change https://github.com/APIUM/finamp/tree/pr-1480-carplay . It does make me worry that possibly @GodlySoftware never built this? Are you willing to do any more work on this @GodlySoftware or should any changes needed be picked up by the Finamp team/others?

EDIT2: Was able to get it tested on the sim, I can't get any content to load on the Now Playing screen, or for any content to appear when opening the app on CarPlay. I just get a blank screen. The main error that appears in console is initializing CLLocationManager with a nil bundle path

@Caian
Copy link
Copy Markdown

Caian commented Jan 13, 2026

@Caian @APIUM did any of you actually manage to build and test this? Any issues with the functionality? I can't test myself since I don't have Apple hardware.

Sorry I haven't had the time, but I think will be able to give it a try next week.

@Peet809178
Copy link
Copy Markdown

@APIUM @Caian I've got CarPlay hardware to test with. I'd just need help with installing the build.

@APIUM
Copy link
Copy Markdown

APIUM commented Jan 15, 2026

@Peet809178 I've stopped working on testing this PR at the moment, I couldn't get it to work at all on the CarPlay sim.

@Chaphasilor
Copy link
Copy Markdown
Collaborator

@GodlySoftware since no-one was able to test this PR so far, and there has been testing with simulators and actual hardware for the other PR (#1516), are you okay with us closing this PR in favor of the other one?

@Chaphasilor Chaphasilor added the awaiting response / stale Issue is possibly outdated or waiting for user feedback label Mar 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting response / stale Issue is possibly outdated or waiting for user feedback

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants