4

I am building an app that monitors the position of the user, and sends it via a socket to our server. On app startup the app connects to the socket on our server, and are we able to send data to the server.

But when the user changes from cell to wifi, or so, the connection drops. I'm trying to figure out how to simply reconnect (automatic), but I can't find out how. Can someone help me?

The code I'm using now (LocationRecorder.m):

//
//  LocationRecorder.m
//

#import "LocationRecorder.h"
#import <Cordova/CDV.h>
#import <coreLocation/CoreLocation.h>
#import <Foundation/Foundation.h>

@implementation LocationRecorder

@synthesize locationManager;

NSInputStream *inputStream;
NSOutputStream *outputStream;

- (void)startUpdates
{
    // this only runs once when the app starts up
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;

    [locationManager startUpdatingLocation];
    [locationManager startUpdatingHeading];

    // connect to the socket
    [self initNetworkCommunication];

    // set a timer for every 5 seconds
    [NSTimer scheduledTimerWithTimeInterval:5
                                     target:self
                                   selector:@selector(timerInterval:)
                                   userInfo:nil
                                    repeats:YES];
}

- (void)timerInterval:(NSTimer *) timer
{
    CLLocation *location    = [locationManager location];

    // process location data
    [self processLocationData:location];
}

- (void)processLocationData:(CLLocation *)location
{
    // format all the data to prepare it for sending it to the server

    NSString *response  = [NSString stringWithFormat:stringFormat,
                           utctime,
                           utcdate,
                           lat,
                           lng,
                           alt,
                           speed,
                           heading,
                           imei,
                           numsat,
                           battery,
                           cellno];

    //NSLog(@"%@", @"tx");

    NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];

    // check for connection
    if ([outputStream streamStatus] != NSStreamStatusOpen) {
        NSLog(@"%@", @"reconnecting...");
        [outputStream open];
    }
    [outputStream write:[data bytes] maxLength:[data length]];
}

- (void)initNetworkCommunication
{
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;

    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"***.***.***.***", 9000, &readStream, &writeStream);

    outputStream = (NSOutputStream *)writeStream;
    // we don't initialize the inputStream since we don't need one (the server does not (yet) talk back)

    [outputStream setDelegate:self];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream open];
}

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
    switch (streamEvent)
    {
        case NSStreamEventNone:
            // can not connect to host, no event fired
            break;

        case NSStreamEventOpenCompleted:
            // connected!
            NSLog(@"%@", @"connected to socket");
            break;

        case NSStreamEventErrorOccurred:
            // Connection problem
            NSLog(@"%@", @"connection lost");
            [theStream open]; //this does not work :-(
            break;

        case NSStreamEventEndEncountered:
            // connection closed
            [theStream close];
            [theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [theStream release];
            theStream = nil;
            break;

        default:
            // unknown or untracked event
            break;
    }
}

@end
rmaddy
  • 314,917
  • 42
  • 532
  • 579
George Boot
  • 585
  • 2
  • 8
  • 17
  • You need to hold the state of the connection. When you want to write to the server and you are disconnected you need to reconnect. It's pretty simple I think? – trojanfoe May 20 '13 at 08:33
  • Please see my changed code above. This is the only way I could come up with, but this does not work. – George Boot May 20 '13 at 08:45
  • 1
    I assume that you have to close the stream in the case of a network error, and reopen it by calling `initNetworkCommunication` again. – Martin R May 20 '13 at 08:50

1 Answers1

1

Credits to Martin R for his simple solution.

I added [outputStream close] to NSStreamEventErrorOccurred, and before I send data to the socket in processLocationData I added the following code:

// check for connection
if ([outputStream streamStatus] != NSStreamStatusOpen) {
    NSLog(@"reconnecting...", nil);
    [self initNetworkCommunication];
}
George Boot
  • 585
  • 2
  • 8
  • 17