I'm trying to understand the basic steps required for a game I'm trying to make using GameKit for bluetooth connections. I only have 1 device, so I can't test out my ideas very easily.
The game involves a maximum of 2 players over bluetooth via GameKit and the only data to send/receive is a 'shot' which includes position and direction data only.
This is what I think should happen, I really just want someone to point out any mistakes I've made:
The game starts by presenting a GKPeerPickerController with a connectionTypeMask of 'GKPeerPickerConnectionTypeNearby' and setting it's delegate to 'self'.
The GKPeerPickerController delegate method 'peerPickerController:didConnectPeer:toSession:' is implemented and sets the sessions dataReceiveHandler to self. The peerID is added to an NSMutableArray which holds all peer IDs connected. (There should only be 1 peer connected at any time).
To enforce only 1 peer connection per game the method 'session:didReceiveConnectionRequestFromPeer:' checks the 'count' property of the NSMutableArray which holds the connected peerIDs. If 'count'>0 then we respond by calling: 'denyConnectionFromPeer:' else, we call: 'acceptConnectionFromPeer:error:'
To send a shot, the game calls: 'sendData:toPeers:withDataMode:error:'
To receive shots, the game responds to: 'receiveData:fromPeer:inSession:context:'
Are there any steps missing? For example, if a user tries to connect to me before I connect to them, what will happen with my GKPeerPickerController? How do I know to dismiss it?
And without another iPhone/iPod I can't test.
First off, if you want to test Bluetooth in Gamekit you really are going to need a 2nd device. If you're serious about your app, try and buy a cheap/refurbished iPhone or iPod Touch that will support GameKit Bluetooth (the oldest devices don't do it). I actually think you do even better with two Macs for testing, but if you don't already have a second one that's an expensive proposition.
What you've posted above is pretty much correct - actually using the PeerPicker is pretty straightforward and you should be able to get through it easily using Apple's docs. The problem is that in my experience, it's a bit janky. It might be because I'm using a 3GS and a 3G to test and they have different Bluetooth inside, but a lot of times I see weird things when the scenario you outlined occurred - "if a user tries to connect to me before I connect to them." In the end it typically still works, but not without a little overhead of waiting and perhaps the user having to repeat the process a time or two.
Related
How can I find nearby iPhones and iPods running the same application and index them into a UITableView? Then how would I go about pairing with the selected devices over bluetooth to carry out an undisclosed process?
GKSession is the easiest I've seen, although it took me about 4-5 hrs to do and that was not messing around just straight typing you will need a client model
A server model hostTableView and a joingameTableView and not to mention quite a few delegates to transfer the info back and forth between the server model and client model and back and forth between the host and the client(joingameTableView) they all talk back and forth to make that happen. You can use bonjour and other methods but I haven't used any other. I will try to post an example that compiles to git sometime soon, there is just way to much logic involved for me to explain in a post! Hope I helped at least guided you in the right direction.
OK, so I specified a UIRequiresPersistentWiFi key of my App's plist to YES so the iOS won't stop fetching the data when my app is in the background.
However, when the user uses cellular connection (not wifi) and my app is in the background, the download of the data is stopped after several minutes.
I double checked the docs and it seems there is no equivalent of UIRequiresPersistentWiFi for cellular network that I could set.
Is there any way I can make the connections over cellular network survive while the app is in the background? Any hints?
Cheers!
Updates:
I am making an Internet radio app. Stream is combined with mp3s which I request one after another (can't request them in advance, can't change server side). It works when my app is in the background and uses wifi. However, when using cellular connection the network requests are not performed after some time spent in the background. There is no place for changing the strategy. The app is in the AppStore and it had worked before. I guess they changed something in the new version of the system.
What is more I do not need throttling. My radio app has been already approved and is in the AppStore. The stream is sent with 128kb/s (that is the maximum) so that is not a problem. It looks like system silences my network requests (when on cellular network) after some time in the background. However, this only happens when I try to start the connection in the background.
Description:
App is in the background playing a mp3 streamed over cellular
network.
Mp3 ends
I request the URL to another mp3
The request is not performed*.
*works when using WiFi.
I'm fairly certain there isn't something like this for Cell networks. Here is my reasoning:
Cell service costs money. A LOT of money. Per minute. Wifi service does not cost money, in comparison.
AT&T does not have very much bandwidth, and charges users extra for extra bandwidth usage.
Apple is a company that wants to make the user experience as clean and nice as possible.
When costs are exorbitant through no fault of their own, users are angry and their experience is not nice.
If Apple lets you have a constant connection to the web outside of wifi range, the user's cost of service would skyrocket and they wouldn't know why. And if Apple gives programmers this ability, somebody would abuse it. So, I'm sure that Apple won't allow you to do that.
Why do you need a constant internet connection when your app is in the background anyway (unless, I guess, you're making an internet radio app)? Keep in mind that, when in the background, your app can be terminated without warning at any time. You may want to rethink your strategy if you can't find a way to do this. :/
I think there is no equivalent of UIRequiresPersistentWiFi, there reasons probably include the ones pointed out by Tusting2121.
But please note that UIRequiresPersistentWiFi is connected with energy saving. The wifi module consumes energy, so normally it is shut down after some time to save some energy unless UIRequiresPersistentWiFi is set.
Such enrgy saving, I believe, is not a case in cellular case.
And the fact that your connection disappears after certain minutes in cellular mode may be caused by something completely different that the copy of wifi energy saving mechanism you claim. See for example this article which suggests that you are obliged to throttle your 3G data flow.
Add audio to your UIBackgroundModes entry in Info.plist.
According to the Apple Docs: In your callbacks, though, you should do only the work necessary to provide data for playback. For example, a streaming audio app would need to download the music stream data from its server and push the current audio samples out for playback. You should not perform any extraneous tasks that are unrelated to playback.
You may also get some value out of the voip entry - you can setKeepAliveTimeout:handler: to have your handler called on a periodic basis to populate your data stream.
I am currently starting my way on developing iPhone applications, and I have recently encountered a problem which I could not find a proper answer to.
In my application, I want one iPhone to send a request and another, far iPhone respond to that request using an Alert View, almost like the way Game Center works when you invite someone to play with you.
Do I do that with Push Notifications? Some server? Or what?
Thanks ahead,
A Newbie Developer.
Not the simplest things to try and do when you are new - but have a look at GameKit.
There is a sample application called GKTap which shows how to hook up two iPhones.
Don't be fooled by the word Game. This framework makes it easy to set up communication between phones, even using Bluetooth.
It depends on what you mean by "far". If you mean in another room, but within Bluetooth range or on the same local network, then there is GameKit. If you mean on a different network, or a long distance away, then you are looking at needing to have a server that keeps track of the devices and the connections between the devices so you can use Push Notifications. If you are thinking of something like Words With Friends where it sends a message to another user to tell them it is their go, then you would need the server.
I am building an app which allows a user to draw on the screen. I'd like to add network capability so that user A can draw on user B's screen. My current plan is to build a system where I have my own UserOrNetworkTouch object which can be created based on either a real UITouch, or a message which comes over the network, and base all of the drawing in the app off of UserOrNetworkTouch events, rather than UITouch events.
Another thing I'll want to use this system for is recording touches, so a user will be able to press "record", and then play back their drawing at a later time.
I'd like to make sure I'm not reinventing the wheel here. Are there any libraries available which will handle some or all of this for me?
You probably wouldn't send the UITouch objects over the network (although you could if you wanted). I might package then touch positions into a struct of some kind and just send that to decrease the amount of traffic you were sending. If you needed the entire UITouch object and all of its data then sure, send the object to your server.
You could use CFNetwork framework to send data to a server from your client application. If you do you should really try to use IPv6.
Apple have sample code here for working with CFNetwork streams
If you want to record the touch events, just use an NSArray or an NSDictionary if you wanted to store say the touch along with a timestamp for when the touch occurred.
Then just add each touch to the array or dictionary as the user makes them.
Update: I wouldn't waste your time with Apple's WiTap sample code. I've read though it before and there is a LOT of code in it that is just confusing and irrelevant if you want a simple client/server app up and running quickly. It will more than likely be way too confusing for you if you haven't done any network programming before.
I would get the network transfers working first, then if you like you can refer to WiTap for the Bonjour networking part so you can do auto discovery of the client and server. But add Bonjour support only after you have data steams working first.
A good place to start would be Apple's WiTap sample. It sets up a game over Bonjour and sends taps back and forth.
Also look at GameKit which'll make some of the networking even simpler.
A SQLite DB would be a great place to record events. Search for the 'fmdb' SQLite wrapper for a nice Objective-C wrapper.
used this website for the long time to find answers, now need to ask on myself! :)
I have implemented multi player for my game using GKSession and client/server approach, not using peer picker (up to 4 player allowed).
I have one big problem which I can't find solution for.
If you disconnect/reconnect server peer quickly enough, client peer will "remember" that host and will show it in the list of all available peers permanently, only turning wifi/bluetooth off resets this.
So if I do this 5 times in a row, my client will show 5 available hosts with the same name!
Anyone had experience with this? Any idea of workarounds?
I should note that requirements for my game is iPhone SDK 3.0 for Bluetooth and 3.1 for Wifi as GKSession supports both now.
I have a similar problem. In fact I event get peers listed who are not even currently playing the game. Even more so, peers who are not acting as server are listed. I am wondering if there is some behind the scenes caching going on.
I'm thinking about implementing some kind of timer with visual feedback to show the disconnect progress, ideally to prevent this situation. It seems like in general there is a bit of time delay involved with connecting/available and disconnecting/unavailable. It might be better to code the interface to take these time delays into consideration, though I'm not sure exactly how.