[TIMOB-27896] TiAPI: Add ability to run in the background without UI
GitHub Issue | n/a |
---|---|
Type | New Feature |
Priority | Low |
Status | Open |
Resolution | Unresolved |
Affected Version/s | n/a |
Fix Version/s | n/a |
Components | Android, iOS |
Labels | android, background, ios |
Reporter | Joshua Quick |
Assignee | Joshua Quick |
Created | 2020-05-16T00:09:37.000+0000 |
Updated | 2021-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.
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!
[~michael], yes, the runtime continues to run when you swipe off the app from the app switcher. I tested it. :)
PR (master): https://github.com/appcelerator/titanium_mobile/pull/11728 PR (ti.playservices): https://github.com/appcelerator-modules/ti.playservices/pull/39