CarPlay iOS 13.1 - never calling MPPlayableContentDataSource

Hi!


A few weeks ago I finally updated my audio app to support CarPlay. I have tested it with the 12.4 simulator and it was running fine. Now, if I compile and test on the iOS 13.1 simulator, it tells me that CarPlay can't connect to my app. The same happens if my colleague tries to use the app in a real CarPlay environment. A few days ago he also updated his XR to iOS 13.1, so we can't test it with a real iOS 12.4.


I don't understand what I could be missing. I already searched on StackOverflow and googled lots of possible keywords. But I've found nothing that would help or give a hint what's wrong with my app.


Again, all is fine with iOS 12.4 simulator.


If someone has an idea or advice, what could cause my problems, please feel free to post an answer.


Here is a short overview (essential methods only), what I've implemented:


@implementation CPMainController

- (instancetype)init {
    self = [super init];
    if (self) {
        DLog(@"I", @"");
        // 1. code that registers handlers with the MPRemoteCommandCenter:
        // playCommand,
        // pauseCommand,
        // stopCommand,
        // togglePlayPauseCommand,
        // previousTrackCommand and
        // nextTrackCommand

        // 2. code that invokes '[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = someTitleInfo;'

        _playableContentManager = [MPPlayableContentManager.sharedContentManager retain];
        _playableContentManager.dataSource = self.dataSource;
        _playableContentManager.delegate = self.delegate;
        /* here, I already tried several variants and combinations */
        // [_playableContentManager beginUpdates];
        // DLog(@"I", @"force load the content items");
        // [self.dataSource contentItems];
        // [_playableContentManager endUpdates];
        [_playableContentManager reloadData];
    }
}

- (cp_data_source*)dataSource {
  // lazy getter, creates and returns an instance of 'cp_data_source'
}

- (cp_delegate*)delegate {
  // lazy getter, creates and returns an instance of 'cp_delegate'
}

(... some other stuff for memory management ...)

@end


@implementation cp_data_source

- (NSArray<mpcontentitem*>*)contentItems {
  // lazy getter, creates and returns the MPContentItem objects
}

- (void)beginLoadingChildItemsAtIndexPath:(NSIndexPath*)indexPath
                        completionHandler:(void (^)(NSError* __nullable))completionHandler {
  // protocol method, never gets called on ios 13
}

- (BOOL)childItemsDisplayPlaybackProgressAtIndexPath:(NSIndexPath*)indexPath {
  // implemented
}

- (void)contentItemForIdentifier:(NSString*)identifier
               completionHandler:(void (^)(MPContentItem* _Nullable, NSError* _Nullable))completionHandler {
  // implemented
}

- (NSInteger)numberOfChildItemsAtIndexPath:(NSIndexPath*)indexPath {
  // implemented
}

- (MPContentItem*)contentItemAtIndexPath:(NSIndexPath*)indexPath {
  // implemented
}

@end


@implementation cp_delegate

- (void)playableContentManager:(MPPlayableContentManager*)contentManager
    initiatePlaybackOfContentItemAtIndexPath:(NSIndexPath*)indexPath
                           completionHandler:(void (^)(NSError* __nullable))completionHandler {
  // implemented, plus the following snippet:
#if (TARGET_IPHONE_SIMULATOR)
            [UIApplication.sharedApplication endReceivingRemoteControlEvents];
            [UIApplication.sharedApplication beginReceivingRemoteControlEvents];
#endif
}

@end


For completeness, my logs with the two simulators...

--- For iOS 12.4: ---


[I] -[CPMainController init]:
[I] NowPlaying:
{
    artist = "CPMainController";
    artwork = "<MPMediaItemArtwork: 0x600000510140>";
    title = Stopped;
}
[I] -[CPMainController dataSource]:
[I] -[cp_data_source init]:
[I] -[CPMainController delegate]:
[I] -[cp_delegate init]:

...(
  now I open the car play external display in simulator:
  * the phone screen dims and shows that car play is active now.
)...

