setKeepAliveTimeout und BackgroundTasks
Habe ich eine große Kopfschmerzen mit dem Thema. Ich arbeite an einer Anwendung, muss die Umfrage auf einem webserver regelmäßig, um zu prüfen, ob neue Daten. Auf der Grundlage der zurückgegebenen Informationen, ich möchte die push-lokale Benachrichtigung an den Benutzer.
Ich weiß, dieser Ansatz ist etwas anders als dargestellt von Apple, in dem ein remote-server macht die Arbeit, schob ein remote-Benachrichtigung, basierend auf APNS. Es gibt jedoch viele Gründe die kann ich nicht nehmen, diesen Ansatz in Betracht. Einer für alle, ist die Benutzer-Authentifizierung Mechanismus. Der remote-server aus Gründen der Sicherheit nicht berücksichtigt werden die Anmeldeinformationen des Benutzers. Alles, was ich tun kann, ist, bewegen Sie den login und das abrufen Kern, dem client (iPhone).
Bemerkte ich, dass Apple bietet eine Möglichkeit für Anwendungen, wake-up und halten, eröffnet eine Socket-Verbindung (dh. eine VoIP-Anwendung).
Also fing ich an zu untersuchen, in dieser Art und Weise. Hinzugefügt die erforderlichen Informationen in der plist, ich bin in der Lage, "wake" meine Bewerbung, mit so etwas in meiner appDelegate:
[[UIApplication sharedApplication] setKeepAliveTimeout:1200 handler:^{
NSLog(@"startingKeepAliveTimeout");
[self contentViewLog:@"startingKeepAliveTimeout"];
MyPushOperation *op = [[MyPushOperation alloc] initWithNotificationFlag:0 andDataSource:nil];
[queue addOperation:op];
[op release];
}];
Die NSOperation, dann startet eine hintergrund-task mit dem folgenden code-block:
#pragma mark SyncRequests
-(void) main {
NSLog(@"startSyncRequest");
[self contentViewLog:@"startSyncRequest"];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"exipiration handler triggered");
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
[self cancel];
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSMutableURLRequest *anURLRequest;
NSURLResponse *outResponse;
NSError *exitError;
NSString *username;
NSString *password;
NSLog(@"FirstLogin");
anURLRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:webserverLogin, username, password]]];
[anURLRequest setHTTPMethod:@"GET"];
[anURLRequest setTimeoutInterval:120.00];
[anURLRequest setCachePolicy:NSURLRequestReloadIgnoringCacheData];
exitError = nil;
NSData *tmpData = [NSURLConnection sendSynchronousRequest:anURLRequest returningResponse:&outResponse error:&exitError];
[anURLRequest setTimeoutInterval:120.00];
if(exitError != nil) { //somethings goes wrong
NSLog(@"somethings goes wrong");
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
[self cancel];
return;
}
//do some stuff with NSData and prompt the user with a UILocalNotification
NSLog(@"AlltasksCompleted");
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
[self cancel];
});
}
}
Der obige code scheint zu funktionieren (manchmal), aber viele andere stürzt meine Anwendung mit den folgenden log-Informationen:
Exception Type: 00000020
Exception Codes: 0x8badf00d
Highlighted Thread: 3
Application Specific Information:
DemoBackApp[5977] has active assertions beyond permitted time:
{(
<SBProcessAssertion: 0xa9da0b0> identifier: UIKitBackgroundCompletionTask process: DemoBackApp[5977] permittedBackgroundDuration: 600.000000 reason: finishTask owner pid:5977 preventSuspend preventIdleSleep
)}
Elapsed total CPU time (seconds): 0.010 (user 0.010, system 0.000), 100% CPU
Elapsed application CPU time (seconds): 0.000, 0% CPU
Für diejenigen, die Fragen, ja. Ich habe versucht, die Async NSURLConnection Ansatz, zu. Egal. Es crash das gleiche, auch wenn ich einen asynchronen Ansatz mit timeout-handler und didFinishLoading:WithError.
Ich bin stecken. Alle Hinweise sind hoch geschätzt.
InformationsquelleAutor valvoline | 2011-01-24
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist ein Alter thread, aber rechtfertigen kann ein update.
Ab iOS 6, das ist das Verhalten, das ich bin, zu sehen, mit der die VoIP-timer-hintergrund-Methoden, wie in diesem thread diskutiert:
Hoffe, das hilft!
InformationsquelleAutor mattv123
Beim Aufruf
-setKeepAliveTimeout:handler:
haben, erhalten Sie nur maximal 30 Sekunden alles und anhalten. Sie sind nicht die gleichen hintergrund Nachfrist, wie Sie würde, wenn Ihre Anwendung zunächst den übergang zum hintergrund. Das bedeutete für den Abschluss von lang Laufenden Aufgaben, heruntergefahren Dinge nach unten, etc.Mit der VOIP-callback, die Sie gerade senden soll, was auch immer ping-Paket-Sie senden müssen, um Ihren Dienst zu halten, die Netzwerk-Verbindung am Leben und nicht wegen Zeitüberschreitung abgebrochen. Nach 30 Sekunden, unabhängig von der Ausgangspunkt neuer hintergrund-tasks, wenn Ihre Anwendung noch ausgeführt wird, du wirst gekündigt.
Es ist auch wichtig zu beachten, dass, wenn Sie nicht tatsächlich eine VOIP-Anwendung oder wenn Sie nichts tun, während die VOIP-callback-Fenster, dass nicht mit, dass Ihr Netzwerk-verbindungen öffnen Sie Ihre app wird abgelehnt werden aus dem app store. Wenn Sie die stay-active-flags (VOIP, Musik im hintergrund, navigation), dann testen Sie es ziemlich streng, um sicherzustellen, dass es nur macht, was es ist geflaggt zu tun, während in der hintergrund. Dabei jede Art von HTTP-GET-Anforderung, und warten auf ein großes Daten-update zurück zu kommen ist fast garantiert, um Ihre app abgelehnt.
EDIT: Wie bereits von Patrick in den Kommentaren, die aktuelle Zeitspanne, die der block ist gegeben, ausgeführt wurde, reduzierte sich von 30 Sekunden bis 10 Sekunden, mit iOS 5. Es ist eine gute Idee zu halten ein Auge auf die Zeiten, wenn Sie re-link Ihre Anwendung für eine neue version des SDK, zumindest immer schnell prüfen, ob die Dokumente im Fall Sie ' ve wurde aktualisiert (mit iOS 6 kommen, kann diese Zahl verändert werden).
Das es mal nicht funktioniert, bist du hintergrund-task ist offensichtlich zu lange dauert. Die docs sagen wir 30 Sekunden, aber vielleicht ist die weiche Nummer und das OS wirklich geben Ihnen 10 Minuten, ich bin mir nicht sicher. Wir wissen aber, dass etwas blockiert irgendwann und dein Ding ist nicht vollständig, und da die VIOP wurde entwickelt für eine schnelle Prüfung, ist es möglich, dass die Fehlerbehandlung von der OS ist verwirrt (wie den Aufruf nicht Ihre Stornierung block oder so).
Sie haben keine Einzelheiten über das, was Sie benötigen, in dieser VOIP-Fenster? Es tut Zustand, dass irgendwo öffentlich?
Für diejenigen Fragen über timeouts, RTFM hier: developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/... Er sagt, es ist ein minimum von 600 Sekunden zwischen den keepalives, und Sie haben nur 10 Sekunden, um die Aktionen auszuführen, die Sie benötigen, nicht 30.
Vielen Dank für das hinzufügen der link zu dem Dokument. Wenn diese Antwort geschrieben wurde, die app wurde gegeben 30 Sekunden zu tun, was für Pflege es benötigt auf seiner voip-Buchse. Das war reduziert auf 10 Sekunden, mit iOS 5. Anwendungen verknüpft mit dem iOS 4 SDK sind noch immer 30 Sekunden, während neue Anwendungen sind nur 10.
InformationsquelleAutor Jason Coco
Nur zu aktualisieren, die dieses Verhalten für iOS7.
Aufgabe Zeit, so berichtet backgroundTimeRemaining. Aber es hält
reagiert bei 5 Sekunden, bevor diese Zeit abläuft, wie berichtet, von
backgroundTimeRemaining.
Sekunden Vordergrund, gefolgt von 60 Sekunden hintergrund-timer
gemeldet von backgroundTimeRemaining. Außerdem reagiert nicht mehr auf 5 Sekunden, bevor diese Zeit abläuft, so berichtet backgroundTimeRemaining.
Also auf iOS7 erhalten Sie 65 Sekunden Verarbeitungszeit pro 10 Minuten.
InformationsquelleAutor d0n13
Es scheint, dass Sie möglicherweise in der Lage zu kombinieren, die keep-alive-timeout-handler durch piggy-backing einen Antrag für die finite-hintergrund-task ausgeführt wird, wenn Sie aufgerufen. Dies wird Ihnen ermöglichen, eine volle 10 Minuten, jedes mal, wenn der VOIP-keep-alive-handler aufgerufen wird (vice die üblichen 10-30 Sekunden).
Immer noch das gleiche problem wie oben-in, müssen Sie den VOIP-flag in der plist zu Unterwerfen, und Apple ist nicht wahrscheinlich, Ihre Anmeldung zu akzeptieren, wenn Sie haben, die Flagge und sind nicht wirklich eine VOIP-Anwendung, aber für die interne Verteilung (enterprise oder anderweitig), diese Lösung sollte funktionieren, geben Sie hintergrund Zeit.
In meinen tests, die 10-Minuten-endliche Ausführung-timer wird zurückgesetzt, jedes mal, wenn der VOIP-handler aufgerufen wird (ob oder ob nicht der Benutzer hat die Applikation auf der Vorderseite, da, dann), und das sollte bedeuten, dass Sie könnte eine Umfrage Ihre server auf unbestimmte Zeit, während im hintergrund einmal alle 600 Sekunden (10 Minuten) und die polling-Vorgang kann bis zu 10 Minuten vor dem schlafen gehen (also nahezu Konstanten hintergrund, wenn das ist, was Sie benötigen).
Wieder, nicht wirklich eine option für den App-Store, es sei denn, Sie können sich davon überzeugen, dass Sie VOIP.
Ja, jedes mal, wenn setKeepAliveTimeout heißt, ich erstelle einen neuen finite-hintergrund die Aufgabe (das scheint um einen frischen 10 Minuten zu laufen).
InformationsquelleAutor BadPirate