Testing CarPlay Audio using the simulator - ios

I have developed an iOS radio audio app using Swift / UIKit and everything works well.
I want to integrate wit CarPlay and got the required entitlements.
I believe I have set everything up right for the most part as I can see the CPListTemplate with my CPListItems and on tapping one of them, it goes to the CPNowPlayingTemplate and the audio starts playing in the simulator.
While everything seems to be working well, However, there are 2 issues:
I can't seem to interact with CPNowPlayingTemplate play / pause button, I just keep seeing the play button but clicking it does nothing
I am able to do this on the device's lock screen and through Command Center after adding this code:
func setupNowPlayingInfoCenter(){
UIApplication.shared.beginReceivingRemoteControlEvents()
MPRemoteCommandCenter.shared().playCommand.isEnabled = true
MPRemoteCommandCenter.shared().playCommand.addTarget { [weak self] event in
self?.reliableRadioPlayer?.play()
return .success
}
MPRemoteCommandCenter.shared().pauseCommand.isEnabled = true
MPRemoteCommandCenter.shared().pauseCommand.addTarget { [weak self] event in
self?.reliableRadioPlayer?.pause()
return .success
}
}
The second issue is again on the same screen, I cannot see any of the meta data such as the artwork, song name and artist name - again these show up on the device's lock screen and the Command Center with the help of these lines of code:
MPNowPlayingInfoCenter.default().nowPlayingInfo =
[MPMediaItemPropertyTitle: currentlyPlaying.getSongName(),
MPMediaItemPropertyArtist: currentlyPlaying.getSongArtist(),
MPMediaItemPropertyArtwork: artwork]
Do I need to set anything else up or are these simply limitations of the CarPlay simulator ?
Thanks

While I do not believe this is going to be best answer and someone might come up with something better, here are some things I believe could improve how you test CarPlay and explain some issues you might face:
Add these two lines of code before launching your NowPlayingTemplate
#if targetEnvironment(simulator)
UIApplication.shared.endReceivingRemoteControlEvents()
UIApplication.shared.beginReceivingRemoteControlEvents()
#endif
I immediately saw some improvements in the meta data displayed by the simulator
The player status does not reflect accurately on the simulator
When you launch the app on the CarPlay simulator and the now playing template is showing, most likely your audio is going to be playing but the player's status is going to show and this will not show the isPlaying status accurately in your CPListTemplate if you have one
There is nothing to worry about here as it works fine in the car, however, I suggest just clicking the play button so you can see the active status in the NowPlayingTemplate and CPListTemplate screen with the animated bars
Testing on a real device
While I don't think most of us can buy a car just to test CarPlay, you could look into buying a car stereo which supports CarPlay like a Sony XAV-AX5500, Sony XAV-AX1005DB or something lower end like this
You cannot power up a car stereo normally with your plugs at home, so I suggest youtubing some videos to power this up, however, this was the easiest one I found using a laptop charger - basically I believe you need something 12V or greater
Good luck

Related

How is MPChangePlaybackRateCommand triggered?

I'm playing around with the audio features in iOS, and I'm looking at MPRemoteCommandCenter's changePlaybackRateCommand. I have enabled it, given it a target, and set its supportedPlaybackRates, but I don't see any related UI showing up in control center or the lock screen. And other commands I've set up, like skip forward, skip back, like, dislike, and bookmark, show up properly.
How does a user trigger a MPChangePlaybackRateCommand on iOS?
I face this problem and when I search I get other people face the same problem here
but I found something strange when I play podcast app in apple watch I found rate icon and I change the playrate from it
I think it's not work in iPhone (iPhone 6 iOS 11 ) but appear and work in another Apple devices in my case Apple watch
in iOS example here Apple not add MPChangePlaybackRateCommand like other commands that make me sure about it's bug in iOS

How to show the Now Playing Tab in CarPlay?

