Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-27896] TiAPI: Add ability to run in the background without UI

GitHub Issuen/a
TypeNew Feature
PriorityLow
StatusOpen
ResolutionUnresolved
Affected Version/sn/a
Fix Version/sn/a
ComponentsAndroid, iOS
Labelsandroid, background, ios
ReporterJoshua Quick
AssigneeJoshua Quick
Created2020-05-16T00:09:37.000+0000
Updated2021-02-22T18:51:07.000+0000

Description

*Summary:* The Titanium JS (JavaScript) runtime is currently tightly bound to the UI. The JS runtime is created when the native UI is created and the 1st script executed (the "app.js" or "alloy.js") is expected to immediately create a window. On Android, the JS runtime is terminated once all windows have been destroyed and a new JS runtime will be created when the app's UI has been re-launched. We should add a new feature which will create the Titanium JS runtime on app startup before it can natively host UI (if applicable) and keep the JS runtime running for the lifetime of the application process. On Android, this means destroying all UI will no longer terminate the JS runtime and a re-launch will re-use the existing JS runtime. This should be an opt-in feature since this may require the app developers to re-architect their app launch behavior. *Use-Cases:* * On iOS, allow app to run tasks in the background via [BGTaskScheduler](https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler?language=objc). * On Android, prevent JS runtime from being terminated after end-user backs out of all windows or OS forcibly destroys all windows but keeps app process alive. * On Android, allow developer to set up a BOOT_COMPLETED broadcast receiver to run backgrounding tasks after device boot-up. *New "tiapp.xml" property:* Setting this to true will enable this feature. The default is false.
<ti:app>
	<property name="run-in-background" type="bool">true</property>
</ti:app>
*New Ti.UI property:* * Ti.UI.hasSession: A read-only boolean property which returns true if the app can currently host UI. Will returns false if unable to host UI and creating windows is impossible. *New Ti.UI event:* (This event will only be fired if "tiapp.xml" property "run-in-background" is set true.) * "sessionbegin": Fired when it's time for the app to create its windows. Will only be fired if Ti.UI.hasSession property was previously false. *Bootstrap JS Changes:* Files ending with *.bootstrap.js should no longer display UI via their async execute() function anymore. We will add the following optional function that will be called just before the Ti.UI "sessionbegin" event gets fired so that bootstrap can inject their UI before the app can show its first window. * showUI(callback): Invoked on app startup after execute() only if Ti.UI.hasSession is true. From then on, this method will be invoked just before the Ti.UI "sessionbegin" event is fired. Known bootstrap that show UI are... [ti.playservices.bootstrap.js](https://github.com/appcelerator-modules/ti.playservices/blob/master/android/Resources/ti.playservices/ti.playservices.bootstrap.js) [mocha - ui.bootstrap.js](https://github.com/appcelerator/titanium-mobile-mocha-suite/blob/master/Resources/bootstraps/ui.bootstrap.js) *Classic App Usage:* For a Classic app, the "app.js" should look like the below. Note that the "app.js" can be executed in the background while the app is incapable of hosting UI.
// Listen for an event indicating when it's time to create/re-create app UI.
// On Android, this will be fired every time you back out and re-launch.
Ti.UI.addEventListener('sessionbegin', () => {
	openRootWindow();
});

// On startup, only create window if app is currently capable of hosting UI.
if (Ti.UI.hasSession) {
	openRootWindow();
}
*Alloy App Usage:* Alloy users do not have to worry about window creation at launch. It is Alloy's responsibility to open/re-open the root window when needed. On our end, we will have to change Alloy's "app.js" code generation to do something similar to the Classic code example above. *Backgrounding Pro-Tips:* * On iOS, you must use [URLSession](https://docs.appcelerator.com/platform/latest/#!/api/Modules.URLSession) to do networking in the background. * On Android, you must set up a [Foreground Service](https://docs.appcelerator.com/platform/latest/#!/api/Titanium.Android.Service) to perform networking, geolocation, and other tasks in the background. It also signals the OS to not forcibly terminate the backgrounded app.

Comments

  1. Michael Gangolf 2020-05-22

    Does this mean even if we kill the app from the app-switcher (while the fg service is running) the service continues to run? If so: awesome news!
  2. Joshua Quick 2020-05-22

    [~michael], yes, the runtime continues to run when you swipe off the app from the app switcher. I tested it. :)
  3. Joshua Quick 2020-05-22

    PR (master): https://github.com/appcelerator/titanium_mobile/pull/11728 PR (ti.playservices): https://github.com/appcelerator-modules/ti.playservices/pull/39

JSON Source