[I] -[cp_data_source beginLoadingChildItemsAtIndexPath:completionHandler:]:
[I] -[cp_data_source setRadioStations:]:
[I] -[cp_data_source childItemsDisplayPlaybackProgressAtIndexPath:]:
[I] -[cp_data_source numberOfChildItemsAtIndexPath:]:
[I] -[cp_data_source contentItemAtIndexPath:]:
[I] -[cp_data_source tabItems]:


--- For iOS 13: ---


[I] -[CPMainController init]:
[I] NowPlaying:
{
    artist = "CPMainController";
    artwork = "<MPMediaItemArtwork: 0x600002bb3160>";
    title = Stopped;
}
[I] -[CPMainController dataSource]:
[I] -[cp_data_source init]:
[I] -[CPMainController delegate]:
[I] -[cp_delegate init]:

...(
  now I open the car play external display in simulator:
  * the phone screen gets black (showing an activity indicator)
    for a second and then again shows my app's main screen

  * nothing else happens
)...

Thank you in advance!

Replies

I have the exact same issue as you, did you make any progress with this?


We built our CarPlay media app using Xcode 10 and tested it on both an iOS 12.4 simulator and on a physical iOS 12.4 device using a physical in-car infotainment system. We had no issues with iOS 12.4 and the app worked perfectly. We then upgraded our project to build using Xcode 11.1 so we could have iOS 13.1 simulators. Without changing any of the CarPlay code we cannot get the app to run using the iOS 13.1 iPhone simulator with the CarPlay "external display" screen.


I looked into the code and its the same as you, the beginLoadingChildItemsAtIndexPath() function is never called on iOS 13.1, so nothing loads in our CarPlay app. In iOS 12.4 it is called. Hopefully this will be fixed soon or we get an idea what to change to use CarPlay and iOS 13.1


UPDATE 1:

I tested our CarPlay app on iOS 13.2 with a physical iPhone device in-car and it worked fine. So maybe it's just an iOS 13.1 issue.


UPDATE 2:

I updated to Xcode 11.2 and tested our CarPlay app on an iOS 13.2 iPhone simualtor. Unfortunately it's still the same as iOS 13.1 simulator, the app doesn't load. The beginLoadingChildItemsAtIndexPath() function doesn't get called when using the iOS 13.2 iPhone simulator. I have created a bug report with Apple about the issue.


UPDATE 3:

Got a reply from Apple after I submitted a bug report. The respose is not entirely helpful as I am providing content to MPPlayableContentManager. I'm not going to pursue this any further with them. Here's Apple's response:


"We need a sysdiagnose and, ideally, some sample code reproducing the issue please.


beginLoadingChildItems() is just a hint to the app to start prefetching content, in the event that the user taps a row. Instead, it seems more likely that the client app is not providing any content to MPPlayableContentManager."


I didn't make any further progress. And I am unable to test in a real CarPlay environment. So I was thinking I did something wrong or missed some important code.


Seems like I could stop cracking my head about this now. Thank you for your answer and let's see what the Apple Devs come up with. :-)

Hi, did you get any feedback from Apple? I have the similar issue and I can test the app only in CarPlay similator, which it broken for now unfortunatelly.

See update 3 above.

I faced the same issue, and just redownloaded iOS 12.4 for iPhone XS. You can re-download the iOS 12.4 simruntime as follows:


1. Window > Devices and Simulators

2. Go to "Simulators" tab

3. Press the "+" button at the bottom left.4. Select the device you want to use (except iPhone 11 and Co. since they're iOS 13 only).

5. Select the "OS Version" dropdown and select "Download more simulator runtimes."

6. Download iOS 12.4 Runtime (~2.5 GB)

7. Go back to devices window and finish setup.

8. Build to new iOS 12.4 device and CarPlay should work! (i.e. delegate and data source methods called)

I have the same issue , sign in with apple must use xcode11, but can't use carplay , this is a Big problem!!!


Not only simulator , the real carplay device has the same problem.


Xcode10 depoly carplay work fine (os 13.3.1) , the same code Xcode11 depoly carplay unable to use....