Paused & Resumed events on Android

Because of the way Android works, it does not have Ti.App.paused and Ti.App.resumed events like iOS. On Android an app is a stack (task) of activities and you can even open another app’s activity within the task of another app. Those activities themselves have Ti.Android.Activity.pause and Ti.Android.Activity.resume events, but since Titanium 3.2 every window is heavy weight, which means it has its own activity. There is no way to tell if an activity paused because another window of the same app opened over it, or that the app moved to the background. This is not unique to Titanium Android apps, but an issue with JAVA Android apps as well.

Workaround

With the help of one of Ben Bahrenburg’s excellent modules, I’ve finally found a workaround that actually works pretty good. I use it to pause and resume app-wide background music when the app is moved to the background, while still allowing it to continue playing when new heavy windows open.

Ti.App.addEventListener('resumed', onResumed);
Ti.App.addEventListener('paused', onPaused);

if (OS_ANDROID) {
    var platformTools = require('bencoding.android.tools').createPlatform(),
        wasInForeGround = true;

    setInterval(function() {
        var isInForeground = platformTools.isInForeground();

        if (wasInForeGround !== isInForeground) {
            Ti.App.fireEvent(isInForeground ? 'resumed' : 'paused');

            wasInForeGround = isInForeground;
        }
    }, 3000);
}

You can change the interval to change the responsiveness of the workaround or even use Ben’s other ti.mely module to make sure the check is not delayed by other code on the single thread.

App imagineer: Imagining, Engineering & Speaking about Native mobile Apps with Appcelerator Titanium & Alloy • Meetup organizer • Certified Expert • Titan


Comments

  • jayesh

    my app is alarm manger kind not i set alarm and i move to background and
    i used https://github.com/benbahrenburg/benCoding.AlarmManager
    and register for background service but when it fire backgroundservice it gives current activity null . App not start from background

    alarmManager.addAlarmService({
    service:”com.custom.alarmapp.CustomalarmService”,
    year : dt.getFullYear(),
    month : dt.getMonth(),
    day : dt.getDate(),
    hour : dt.getHours(),
    minute : dt.getMinutes(), //Set the number of minutes until the alarm should go off
    userInfo : {
    “notificationData” : {
    date : selectedDateForDb.toString(),
    dbid : lastInsertedRow,
    alarmtimeid : alarmtime_id
    }
    }
    });

    and in my TiApp.xml

    below is my customalarm.js

    var service = Ti.Android.currentService;
    var serviceIntent = service.getIntent();
    //var userInfo = JSON.parse(serviceIntent.getExtra(“userInfo”));
    var playAlarm = function() {
    Titanium.API.info(‘————- Servvicve———‘);
    var activity = Ti.Android.currentActivity;
    var intent = Ti.Android.createIntent({
    action : Ti.Android.ACTION_MAIN,
    className : ‘com.custom.alarmapp.AlarmappActivity’,
    flags : Ti.Android.FLAG_ACTIVITY_CLEAR_TOP | Ti.Android.FLAG_ACTIVITY_NEW_TASK,
    });
    Titanium.API.info(‘————- activity———:’ + JSON.stringify(activity));

    intent.addCategory(Ti.Android.CATEGORY_LAUNCHER);
    activity.startActivity(intent);

    };
    playAlarm();
    Ti.Android.stopService(serviceIntent);

    // here activity is null

  • Fokke Zandbergen Post author

    Sorry, I don’t get your question @jayesh ?!

  • Varun

    i need to run a service in background to detect a javascript event fired in the native android browser. How do i do it?

  • Kristjan Mikaelsson

    Hi.
    This does not seem to work in Ti 3.4

    This solution works perfectly with hevyweight(default) windows:
    https://gist.github.com/kristjanmik/aefc77b5b05e792ecdd2

  • Fokke Zandbergen Post author

    I just tested it with 3.4.0.GA and it works for me.

  • Jonathan Coetzee

    Is this really the best option to check for background event? Seems a bit messy to me. Not to say that your method is bad cuz I can’t really think of another way, this really seems like this should be something that Android SDK should cater for.

    Off the top of my head what about something like the following, assuming you always open a new window before closing the previous window: If you have a global flag and you set the flag to true on activity resume (I’m assuming this will fire when the activity is launched as well?). Then on activity pause you check the flag, if it’s true you must have just opened a new activity and you continue normally, if however it’s false then you are pausing this activity without having opened another one and this is when you would run your code to handle the app going into the background. Have no idea if this actually will work, would appreciate your input.

  • Timan Rebel

    I created a small javascript library that listens to the Activity callbacks and fires the paused/resumed events appropriately. Instead of a 3 sec pull approach, this is a push approach.

    https://github.com/timanrebel/AndroidContext

  • Jason Priebe

    I have found that Timan’s approach handles the screen off/on situation, whereas the Android.Tools approach does not generate paused and resumed events when the screen is turned off and on.

  • Fokke Zandbergen Post author

    Nice one Timan! I’ve used the above in a case where not all code in the app was mine (some 3P widgets) and I didn’t want to make changes to that code.

    But if you can, yours is indeed more efficient.

  • Fokke Zandbergen Post author

    The thing is… Android doesn’t cater ;)

  • FC

    Nice workaround. Works with 3.5.1.GA.
    Thank you

  • Andrey

    Thank you so much!!!You really helped me