Background JavaScript with PhoneGap / Cordova and iOS

I was recently working on a project where I needed the ability to do some background processing for audio on iOS. I started out writing a lot of native Objective-C to accomplish this, but in the process discovered that I could actually do almost all of my processing in JavaScript by simply starting a background task for a period of time. It seems that while a background task is active, all threads are allowed to process with no real restrictions! It’s quite incredible really, as iOS is often loathed for its limitations on multitasking.

Now take note… Apple may feel differently about this than you probably do. They have a typically strict set of guidelines around when you are allowed to background task, and often these states must be declared in your Info.plist. These could be tracking location, or playing background audio. Take them to heart – they are really a good thing designed to prevent abuse of battery life and network usage. Check out the iOS App Programming Guide and the Technology Usage guidelines.

Generally my operations maybe only needed 5 to 30 seconds of background time in case a user was impatient and tabbed out of the application before a buffer was filled or an AJAX request was completed. In any case, having just a few spare seconds of background time can be a real help to your application!

I wrote up a small plugin for PhoneGap to help take care of this. Here is what most of the magic on the plugin side looks like:

- (void)doBackgroundTimeLoop
{
    __block UIBackgroundTaskIdentifier task;
    UIApplication* app = [UIApplication sharedApplication];
    task = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:task];
        task = UIBackgroundTaskInvalid;
    }];
 
    while(YES){
        @synchronized(self){
            backgroundSecondsCounter--;
            NSLog(@"Remaining background seconds: %i", backgroundSecondsCounter);
            if (backgroundSecondsCounter <= 0)
                break; // Exit loop
        }
        [NSThread sleepForTimeInterval:1];
    }
 
    // End this background task now
    [app endBackgroundTask:task];
    task = UIBackgroundTaskInvalid;
}

 

This is a very basic use-case for background tasking. There’s only a single task running on a background thread that keeps all of your other threads alive. This may not be ideal for your app, and I also heard rumors that a single background task will expire after 15 minutes, regardless of whether you are finished or not. Keep this in mind while you program, as keeping the background operation alive too long could cause the entire thing to time out. Use it sparingly, only when needed, and free it up when it is complete. Be a good app citizen and treat your user’s phone (read: battery life) with respect!

Clone or download the plugin on GitHub

About James

I own this site. I love code. The end?
This entry was posted in Hacks, iOS, Javascript, Mobile, Programming. Bookmark the permalink.

14 Responses to Background JavaScript with PhoneGap / Cordova and iOS

  1. Luis says:

    Hi James, very interesting your post and your plugin!! I wonder if you actually confirmed that the single background thread ends in 15 minutes and what you suggest me to get the user geolocation every 30 minutes.
    My application is made ​​in PhoneGap and the idea is to prompt the user when it is in any risk area (assault, car theft, assault, etc.) even with the application closed.

    Thanks πŸ™‚

  2. Object Reference says:

    Could you please make the plugin version 3.0.0 compatible, it looks very interesting.

    Many Thanks πŸ™‚

  3. david says:

    I’ve just had a request for background porcessing and my research has led me here…. pg3.0 support isn’t a dealbreak, we can easily pull and use and older version of PG that allows the old-style plugins (v2.9). But I too am curious about the time limitations – 15min, is that the hard limit?

    thanks for sharing the plugin…

    • James says:

      Last I heard, the 15 minute limit was the hard limit per Apple’s documentation. You should check for yourself (and comment back!) if you find differently. I haven’t actually tested it myself.

  4. Perfect!!!

    It is very useful!!

  5. Wil says:

    Hi James,
    Does your app work with PhoneGap 3.1.0. It seems to be working but I am not sure how to make an javascript function run in a background thread using the call to BackgroundJS. I want to make the navigator.camera.getPicture function run in a background thread. Where do I place the statement BackgroundJS.SetBackgroundSeconds(30); in my code to put it into a background thread.

    Below is the code that I have try:

    function takePhoto(){
    BackgroundJS.SetBackgroundSeconds();
    navigator.camera.getPicture(
    displayPhoto,
    function(message) { navigator.notification.alert(
    ‘Image Capture Canceled.’, // message
    [], // callback
    ‘Image Capture’, // title
    ‘OK’ // buttonName
    );
    BackgroundJS.UnlockBackgroundTime();
    return false;
    },
    {
    quality : 60,
    destinationType : Camera.DestinationType = 1,
    sourceType : Camera.PictureSourceType.CAMERA,
    correctOrientation : true,
    targetWidth : 500,
    targetHeight : 500
    });
    }

    function displayPhoto(imageURI){
    currentImage = imageURI;
    var d = new Date();
    $(“#smallImage”).attr(“display”,”block”);
    $(“#reciept”).html(“”);

    if(action != “save”){
    db.transaction(function(tx){
    tx.executeSql(“SELECT photo FROM expenses where recordid =”+recordid,[],getPhotoName);
    });
    BackgroundJS.UnlockBackgroundTime();
    return true;
    } else {
    var d = new Date();
    var n = d.getTime();
    newFileName = n + “.jpg”;
    photo = newFileName;
    BackgroundJS.UnlockBackgroundTime();
    return true;
    };
    };

    Thanks in advance for you help.

    • Joseph says:

      Same problem. It’s missing some documentation, we do not even know how to use it. The whole javascript on the app is background-ed? Or what?

      • James says:

        It was several iOS versions back when I did this, but it seemed that the entire app keeps running. On iOS, there’s no partial suspend of applications. I discovered this because playing background audio would keep my JavaScript engine alive, even when the phone was locked.

  6. Chris Scott says:

    I use use this mechanism in my cordova-background-geolocation plugin.

    https://github.com/christocracy/cordova-plugin-background-geolocation

  7. arnold says:

    Thank you very much.

  8. xavier says:

    funciona en background , pero solo durante 8 minutos no mas y se garadece el aporte

Leave a Reply

Your email address will not be published. Required fields are marked *