I'm working on an app that will support CarPlay.It's an audio app.
I'm able to show 2 tabs (favourite and recommended) though I just don't know how to show the Now Playing Tab. I just cannot find any info regarding this.
Do I have to manually show it, and the, how do I push? Do I have to do it manually? If so, what's the viewcontroller?
Thanks.
For the Transition to the Now Playing tab to work on both the simulator and an actual car, you need to make sure to
call beginReceivingRemoteControlEvents on the current UIApplication, and
set a nowPlayingIdentifier on the MPPlayableContentManager
before calling the completion handler in playableContentManager:initiatePlaybackOfContentItemAtIndexPath:completionHandler:.
I know this post is a couple months old, but for me, I had to test in an actual device with CarPlay. Apple says always test it on an actual device with CarPlay. At first, I didn't see a Now Playing tab in the simulator, but as soon as it was tested in a device it was there automatically. I didn't do anything special. I think CarPlay knows when you're playing audio via MPNowPlayingInfoCenter and does this automatically in the actual CarPlay device.

Notification with sound and vibration when iphone is Locked

I am currently working on an iOS app and i need some help.
I want the app to be able to notify the user about something in form a "push notification" even when the phone locked. The push notifications work fine when the phone is not locked but as soon as i lock the phone it wont give me any sound or vibration. It will only show me the visual part of the notification but it comes in completely silence. It does not even light the screen up when the notification gets pushed to the user.
I currently use
content.sound = UNNotificationSound.default()
And it works fine with sound and vibration when the phone is unlocked.
Is it because i need to do something with my settings? do i need any code to do such thing? do i need to have developer account?
Any help would make me really happy!!
3 STEPS TO HOPEFULLY RECOVER SOUND ON YOUR IPHONE FOR INCOMING NOTIFICATIONS.
Check that the ringer on the left of the phone doesn’t show an orange line – indicating sound switched off. If so, slide it to the right so only white is showing. This may have fixed it.
Swipe up from the bottom of the screen to reveal symbols, music etc. Ensure that the half moon symbol is grey and not white. If it’s white touch it to make it grey – this will switch off do not disturb. This may have fixed it.
Check your settings, Do not Disturb half moon icon, ensure that Manual is off and not showing a green on icon. If it is, touch the green icon which will make it white and switch it off. This may have fixed it.
(I hope that helps, it worked for my iphone 5C as I’d inadvertently switched on Do Not disturb as shown in step 2. above.)
Just an FYI if someone else is having this same issue. I was having the same troubles getting my notifications to come through on my phone when it was locked.
I realized the issue was I was building to my physical device which was also attached to the Apple Watch I was wearing. Since my watch is set to mirror my iPhone notifications the phone didn't play them as it expected my watch to take over when was locked. However, every time you build & run your app it takes a few minutes for your watch to recognize your app and take over the user notifications.
The solution here is to either wait 10 minutes or so after building and then try firing off a notification (which should appear on your watch) OR simple take off your watch before you build & run.

Play a sound on my backgrounded app when the phone is in silent mode

