Titanium Community Questions & Answer Archive

We felt that 6+ years of knowledge should not die so this is the Titanium Community Questions & Answer Archive

What's wrong with setInterval?

Right so if there's one single thing that is most important out of everything else for a programming language/framework it's the ability to have accurate reliable timers.

So…..who wants a go at solving this puzzle:

setInterval (seems) to work fine when the phone is on. If the display switches of (times out) and the phone locks the timer seems to stop running (according to my mental counting). So i thought "would titanium after all this time still not have one of the most fundamental pieces of functionality - ability to keep track of time regardless of phone state". To test this i added a Ti.Media.vibrate() call inside my setInterval loop and set it for 420sec. Off i switch the phone and hey! It vibrates (more or less on time with every tick). So that's odd i thought - timer works with vibrate, but not without. Until……After leaving it running a few minutes i suddenly noticed the vibrations stopped.

There's more.

So the natural conclusion is - something times out and the app gets suspended (since for some unknown reason no one though a timer was important enough to fix yet - i guess titanium isn't designed for anything too serious). So i was about to accept this and make the switch to some other framework (or just write it in Java) when all of a sudden - my phone started to vibrate again. But the strange thing is that the vibrations were not uniform - it seemed like the phone was seriously lagging. It would miss a tick and then try to catch up. Sometimes it would vibrate perfectly in time. After a few vibrations it dies again. Sometimes it takes less than 10 seconds before i feel it try to vibrate again. Other times it will just do nothing for a minute or two and start to vibrate again. Usually it only manages 2-3 vibrates before dying.

So the question is… Wtf? Either it works or it doesn't. Either setInterval will fire on time every time regardless of phone state or it will suspend when the phone goes to sleep. So whats up with the odd on/off flaky thing?

Obviously I cant test any of this via the emulator (no vibrate, vm never actually goes into anything I'd call a "sleep" state - the best i could do is make it auto lock). My development device is a Samsung Galaxy S 2.1

— asked December 1st 2010 by Alex Borisov
  • android
  • idle
  • lock
  • mobile
  • setinterval
  • sleep
  • timer
3 Comments
  • An update. I have a separate application that uses the setInterval timer to control patterned volume changes to a playing sound object - same principle calling a function every 50ms. I have run the application for about 2 hours - with the display off and in standby, and the changes in volume ran like clockwork. I have a sneaky suspicion the sound playback has something to do with this. I will try to create a dummy empty sound object and start playing it when the timer starts running. Hopefully it wont impact the battery/performance too much since it's empty (I'll accept the memory loss incurred for object instantiation). If this works i will post an update, but the hackiness of the solution just drains all desire to use titanium for anything serious (or commercial). Ahh well. The stuff i write is free so w/e.

    — commented December 14th 2010 by Alex Borisov
  • UPDATE: I was correct. By creating a looping sound object (of an empty 1 second track) the timer now runs as it should and fires on time. I've let my test case run 3 simultaneous timers for over an hour and the vibrate() function fired every single second.

    For reference: Go to audacity, go to generate and select "silence". Generate like 1 second of silence and export it (i went with ogg, level 1 encoding). Now create a new Sound object using your new dummy track as the source (here's how i did it):

    var dummySound = Titanium.Media.createSound ({
        url:'assets/audio/blank.ogg',
        audioSessionMode: Ti.Media.AUDIO_SESSION_MODE_PLAYBACK,
        allowBackground: true,
        volume: 0
    });
    dummySound.looping = true;
    dummySound.play();
    

    Now your timers will fire regardless of your phone state. It will probably not be as battery friendly as a native quality timer (since that will use optimisations and will not cause empty data to be send to the sound output), but short of writing a service (thanks to the long overdue 1.5 release) which i think is a little overkill, this is the best i can come up with. I'm banking with the Android system being smart enough that it wont stream empty data to the sound buffer (or at the very least if the volume is 0) so without doing any serious low level profiling i cannot give a solid answer as to this hacks efficiency. Perhaps a native module thanks to the new TI SDK will make all this redundant.

    — commented December 14th 2010 by Alex Borisov
  • Thanks for your detailed comments and follow-up on this issue. I was noticing problems with the timer as well, and your notes confirmed my suspicions.

    Also, as someone who has been developing a very large application since before Ti 1.0, I can greatly sympathize with your frustrations. I've had to implement countless work-arounds of this nature, and the devs don't seem interested in user submitted bug reports.

    — commented February 5th 2011 by Mike Dosey

2 Answers

  • Android Timer (even when the phone goes to sleep)

    When the phone goes to sleep, the app is “paused” and therefore, the timer is paused. To solve this issue on Android, I added the WAKE_LOCK permission to tiapp.xml:

    (…)
        <android xmlns:android="http://schemas.android.com/apk/res/android">
            <manifest android:versionName="1.0.0">
                <uses-permission android:name="android.permission.WAKE_LOCK" />
            </manifest>
            <services>
                <service type="interval" url="myservice.js"/>
            </services>
        </android>
    (…)
    

    I am using an interval service that updates a progress bar; for an example, please look at ‘examples/android_services.js’ in the Kitchen Sink.

    Iphone Timer

    I use the ildeTimerDisabled

    Ti.App.idleTimerDisabled = true; // to disable going to sleep (iPhone only)    
    Ti.App.idleTimerDisabled = false; // to re-enable it
    

    Hope this helps.

    — answered January 16th 2012 by Gregori Faroux
    permalink
    0 Comments
  • Alex,

    I think the basic problem is not with Titanium. It is that timers under javascript are never guaranteed to fire at regular intervals. See this page:

    http://ejohn.org/blog/how-javascript-timers-work/

    Also, since you are trying this under Android, be aware that in Titanium SDK 1.4.x there are many issues with Android which are addressed in the 1.5.0 release.

    However, it is still in beta but you could try one of the nightly builds and see if it works better for you. See this page:

    http://developer.appcelerator.com/doc/mobile/get_continuous_builds

    — answered December 1st 2010 by Doug Handy
    permalink
    4 Comments
    • I would say this: even if it's not Titanium misfiring the intervals, I'd submit that it should be documented in the docs as a limitation of the framework (i.e. JS dependency).

      The Titanium framework sounds promising, but it does lack support for crucial elements of game development.

      — commented December 1st 2010 by Toord Bucket
    • Agreed with the game development bit. It's a shame - I love the simplicity of writing apps with titanium, but i have just 1 project out of a dozen that i could even get to RC stage since the rest are all stalled due to limitations and i don't have the time to rewrite them in java.

      — commented December 14th 2010 by Alex Borisov
    • Also, I tested this problem with 1.5 and it was still an issue. For now I am going with my little hack I posted above. TI SHOULD have a basic reliable and accurate timer. It's a programming staple like a resistor in an electric circuit. If the JS one wont cut it due to design limitations, a module that links to a native java timer should be created. I'm waiting for the how-to on custom Android modules for 1.5, but i cannot imagine it being more than a few lines of code. Suffice to say i will write one if no one else will.

      — commented December 14th 2010 by Alex Borisov
    • Thank you for that one, tried it and its working.
      accelerator team, your apps on android will have poor power performance(timer ? its like not supporting a button ….).

      — commented December 29th 2011 by eran shlomo
The ownership of individual contributions to this community generated content is retained by the authors of their contributions.
All trademarks remain the property of the respective owner.