SORU
11 Ocak 2011, Salı


iPhone - ankete altta yatan olaylar için

Uzunca bir süre iPhone uygulamam bir şekilde her X dakikada bir veri sayaçları kontrol etmek için anket bekliyordum. Arka Plan Yürütme belgelere ve birkaç deneme uygulamalar kadar okuduktan sonra bu imkansız plan API kötüye olmadan görevden alırdım.

Geçen hafta tam da bunu yapıyor bu uygulamayı buldum. http://itunes.apple.com/us/app/dataman-real-time-data-usage/id393282873?mt=8

Arka planda çalışır ve kullandığın Hücresel/WiFi veri sayısını izler. Geliştirici izleme konumunu değiştirir ama konum servisleri simgesi bir gereklilik olduğunu düşündüğüm bir uygulama çalışırken görünür değil, onun uygulama kayıt olduğunu sanıyorum.

Herkes bu yapılabilir nasıl herhangi bir ipucu var mı?

CEVAP
26 Ocak 2011, ÇARŞAMBA


Bu davranış, çok gördüm. Bir çok şey denedikten sonra yardımcı olabilecek iki şey keşfettim. Ama yine de bu Gözden Geçirme sürecini etkileyebilecek nasıl emin değilim.

Eğer arkaplan özelliklerinden biri kullanıyorsanız, app çıkın, sonra tekrar arka plan (sistem tarafından) iOS tarafından açılacak. Bu daha sonra taciz edeceğiz.

Benim durumumda VoIP arkaplan benim plist etkin kullandım. Tüm kodu burada AppDelegate yapılır:

// if the iOS device allows background execution,
// this Handler will be called
- (void)backgroundHandler {

    NSLog(@"### -->VOIP backgrounding callback");
    // try to do sth. According to Apple we have ONLY 30 seconds to perform this Task!
    // Else the Application will be terminated!
    UIApplication* app = [UIApplication sharedApplication];
    NSArray*    oldNotifications = [app scheduledLocalNotifications];

     // Clear out the old notification before scheduling a new one.
    if ([oldNotifications count] > 0) [app cancelAllLocalNotifications];

    // Create a new notification
    UILocalNotification* alarm = [[[UILocalNotification alloc] init] autorelease];
    if (alarm)
    {
        alarm.fireDate = [NSDate date];
        alarm.timeZone = [NSTimeZone defaultTimeZone];
        alarm.repeatInterval = 0;
        alarm.soundName = @"alarmsound.caf";
        alarm.alertBody = @"Don't Panic! This is just a Push-Notification Test.";

        [app scheduleLocalNotification:alarm];
    }
}

ve kaydı yapılır

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

    // This is where you can do your X Minutes, if >= 10Minutes is okay.
    BOOL backgroundAccepted = [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{ [self backgroundHandler]; }];
    if (backgroundAccepted)
    {
        NSLog(@"VOIP backgrounding accepted");
    }
}

Şimdi sihirli olur: VoIP-Yuva kullanmıyorum. 10 Dakika (bazen daha önce) benim zamanlayıcılar ve önceki çalışan basamakları kısa bir süre için yürütülmekte olan keşfettim Sonra. ama geri güzel bir yan etkisi sağlar bu 10 Dakika: (..) Senin kod biraz NSLog koyarsanız bu görebilirsiniz. Bu kısa "uyandırma" bir süre kod çalıştırır. anlamına gelir Apple'a göre yürütme kalan süre 30 saniye var. İş parçacıkları gibi arka plan kod yaklaşık 30 saniye için idam ediliyor herhalde. Bu "bazen" bir şey sor. gerekiyorsa yararlı bir kod.

Doktor tüm arka plan görevleri (VoIP, ses, konum güncellemeleri) uygulaması sona erdirildi otomatik olarak arka planda yeniden başlatılacak diyor. VoIP uygulamaları arkaplanda önyükleme sonra otomatik olarak başlatılır!

Bu davranış, taciz, uygulama çalıştırma gibi yapabilirsiniz "". sonsuza dek Bir arka plan işlemi için (yani VoIP) kayıt. Bu app ermesinden sonra yeniden neden.

