connecting 2 devices over different WiFi network using GKSession - iphone

I am trying to connect 2 devices using GKSession. When the devices are on same WiFi network it is working but when i am trying to connect devices on different WiFi network it is not working.
This is my code for GKSession
chatSession = [[GKSession alloc] initWithSessionID:AppName displayName:name sessionMode:GKSessionModePeer];
[chatSession setDataReceiveHandler:self withContext:nil];
chatSession.delegate = self;
chatSession.available = YES;
-(void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state{
NSLog(#"state=%d", state);
if(state == GKPeerStateDisconnected)
{
// A peer disconnected
chatSession.available = YES;
NSLog(#"Disconnected");
[data removeAllObjects];
chatInput.hidden = YES;
}
else if(state == GKPeerStateConnected)
{
// You can now send messages to the connected peer(s)
NSData *imgData = UIImageJPEGRepresentation(myImage, 0.5);
if(imgData==nil)
NSLog(#"myImage is nil");
NSError *err;
//NSLog(#"pid=%#", pID);
NSLog(#"before sending image");
[chatSession sendData:imgData toPeers:[NSArray arrayWithObject:pID] withDataMode:GKSendDataReliable error:&err];
NSLog(#"after send data");
if(err)
NSLog(#"error:%#", err.description);
}
else if (state == GKPeerStateAvailable)
{
pID = peerID;
[session connectToPeer:peerID withTimeout:60*120];
}
}
-(void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID{
// We can now decide to deny or accept
bool shouldAccept = YES;
if(shouldAccept)
{
pID = peerID;
[session acceptConnectionFromPeer:peerID error:nil];
}
else
{
[session denyConnectionFromPeer:peerID];
}}
I am not sure if it is possible using GKSession.
According to Apple
A GKSession object provides the ability to discover and connect to nearby iOS devices using Bluetooth or Wi-fi.
Please help me ia m trying to create a chat app using GKSession.

iOS' GameKit most probably uses Bonjour for this, which works by doing broadcasts on a local network. It won't work between two separate Wi-Fi networks.
This means you'll need a central server (at least during connection set-up). Have a look at XMPP, if you haven't done so already.
Good luck!

Related

need XMPP Framework

I am working on ejabberd setup, i configured the server successfully, But in the client side we need XMPP Framework for this,
I Googled i got the following links
http://deusty.blogspot.in/2008/08/xmppframework-on-iphone.html
http://iphone4developer.blogspot.in/2011/07/how-to-add-xmpp-in-your-ios-project.html
I downloaded the robbiehanson / XMPPFramework but it throws errors, and some links gives me 404 error(they removed)
I downloaded the jabber client from this link (https://github.com/funkyboy/Building-a-Jabber-client-for-iOS) but the xmpp framework files throws errors(those are already deleted) from the app
I got one sample that is iPhoneXMPP sample but it throws error that is "Unable to connect to server. Check xmppStream.hostName" i given my host name in willSecureWithSettings method
Doubts:
1)Please Guide me to download the proper XMPP Framework with out errors
2)How to Configure ejabber client side?
Please guide me
Thanks a lot in advance
I downloaded the robbiehanson/XMPPFramework around 6 months back from this link: https://github.com/robbiehanson/XMPPFramework . I followed the steps that are mentioned in Getting Started section. It didn't throw any error. Just try to follow these steps to setup the xmppframework with your application.
In sample app, I found the function setupStream() that I am calling when I start my application. In this function I am creating an xmppStream and activating different modules that are needed in my application. e.g
xmppStream = [[XMPPStream alloc] init];
// Activate xmpp modules after creating them
[xmppReconnect activate:xmppStream];
[xmppRoster activate:xmppStream];
[xmppvCardTempModule activate:xmppStream];
[xmppvCardAvatarModule activate:xmppStream];
[xmppCapabilities activate:xmppStream];
// Add ourself as a delegate to anything we may be interested in
[xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
[xmppStream setHostName:XMPPHOST];
[xmppStream setHostPort:5222];
// You may need to alter these settings depending on the server you're connecting to
allowSelfSignedCertificates = NO;
allowSSLHostNameMismatch = NO;
After setting the stream, you need to do authentication like this:
- (BOOL)connect:(NSString *)myJID //username registered with server
{
if (![xmppStream isDisconnected]) {
return YES;
}
if (myJID == nil) {
return NO;
}
[xmppStream setMyJID:[XMPPJID jidWithString:myJID]];
NSError *error = nil;
if (![xmppStream connect:&error])
{
if(DEBUG)
{
NSLog(#"ERROR: Not connected to XMPP Server");
}
DDLogError(#"Error connecting: %#", error);
return NO;
}
return YES;
}
This function will be called by the framework and pass the password here:
- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
if(sender == xmppStream)
{
//DDLogVerbose(#"In xmppStream: %#: %#", THIS_FILE, THIS_METHOD);
isXmppConnected = YES;
NSError *error = nil;
if (![[self xmppStream] authenticateWithPassword:password error:&error])
{
DDLogError(#"Error authenticating: %#", error);
}
}
}
Now if user is authenticated, this function will be called:
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
if(sender == xmppStream)
{
[self goOnline];
}
}
goOnline will send user's presence to server:
- (void)goOnline
{
XMPPPresence *presence = [XMPPPresence presence]; // type="available" is implicit
[xmppStream sendElement:presence];
}
Now you can send/receive the message/presence etc.
You will find a nice - complet - tutorial here: http://mobile.tutsplus.com/tutorials/iphone/building-a-jabber-client-for-ios-server-setup/

AsycnSocket not connecting to TCP serial port over wifi

I have an iPhone app that I run on the simulator. XCode ver 3.2.6/4.3. I am trying to communicate with a radio on a serial port of a PC over wifi, both on the same server... I've tried NSStream and GCDAsyncSocket (just to make sure). The radio has its own IP address and port number. It's actually a TCP/IP wifi module. After changing the remote access on the PC to accept my IP address, I am finally able to connect but I get kicked off immediately, I'm assuming it's when I try to read or write. Same happens when using Telnet, connects then disconnects. The radio issues HELLO when someone connects, so Telnet must try to read since data is sent. I'm guessing. I thought since I am able to connect, I should be able to read/write. (Yes, newbie here)
I would appreciate any thoughts or direction. I've been researching for over a week now and going bonkers.
Thanks. I added the code below as well as the error message.
This is the error message:
socketDidDisconnect:withError: "Error Domain=NSOSStatusErrorDomain
Code=-9844 "The operation couldn’t be completed. (OSStatus error
-9844.)" UserInfo=0x4c38a60 {}"
- (IBAction)performConnection:(id)sender
{
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
uint16_t port = [[[self serverPort] text] intValue];
if (![asyncSocket connectToHost:[serverAddr text] onPort:port error:&error])
{
DDLogError(#"Unable to connect due to invalid configuration: %#", error);
[self debugPrint:[NSString stringWithFormat:#"Unable to connect due to invalid configuration: %#", error]];
}
else
{
DDLogVerbose(#"Connecting...IP:%#, port:%i", [serverAddr text], port);
}
}
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
DDLogInfo(#"socket:%p didConnectToHost:%# port:%hu", sock, host, port);
NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:3];
[settings setObject:#"XXX.XXX.X.XXX"
forKey:(NSString *)kCFStreamSSLPeerName];
// In fact, don't even validate the certificate chain
[settings setObject:[NSNumber numberWithBool:NO]
forKey:(NSString *)kCFStreamSSLValidatesCertificateChain];
[settings setObject:(NSString*)kCFStreamPropertySocketSecurityLevel
forKey:(NSString*)kCFStreamSocketSecurityLevelNegotiatedSSL];
DDLogVerbose(#"Starting TLS with settings:\n%#", settings);
[sock startTLS:settings];
[self debugPrint:[NSString stringWithFormat:#"socket:didConnectToHost:%# port:%hu", host, port]];
//[sock readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];
[sock readDataWithTimeout:-1 tag:0];
}
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
DDLogVerbose(#"socket:didWriteDataWithTag:");
[sock readDataWithTimeout:-1 tag:0];
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
DDLogVerbose(#"socket:didReadData:withTag:");
NSString *response = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"read response:%#", response);
[self debugPrint:[NSString stringWithFormat:#"Read: \n%#",response]];
[response release];
//NSData *newline = [#"\n" dataUsingEncoding:NSASCIIStringEncoding];
//[sock readDataToData:newline withTimeout:-1 tag: 0];
[sock readDataWithTimeout:-1 tag:0];
}
- (IBAction)sendBuf:(id)sender
{
if ([[bufOut text] length] > 0)
{
NSString *requestStr = [NSString stringWithFormat:#"%#\r\n", [bufOut text]];
NSLog(#"Sending:%#",requestStr);
NSData *requestData = [requestStr dataUsingEncoding:NSASCIIStringEncoding];
[asyncSocket writeData:requestData withTimeout:-1.0 tag:0];
[self debugPrint:[NSString stringWithFormat:#"Sent: \n%#",requestStr]];
}
}
I found a partial solution (by sheer accident). It seems the radio or how the radio is setup only allows me to connect/read/write if my app or iMac initiates the connection. It's fine with another PC. Both can initiate a connection and everything works. Still need to resolve this but at least I know my code is working.
Thanks to anyone who gave my problem some thought.

Reachability Help - WiFi Detection

I have imported Reachability into my application, and I have a couple of how-to questions for you all. Let me explain my application and other tools first.
This application communicates with two things AT THE SAME TIME, an ad-hoc network, and the internet through 3G. Note: The ad-hoc network IS NOT connected to the internet. This works perfectly - it's already implemented and tests out wonderfully.
With that being said, I want to implement Reachability to detect a two things.
1) Is the user connected to a wifi ad-hoc network? (Even better, if possible, is to detect if it is connected to the wifi ad-hoc network with a prefix of WXYZ. For example, if there are two networks listed, one called Linksys and the other called WXYZ-Testing_Platform, it knows whether or not it is connected to WXYZ).
2) Can the user connect to the internet through 3G (or 2G, etc) and access our server?
Thanks in advance
EDIT TO INCLUDE ANSWER FOR FUTURE LOOKERS:
For 1), my code looks like this:
.h
#import <SystemConfiguration/CaptiveNetwork.h> //for checking wifi network prefix
.m
- (BOOL) connectedToWifi
{
CFArrayRef myArray = CNCopySupportedInterfaces();
// Get the dictionary containing the captive network infomation
CFDictionaryRef captiveNtwrkDict = CNCopyCurrentNetworkInfo(CFArrayGetValueAtIndex(myArray, 0));
NSLog(#"Information of the network we're connected to: %#", captiveNtwrkDict);
NSDictionary *dict = (__bridge NSDictionary*) captiveNtwrkDict;
NSString* ssid = [dict objectForKey:#"SSID"];
if ([ssid rangeOfString:#"WXYZ"].location == NSNotFound || ssid == NULL)
{
return false;
}
else
{
return true;
}
}
And for 2), I imported Reachability and have it using this method whenever I go to connect to the server... NOTE:replace http://www.google.com with the server information
-(void) checkIfCanReachServer
{
UIAlertView *errorView;
Reachability *r = [Reachability reachabilityWithHostName:#"http://www.google.com"];
NetworkStatus internetStatus = [r currentReachabilityStatus];
if(internetStatus == NotReachable) {
errorView = [[UIAlertView alloc]
initWithTitle: #"Network Error"
message: #"Cannot connect to the server."
delegate: self
cancelButtonTitle: #"OK" otherButtonTitles: nil];
[errorView show];
}
}
Reachability only lets you know if the device can send data packets out successfully. So
for 1) you should refer to iPhone get SSID without private library. For 2) you will use Reachability only to check for an internet connection then you would need to use NSURLConnection or other network library to make sure you can reach your server.

How to check Internet status in iPhone

I wanted to check whether internet is connected or not using either the SystemConfiguration or the CFNetwork i am not quite sure which one.
Then i want to know that if the internet is connected then is it connected through wifi or not.
I tried an example where i used the below code
-(IBAction) shownetworkStatus
{
NSString *str = #"http://www.google.com";
NSURL *url = [NSURL URLWithString:str];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
if (req!=NULL) {
lbl.text = #"Connected";
}
else {
lbl.text = #"notConnected";
}
}
some say that its not valid as per apple and you have to use the SystemConfiguration Framework, Please let me know what needs to be done.
Also i personally think that what i am doing in the above code is not proper as if one day google may also be down due to maintenance or some other factors.
Also if you could provide me a link where i could display the name of the WIFI network then it would be really cool.
I searched the internet then i got these Reachability.h code which again is a bouncer as i wana learn the concepts not copy paste them
Thanks and Regards
Building on top of what Raxit mentions, I use the following code (extracted from the reachability example mentioned by Raxit) to check for internet access in my application delegate:
- (BOOL)isReachableWithoutRequiringConnection:(SCNetworkReachabilityFlags)flags
{
BOOL isReachable = flags & kSCNetworkReachabilityFlagsReachable;
BOOL noConnectionRequired = !(flags & kSCNetworkReachabilityFlagsConnectionRequired);
if ((flags & kSCNetworkReachabilityFlagsIsWWAN)) {
noConnectionRequired = YES;
}
return (isReachable && noConnectionRequired) ? YES : NO;
}
- (BOOL)isHostReachable:(NSString *)host
{
if (!host || ![host length]) {
return NO;
}
SCNetworkReachabilityFlags flags;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [host UTF8String]);
BOOL gotFlags = SCNetworkReachabilityGetFlags(reachability, &flags);
CFRelease(reachability);
if (!gotFlags) {
return NO;
}
return [self isReachableWithoutRequiringConnection:flags];
}
- (BOOL)connectedToNetwork {
return [self isHostReachable:#"www.hostyoureallycareabouthavingaconnectionwith.com"];
}
You can use the reachability code provided by Apple. It is sample code. you can find whole detail regarding internet connection. This is the link http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html

Iphone How to know if Bluetooth headset connected

using iphone sdk 3.1.2.
Is there anyway of knowing if a Bluetooth headset is connected to the device? Don't need any info except if its connected or not. This is different from knowing if one was plugged in or not which one can do via a Property Listener of an Audio Session.
Thanks
Call this method to find out the bluetooth headset is connected or not.
First import this framework #import <AVFoundation/AVFoundation.h>
- (BOOL) isBluetoothHeadsetConnected
{
AVAudioSession *session = [AVAudioSession sharedInstance];
AVAudioSessionRouteDescription *routeDescription = [session currentRoute];
NSLog(#"Current Routes : %#", routeDescription);
if (routeDescription)
{
NSArray *outputs = [routeDescription outputs];
if (outputs && [outputs count] > 0)
{
AVAudioSessionPortDescription *portDescription = [outputs objectAtIndex:0];
NSString *portType = [portDescription portType];
NSLog(#"dataSourceName : %#", portType);
if (portType && [portType isEqualToString:#"BluetoothA2DPOutput"])
{
return YES;
}
}
}
return NO;
}
Have you looked at the: kAudioSessionProperty_AudioRoute?
Also see this post:
How can I find out if an external headset is connected to an iPhone?