Swift: How to take input from solid button through earphone jack? - ios

I'm working on an app and I need it to take input from two solid buttons connected from the earphone jack. I need the app to count how much time it take to finish pressing the button 10 times. I have the timer working now but I can't figure out how to make it take the input. Also, if I have this figured out, is there a way to stimulate? Can you guys give me a hand, please?

remoteControlReceivedWithEvent is used get the audio controls (play/pause), probably it's same as your audio jack device. You need to enable your application with Background audio capability and should add code to start audio session for your app so that you can get call backs when any button pressed in headphones to the function
try this:
override func remoteControlReceivedWithEvent(event: UIEvent?) {
let rc = event!.subtype
print("does this work? \(rc.rawValue)")
}

Related

Testing CarPlay Audio using the simulator

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

How can I play an iOS system sound and cancel the callback

I have an app where I play a system sound to indicate to the user that they can begin recording. I currently use the code below.
AudioServicesPlaySystemSoundWithCompletion(1117) {
DispatchQueue.main.async {
self.setupRecordingViews()
}
// beging recording
}
However the user could cancel wanting to record something once this function has begun and I need to a way to be able to cancel it in order to stop my UI changing to begin recording.
Any ideas how I could do this using a system sound? is there a way I can add an observer or delegate?
I'm not sure if I completely understand the issue, but just before you call setupRecordingViews() could you check a self.didCancel flag?
In your handler for whatever cancel button you have you would just set that:
self.didCancel = true

'Play on' feature is an in-app purchase? SpriteKit/Swift

I'm near the end of developing a game, and long story short, the game will be over when an object crashes into one of the obstacles. I've got that part down and the game runs really well by itself, but there is one more step I am looking to add in.
I would like to add in an in-app purchase of a 'play on' feature, that is, starting where the user's game originally ended so they can continue on. I'm okay with in-app purchases on the whole, but I guess what I want to know is how does one make it possible to 'play on' following the in app purchase? I'm just looking for something basic I can build on.
I'm a Stack newbie, as I've only created an account today (but I've been programming for a little while and this site has helped me so many times), so I'm sorry if there has been a duplicate thread made elsewhere. I did look around for an hour or so before deciding to post (and Google was no help).
As a general stack overflow rule you should always post some of your own code or what code you have played around with.
I am actually also looking to integrate a playOn button in my game. Now I haven't actually found the perfect solution for this yet but hopefully this helps you get on the right track.
Step 1:
How have you programmed your game over scenario?
Are you just pausing the scene, are you pausing nodes or are you removing all children from your scene?
The way I pause my scene is by creating a worldNode and than adding all objects that I need paused to the worldNode.
You can read my two answered questions for more detail
Keeping the game paused after app become active?
Sprite moves two places after being paused and then unpaused
This way when I pause my game I dont actually pause the scene which gives me more flexibility adding pauseMenus etc. Furthermore its seems smoother than pausing the skView.
I also call pause when the player died, which means I could resume the enemies/obstacles from where they left of if I call resume.
So my game over method looks like this
func gameOver() {
pause() // call pause method to pause worldNode etc
//show game over screen including playOn button
}
Step 2:
Now in regards to respawning the player, it depends on how he is positioned, how far he can move etc.
If your player is mostly in the same area than you can probably just respawn you player manually once "PlayOn" is pressed and than resume the game as if it was just paused.
So once your playOn button is pressed you can call a method like so
func playOnPressed() {
// Remove current player
// Doesnt have to be called, you could just change the position
player.removeFromParent()
// Add player manually again to scene or just reposition him
...
// Remove obstacle that killed player
// haven't found a great solution for this yet
// You could make the player not receive damage for 5 seconds to make sure you dont die immediately after playOn is pressed
// Call resume method, maybe with delay if needed
resume()
}
If your player position could be all over the screen, as in my game, I have been playing around with a few things so far.
I created a position property to track the player position
playerPosition = CGPoint!
and than in my scene update method I constantly update this method to the
actual position of the player.
override func update(currentTime: CFTimeInterval) {
if gameOver = false {
playerPosition = player.position
}
}
I than have been playing around with the "playOnPressed" method,
func playOnPressed() {
// Remove current player
//Doesnt have to be called, you could just change the positioon
player.removeFromParent()
// Add player manually again to scene or just reposition him
...
player = SKSpriteNode(...
player.position.x = playerPosition.x - 40 // adjust this so it doesnt spawn where he died but maybe a bit further back
player.position.y = playerPosition.y // adjust if needed
// Remove obstacle that killed player
// haven't found a great solution for this yet
// You could make the player not receive damage for 5 seconds to make sure you dont die immediately after playOn is pressed
// Call resume method, with delay if needed
resume()
}
I hope this helps you playing around with your playOn button, if someone has a better way I would also appreciate it immensely.

Running a function when the game becomes active iOS - SpriteKit

In my game in swift / SpriteKit, I have a problem when the user quits the app and opens it up again. If the game is on the pause menu and everything is paused, when the game is reloaded the game is unpaused but the labels on the pause menu do not disappear. How do I keep the game paused when I reopen it? I have tried
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
let scene = GameScene(size: CGSize(width: 2048, height: 1356))
scene.view?.paused = true
}
But this is not doing anything. I have also tried pause() but that messes things up. Any help is appreciated.
You want to use the applicationWillResignActive function to pause your scene, by doing something like scene.speed = 0 which will properly pause your scene (don't know why, but it doesn't quite work just using pause). Here you can also display your pause menus (which you appear to be doing).
Then you want to use the applicationDidBecomeActive function to continue your game. Here you do your checks to see if (guessing here) your "resume" button is pressed, and in the response method for that, set the scene.speed = 1. Here your response method, do anything that requires starting back up (animations, actions, hiding your pause menu(s), or music).
I will say, these are the two functions that I use, you are free to use whichever two functions you would like that have a on/off kind of thing. I've found these to be very reliable.

turning Fire Animation to actionscript 3

How can I turn Fire animation from Timeline to ActionScript 3 Code?
If I use fire animation on timeline for my game, characters position and level details would reset.
Do you have any advice about how can I handle this issue?
My experience on flash is too low, sorry for this kind of question
Thanks
Make a Fire movieclip that contains all the fire timepline animation. Then simply call it's play() function to play it.

Resources