문제

I have an iPhone chat app using XMPP with an EJABBERD server that is setup to function correctly if the app goes into the background (by either hitting the home button or from lack of activity and then the screen goes black) and then continues to function correctly when brought to the foreground.

The app works fine on an iPad when going into the background and back to the foreground, but when I run the app on an iPhone 4S, about an hour after the app has gone into the background, the app goes Offline from the XMPP server. Then when the iPhone 4S goes back into the foreground, the app is no longer connected to the XMPP server. In contrast, on the iPad the app has been running in the background for over a day and is still Online with the XMPP server.

I saw this SO post, but since the app has been running in the background on my iPad for over a day, and the app on the iPad is still Online with the XMPP server, I don't think that is the problem.

1)  Is this because the iPhone 4S goes into Airplane mode after some time?

2)  If the answer to 1) is yes, is there a way for the app to programmatically stop the iPhone 4S from going into Airplane mode?

3)  Or is something else going on?

Update 1 -

The interesting thing is that the iPad can go offline on the XMPP server, but when the app on the iPad is brought to the foreground, XMPP works fine. But if the app on the iPhone 4S goes offline on the XMPP server, then when the app on the iPhone 4S is brought to the foreground, XMPP no longer works. Also the iPad goes offline quickly on the XMPP server, after 20 minutes or so, whereas the iPhone 4S takes a few hours to go offline. Maybe a different method of going offline is occurring between the iPad and the iPhone 4S?

I've tried playing around DEFAULT_KEEPALIVE_INTERVAL in XMPPStream.h as mentioned in this SO post, without success so far. In XXMPStream.h I have the code:

#if TARGET_OS_IPHONE
#define MIN_KEEPALIVE_INTERVAL      20.0 // 20 Seconds
#define DEFAULT_KEEPALIVE_INTERVAL 120.0 //  2 Minutes
#else
#define MIN_KEEPALIVE_INTERVAL      10.0 // 10 Seconds
#define DEFAULT_KEEPALIVE_INTERVAL 300.0 //  5 Minutes
#endif

Update 2 -

The other strange thing is that while the app is in the background on the iPhone 4, if the app on the iPad wants to chat with the iPhone 4, the iPad sends a Push Notification to the iPhone 4. This Push Notification brings the app on the iPhone 4 to the foreground, where the iPhone 4 tries to reconnect to the EJABBERD server but the iPhone 4 is no longer able to reconnect.

Update 3 -

The iPad only has Wifi whereas the iPhone 4 has Wifi and 4G cellular connections. So I thought maybe that is the difference. So I put the iPhone 4 into Airplane mode, and then connected with the Wifi, so the iPhone 4 was only using Wifi. But after 2-3 hours the iPhone 4 went offline with the EJABBERD server again.

도움이 되었습니까?

해결책

I finally found one solution to the problem via this SO post. Even though the iPhone 4 goes Offline from the EJABBERD server, when the app comes to the foreground, the app can reconnect to the EJABBERD server whereas previously the app couldn't reconnect.

Specifically I used the code

- (void)applicationDidEnterBackground:(UIApplication *)application {

UIApplication*    app = [UIApplication sharedApplication];

// it's better to move "dispatch_block_t expirationHandler"
// into your headerfile and initialize the code somewhere else
// i.e. 
// - (void)applicationDidFinishLaunching:(UIApplication *)application {
//
// expirationHandler = ^{ ... } }
// because your app may crash if you initialize expirationHandler twice.
dispatch_block_t expirationHandler;
expirationHandler = ^{

    [app endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;


    bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];
};

bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];


// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // inform others to stop tasks, if you like
    [[NSNotificationCenter defaultCenter] postNotificationName:@"MyApplicationEntersBackground" object:self];

    // do your background work here     
}); 
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top