Adding a CarPlay UI
Asked Answered
S

2

8

I am working on my current iPhone audio app to be supported in CarPlay. I already got approved by Apple and received the development entitlement, and watched the video "Enabling Your App for CarPlay"(https://developer.apple.com/videos/play/wwdc2017/719/). In the video there is a piece of Swift code demonstrating how to add CarPlay UI:

func updateCarWindow()  
{  
    guard let screen = UIScreen.screens.first(where: 
    { $0.traitCollection.userInterfaceIdiom == .carPlay })  
    else  
    {  
        // CarPlay is not connected  
        self.carWindow = nil;  
        return  
    }  

    // CarPlay is connected  
    let carWindow = UIWindow(frame: screen.bounds)  
    carWindow.screen = screen  
    carWindow.makeKeyAndVisible()  
    carWindow.rootViewController = CarViewController(nibName: nil, bundle: nil)  
    self.carWindow = carWindow
}

I re-wrote it to an Objective-C version like following:

- (void) updateCarWindow  
{  
    NSArray *screenArray = [UIScreen screens];  

    for (UIScreen *screen in screenArray)  
    {        
        if (screen.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiomCarPlay)  // CarPlay is connected.
        {  
            // Get the screen's bounds so that you can create a window of the correct size.  
            CGRect screenBounds = screen.bounds;  

            UIWindow *tempCarWindow = [[UIWindow alloc] initWithFrame:screenBounds];  
            self.carWindow.screen = screen;  
            [self.carWindow makeKeyAndVisible];  

            // Set the initial UI for the window.  
            UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];  
            UIViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"VC"];  

            self.carWindow.rootViewController = rootViewController;  
            self.carWindow = tempCarWindow;  

            // Show the window.  
            self.carWindow.hidden = NO; 

            return; 
        }  
    } 

    // CarPlay is not connected.
    self.carWindow = nil; 
}  

However I found that the property "screens" of UIScreen always return 1 element (the main screen), no matter when testing on a real device or simulator. So when my app is running on the simulator or a real car with CarPlay system, the app is just blank and said "Unable to connect to "My App name"" (see the image below). My ViewController has a simple UILabel though.

enter image description here

My question is: what should I do to make my app to be connected by CarPlay? That is, how should I obtain the screen that has UIUserInterfaceIdiomCarPlay idiom, not just always the main screen? Thanks a lot in advance.

Stonehenge answered 25/7, 2017 at 11:1 Comment(1)
Some update to this post and my experiments: 1. CarPlay audio apps cannot use UIScreen based approach shown in above updateCarWindow method. 2. If my AppDelegate conforms to MPPlayableContentDataSource and MPPlayableContentDelegate, and if I implement the data source and delegate methods in AppDelegate.m, then I can see my CarPlay UI.Stonehenge
H
5

CarPlay audio apps are controlled by the MPPlayableContentManager. You are required to implement the MPPlayableContentDelegate and MPPlayableContentDatasource protocol in order to connect with CarPlay. The UI is controlled by CarPlay - all you need to do is feed it data for tabs+tables (datasource) and respond to playable items (delegate).

Hargreaves answered 28/7, 2017 at 8:12 Comment(8)
Thanks for your comments, Billy. CarPlay audio apps cannot use UIScreen based approach shown in the WWDC 2017 video. This is why my CarPlay app doesn't see any UI.Stonehenge
Still have a question: To build CarPlay UI, I should use MPPlayableContentManager APIs (MPPlayableContentDataSource & MPPlayableContentDelegate) in a class which is a subclass of NSObject, then instantiate and initialize that NSObject subclass in the method -application:didFinishLaunchingWithOptions: of AppDelegate.m. Is this correct? Thanks again.Stonehenge
Yes - you can initialize this class anywhere. application:didFinishLaunchingWithOptions is a good choice if you want CarPlay available for all users. Make sure your NSObject subclass also subclasses MPPlayableContentDataSource & MPPlayableContentDelegate.Hargreaves
Billy, did you mean the NSObject subclass conforms to MPPlayableContentDataSource & MPPlayableContentDelegate protocols, or subclasses MPPlayableContentDataSource & MPPlayableContentDelegate ? Thank you.Stonehenge
Conform to the protocol. objc.io/issues/13-architecture/subclassing/…Hargreaves
Thanks, Billy. I created an NSObject subclass (CarPlayDemo) conforming to MPPlayableContentDataSource & MPPlayableContentDelegat. I assigned the dataSource and delegate properties of MPPlayableContentManager in -init method of CarPlayDemo.m, and implemented MPPlayableContentDataSource required methods -numberOfChildItemsAtIndexPath: and -contentItemAtIndexPath: in CarPlayDemo.m as well (but I haven’t implemented MPPlayableContentDelegat methods yet). However I found that MPPlayableContentDataSource methods never got called. Any idea with that? Thanks again.Stonehenge
@BillyCaruso Do you have any sample code to implement contentItemAtIndexPath to return MPContentItem.Shull
@BillyCaruso As of iOS 14 I see in Apple's documentation, "Starting with iOS 14, CarPlay audio apps may use the CarPlay framework to present a customized user interface. CarPlay audio apps that use the CarPlay framework must include the com.apple.developer.carplay-audio entitlement." Do you know if your answer is still the only case? I don't see any instructions on how to create the custom UI it mentions.Sangria
L
2

Custom UI is only available for CarPlay navigation apps. For audio apps, the MediaPlayer framework contains all the necessary API to work with CarPlay.

Lisalisabet answered 5/2, 2019 at 16:33 Comment(2)
hi @DrMicketLaurer I have my own navigation app which uses GLKitView (using OpenGL ES) to draw my app and show the turn-by-turn navigation there. Can I put this in the map template?Puleo
@iori24 Yes, this is allowed. When/If you get an entitlement for CarPlay Map development, you can do that.Lisalisabet

© 2022 - 2024 — McMap. All rights reserved.