Şimdi "Görev" kodu. bitirilmeli bazı yazma Apple'a göre bir süre (5 saniye?) görevleri tamamlamak için bıraktı. Bu CPU zamanı olması gerektiğini keşfettim. Eğer hiçbir şey yapmazsanız, app hala idam ediliyor! bu demek oluyor ki: Apple eğer işinizi bitirdiyseniz bir expirationhandler çağrı öneririm. Aşağıdaki kodu expirationHandler bir yorum olduğunu görebilirsiniz. Bu uygulamayı sistem uygulaması çalışıyor olması izin verdiği sürece çalışan neden olur. Tüm zamanlayıcılar ve ipler iOS uygulaması sona kadar çalışmaya devam.

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

    UIApplication*    app = [UIApplication sharedApplication];

    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];


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

    // you can do sth. here, or simply do nothing!
    // All your background treads and timers are still being executed
    while (background) 
       [self doSomething];
       // This is where you can do your "X minutes" in seconds (here 10)
       sleep(10);
    }

    // And never call the expirationHandler, so your App runs
    // until the system terminates our process
    //[app endBackgroundTask:bgTask];
    //bgTask = UIBackgroundTaskInvalid;

    }); 
}

-Zaman CPU ile ilgili bir yedek ve uygulaması daha uzun çalışır! Ama kesin olan bir şey var: uygulamanız bir süre sonra iptal edilecektir. Ama diğerlerinin VoIP veya bir uygulama, tescil, çünkü sistem arka plan işlemini yeniden arka plan uygulaması yeniden ;-) Bu PingPong ile altta yatan bir çok şey yapabilirim. ama unutma CPU zamanı çok boş olması. Ve tüm verileri kaydetmek, görüşleriniz geri yüklemek için uygulamayı bir süre sonra iptal edilecektir. Hala çalışıyor görünmesi için, geri "" uyandırma sonra. devlet son içine atlamak gerekir

Bu daha önce bahsettiğiniz uygulamalar yaklaşımdır, ama bana uyar mı bilmiyorum.

Yardımcı olabilir umuyoruz

Güncelleme:

BG görevin zaman ölçme sonra, bir de sürpriz vardı. BG Görevin 600 saniye ile sınırlıdır. Bu VoIP minimumtime tam minimum zaman (: 600 setKeepAliveTimeout).

BU kod, "sonsuz" yürütme arka plan: . içine götürüyor

Başlık:

UIBackgroundTaskIdentifier bgTask; 

Kod:

// if the iOS device allows background execution,
// this Handler will be called
- (void)backgroundHandler {

    NSLog(@"### -->VOIP backgrounding callback");

    UIApplication*    app = [UIApplication sharedApplication];

    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];

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

    while (1) {
        NSLog(@"BGTime left: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
           [self doSomething];
        sleep(1);
    }   
});     

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

    BOOL backgroundAccepted = [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{ [self backgroundHandler]; }];
    if (backgroundAccepted)
    {
        NSLog(@"VOIP backgrounding accepted");
    }

    UIApplication*    app = [UIApplication sharedApplication];

    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];


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

        while (1) {
            NSLog(@"BGTime left: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
           [self doSomething];
           sleep(1);
        }    
    }); 
}

Uygulamanız doldu sonra, VoIP expirationHandler sadece uzun süren bir yeniden görev yeri adı verilecek. Bu görev 600 saniye sonra sonlandırılacaktır. Ama yine uzun soluklu görev, vb başka bir başlayan son kullanma işleyicisi, bir çağrı olacak. Şimdi sadece App ön arka oluyor hava durumunu kontrol etmek gerekiyor. Sonra bgTask kapatın ve bitirdiniz. Belki heyecanla beklediğim yapabilirsiniz. uzun süren bu görevden expirationHandler içinde böyle. Sadece dene. Klavyeni kullan, olur... bir aksilik Var!

Güncelleme 2:

Bazen bazı şeyleri basitleştirmek yardımcı olur. Benim yeni yaklaşım bu

- (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     
    }); 
}

Bu çalışıyorolmadanVoIP kesmek. Belgelerine, son kullanma işleyicisi göre (bu durumda benim 'expirationHandler' blok) yürütme zaman içinde ise idam edilecek. Blok bir değişken bloğu tanımlayarak, bir özyinelemeli olarak uzun süren görevi yeniden aşımı işleyicisi içinde başlayabilir. Bu sonsuz yürütme içine çok olur.

Eğer uygulama ön plan tekrar girerse görevin sona erdirmek için farkında olmalısınız. Ve eğer artık ihtiyacınız olursa. görevi Sonlandır.

Benim kendi deneyim için bir şey ölçtüm. GPS radyo olması ile konum geri çağrıları kullanarak şarjım çok hızlı bir şekilde emiyor. Mesajınız hangi yaklaşım kullanarakGüncelleme 2neredeyse hiç enerji alıyor. "" Bu daha iyi bir yaklaşım. userexperience göre Diğer Uygulamalar bu gibi davranışını gizleme çalışma işlevi GPS arkasında belki de ...

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Amir Parmar

    Amir Parmar

    25 Kasım 2010
  • foreignimage

    foreignimage

    13 HAZİRAN 2006
  • TheDroidDemos

    TheDroidDemo

    15 ŞUBAT 2011