I've built a timer app and one problem I have is when it's backgrounded, I'm unable to ring the timer if the user has volume off. Turning the volume or sound off also mutes notifications, which is the method I was using for ringing the timer in the background.
I just bought a tile and discovered it can ring your phone even on silent. I have tested this and it works in iOS 9, but I'm not sure how to duplicate this behavior.
How is ringing the iPhone in silent mode accomplished? Background refresh? Motion and activity? Something else?
Prior art:
this answer plays in silent mode, but does not address when the app is closed. same here
First of all, in order to play a sound in background your application must be able to launch the related code responding to a callback event when in the background. Only specific app types are allowed to respond to callbacks events in the background. For example, the "Tile" application can play sound in background responding to BLE-related callbacks events which are fired when the application is in background (e.g., BLE peripheral connections and disconnections) . Conversely, a simple timer is suspended when application goes in background thus the timer-expiration callback won't be triggered and there is no way to launch any code to play sound in this case. (You can read here for some details and a possibile approach to build alarm clock in iOS)
If your application type is within the set of special background-mode applications you can play a sound responding to events in background even when the phone is in silent mode by using AVAudioPlayer. In your view controller import the AVFoundation framework:
import AVFoundation
than declare an AVAudioPlayer variable
var player: AVAudioPlayer?;
in order to play an mp3 file placed in the app bundle:
func playSound() {
guard let url = Bundle.main.url(forResource: "MY_MP3_FILE", withExtension: "mp3") else {
print("error");
return;
}
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: AVAudioSessionCategoryOptions.mixWithOthers);
player = try AVAudioPlayer(contentsOf: url);
guard let player = player else {
print("error");
return;
}
player.play();
} catch let error {
print(error.localizedDescription);
}
}
Important: in Xcode in the "Capabilities" tab you also have to enable the "Audio, AirPlay and Picture in Picture" feature in the "Background Modes" section.
(Swift 4 solution tested in iOS 11 and 12 with different iPhone models).
Warning: Following this approach the sound will play at the current volume set in the phone, thus if the sound volume is equal to zero the sound will not be played. You can force the volume sound to a given value programmatically in this way:
let volumeView = MPVolumeView();
if let view = volumeView.subviews.first as? UISlider{
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.01) {
view.value = 0.5; //Set the volume level between 0 and 1
}
}
however, take into account that this approach shows the system sound volume bar and it could lead to a bad user experience.
First thing first I think we need to clear up a few things (correct me if I'm wrong):
You are scheduling a local notification when your timer is expired
Your app isn't running in the background at all
You want your local notification to play a sound even if the phone is on mute.
I'm not actually sure this is possible, you mentioned the Tile app, and the important distinction is that the Tile app actually does run in the background where your app doesn't.
Apple defines specific use cases that are allowed to run in the background. One of those allowed modes are to communicate with a Bluetooth LE device. So the way that works is the iPhone identifies the tile device, and send a notification to the tile app, at that point the app is actually executing. See more about background execution here
I don't believe any of the approved backgrounds modes can be used by you to implement a solution that will allow you to workaround this.
My suggestion is that when the user sets a timer in your app, check if the phone is on silent (see here), and if it is, alert the user that the app won't play a sound when the timer completes.
Also download a few other timer apps and see how they deal with it.

iOS - Reset the command center / remote player

I'm using different kinds of players in my app. I have some kind of control over all of them, but one of them I don't, at all.
When I play an embedded video from a UIWebView, specifically.
My issue is, the app requires audio to be played in background, which works fine. Note, the video's audio does not need to be played in background. But that means I need to use the remote controls (command center & lock screen commands).
My issue is the following :
After I've played a video from an embed, the remote controls still control that video, even though it's been dismissed. And when I press "play", it plays both my radio AND the embedded video.
How can I "clear the memory" of the command center ?
I have enough information to know when to apply a solution, I don't know what the solution is though.
Solution can include a complete disability to use the command center while playing the embed video, or until my radio is played. Solution can include some kind of "hard reset" of the command center.
Actually, any solution is welcome.
This question is a little bit old, but I just fixed this issue and feel like this could help someone out. The thing that was preventing me from reseting the command center was that I had added target actions that were persisting past the instance of my view controller's lifecycle.
Here's what my code looked like.
On the view controller:
var commandPlay: Any?
var commandPause: Any?
When adding the targets:
commandPlay = commandCenter.playCommand.addTarget {event in
self.startButtonTapped(self.startButton)
MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 1.0
return .success
}
commandPause = commandCenter.pauseCommand.addTarget {event in
self.startButtonTapped(self.startButton)
MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 0.0
return .success
}
At dismiss to remove the targets (important part):
commandCenter.playCommand.removeTarget(commandPlay)
commandCenter.pauseCommand.removeTarget(commandPause)

Resources