JavaScript Samples
The following JavaScript samples are examples of how you can use the JavaScript engine:
#!/usr/bin/env js
to ensure the Android
device agent recognizes the script as a JavaScript script.Simple log
Demonstrates simple logging to the console.
mobicontrol.log.info('Hello world!');
#!/usr/bin/env js
mobicontrol.log.info('Hello world!');
Executing a simple command on the device
Enters admin mode on the device.
#!/usr/bin/env js
mobicontrol.agent.enterAdminMode();
Log real-time device information to the console
Logs device battery charge level to the console.
#!/usr/bin/env js
mobicontrol.log.info('The current battery level is: ' + mobicontrol.battery.level);
Conditioning on agent's values
Logs camera permission status.
#!/usr/bin/env js
while (mobicontrol.featureControl.camera.isDisabled()) {
mobicontrol.featureControl.camera.allow();
}
mobicontrol.log.info('Camera feature is allowed');
if loop and string operations
Demonstrates some JavaScript standard features: if loop and string operations.
#!/usr/bin/env js
if (mobicontrol.device.name.startsWith('Headquarters')) {
mobicontrol.featureControl.camera.disable();
}
Arrays
Demonstrates a JavaScript standard feature: arrays.
#!/usr/bin/env js
// Stop clock app if it runs in the foreground
var clockApp = 'clock';
var foregroundActivities = mobicontrol.app.foregroundActivities;
foregroundActivities.forEach(function(activity) {
if (activity.packageName.includes(clockApp)) {
mobicontrol.app.stop(activity.packageName);
}
});
Simple asynchronous callback execution
Installs an then starts an app.
#!/usr/bin/env js
// Install an app and start it as soon as it has been installed
mobicontrol.app.install('/sdcard/example.apk', onFinish);
function onFinish(result) {
if (result.isSuccessful) {
mobicontrol.app.start('net.soti.example');
}
}
Complex asynchronous callback execution
Creates an asynchronous callback including an invocation timeout parameter and failure scenario.
#!/usr/bin/env js
mobicontrol.agent.disconnect()
pause(3000)
mobicontrol.agent.connect(onFinish, 3000)
function onFinish(result) {
if (result.isTimedOut) {
mobicontrol.log.info('Timeout')
} else {
mobicontrol.log.info('Failure')
}
if (result.statusCode == mobicontrol.agent.ConnectResult.NO_NETWORK) {
mobicontrol.log.info('No network')
} else {
mobicontrol.log.info(result.statusCode)
}
}
function pause(numberMillis) {
var now = new Date()
var exitTime = now.getTime() + numberMillis
while (true) {
now = new Date()
if (now.getTime() > exitTime)
return;
}
}
Randomize code execution over time
Randomizes device reboots over 30 minutes so the DS (which might serve up to 100-200K devices) does not become unresponsive.
#!/usr/bin/env js
setTimeout(reboot, Math.random() * 30 * 60 * 1000);
function reboot() {
mobicontrol.device.reboot();
}
Verify agent version
Verifies that the version of the agent is correct.
#!/usr/bin/env js
var CORRECT_VERSION = '14.3.3 Build 1234';
if (mobicontrol.agent.version != CORRECT_VERSION) {
mobicontrol.log.error("The agent has incorrect version: " + mobicontrol.agent.version);
}
Check minimum OS version
Checks the minimum Android operating system version on a device.
#!/usr/bin/env js
var MINIMUM_ANDROID_OS_LEVEL = 26;
if (mobicontrol.os.apiLevel < MINIMUM_ANDROID_OS_LEVEL) {
mobicontrol.log.error("Device must be upgraded to Oreo or higher");
}
Check SIM card status
Checks if a SIM card is present in the device.
#!/usr/bin/env js
if (mobicontrol.cellular.signalStrength == null) {
mobicontrol.log.error("SIM card is removed.");
}
Force agent connection
Forces the agent to connect if it is not already online, and provides error messages if the connection fails.
#!/usr/bin/env js
mobicontrol.agent.connect(onFinish);
function onFinish(result) {
if (result.isSuccessful) {
mobicontrol.log.info('Success');
} else if (result.isTimedOut) {
mobicontrol.log.info('Timeout');
} else {
switch (result.statusCode) {
case mobicontrol.agent.ConnectResult.NO_NETWORK:
mobicontrol.log.info('No available networks');
break;
case mobicontrol.agent.ConnectResult.SERVER_UNREACHABLE:
mobicontrol.log.info('The agent cannot establish network connection to the deployment server');
break;
case mobicontrol.agent.ConnectResult.SERVER_BUSY:
mobicontrol.log.info('The network connection to the deployment server was established, but the server didn't acknowledge connection');
break;
default:
mobicontrol.log.info('Other error occurred: ' + result.statusCode);
}
}
}
Device property check and action
Sends a message to the screen when identifying certain device properties. This example checks signal strength and suggests a remedy.
#!/usr/bin/env js
if (mobicontrol.cellular.signalStrength == null) {
mobicontrol.message.createInfoDialog("Check that your SIM card is properly inserted.").show();
}
Request user acknowledgement before action
Sends a custom dialog with many options for controlling app install time. The package pushes to the device, and the pre-install script checks if the app is running in the foreground. If it is, the script asks the user to install the app now, in 5 minutes, or in 1 hour.
#!/usr/bin/env js
var FIVE_MINUTES = 5 * 60 * 1000;
var ONE_HOUR = 60 * 60 * 1000;
var buttonLabels = ['Install now', 'Install in 5 minutes', 'Install in 1 hour'];
if (isAppRunningInForeground('com.acme.importantapp')) {
mobicontrol.message.createInfoDialog('Would you like to install ImportantApp?')
.withButtons(buttonLabels[0], buttonLabels[1], buttonLabels[2])
.withCallback(onConfirm).show();
}
function onConfirm(result) {
if (result.buttonIndex != null) {
switch (buttonLabels[result.buttonIndex]) {
case 'Install now':
installImportantPcg();
break;
case 'Install in 5 minutes':
setTimeout(installImportantPcg, FIVE_MINUTES);
break;
case 'Install in 1 hour':
setTimeout(installImportantPcg, ONE_HOUR);
break;
}
}
}
function installImportantPcg() {
// Do nothing - the normal return from the script will launch the package installation
}
function isAppRunningInForeground(app) {
return mobicontrol.app.foregroundActivities.filter(activity => activity.packageName == app).length > 0;
}
Device self-service scripts
Organize the following simple scripts as icons users can select to perform self-help actions based on condtional logic:
Restarts the agent if the battery is charging.
#!/usr/bin/env js
if (mobicontrol.battery.isCharging) {
mobicontrol.agent.restart();
}
Performs a check-in if the device is not currently roaming.
#!/usr/bin/env js
if (!mobicontrol.cellullar.isRoaming) {
mobicontrol.agent.checkIn();
}
Reboots the device if the clock app is not running in the foreground.
#!/usr/bin/env js
if (isAppRunningInForeground('com.android.deskclock')) {
mobicontrol.device.reboot()
}
function isAppRunningInForeground(app) {
return mobicontrol.app.foregroundActivities.filter(activity => activity.packageName == app).length > 0;
}
Closes an app after detecting a low memory state.
#!/usr/bin/env js
var ONE_HUNDRED_KB = 100 * 1024;
if (mobicontrol.memory.availableSpace < ONE_HUNDRED_KB) {
mobicontrol.app.stop('com.example');
}
Device compliance support
Promotes device compliance by running periodic checks to ensure the device is operating within accepted parameters. In this case, a persistent pop-up window displays for user action if the device battery is low.
#!/usr/bin/env js
if (mobicontrol.battery.level < 0.20 && !mobicontrol.battery.isCharging) {
mobicontrol.message.createWarnDialog('The battery is low, charge your device!').show();
}
Package deployment support
Controls the flow and execution of package installation. In this case, installation aborts on devices running Android below Oreo OS.
#!/usr/bin/env js
if (mobicontrol.os.level < 26) {
mobicontrol.log.warn('Aborting package installation, as device has below-Oreo OS');
throw(mobicontrol.packages.Termination.ABORTED);
}
Device relocation by custom data, attribute, or properties
Controls the deployment progress or ensures the proper configurations deploy based on specific values. The following examples feature SSID and geofencing scenarios.
If a device's SSID is abc, move the device to the ABC folder (device group). To set this up, perform the following steps:
- Create the ABC folder (device group) and configure it with a certain payload
(for example, Disable Camera) and INI custom data ssid.ini,
with section
info
and keyssidIsAbc
. - Create a relocation policy from the original folder to the ABC folder when
ssidIsAbc
becomestrue
. - Create a relocation policy from ABC to the original folder when
ssidIsAbc
becomesfalse
. - Run the following JavaScript on schedule to ensure that when the device connects to and disconnects from abc SSID the device is successfully relocated:
#!/usr/bin/env js
var ini = require('ini');
var iniFile = new mobicontrol.io.File(mobicontrol.storage.internal.dataDirectory + '/ssid.ini');
var config = ini.parse(iniFile.readText());
var currentSsidIsAbc = mobicontrol.network.ssid == 'abc';
if (config.info.ssidIsAbc != currentSsidIsAbc) {
config.info.ssidIsAbc = currentSsidIsAbc;
iniFile.writeText(ini.stringify(config));
mobicontrol.agent.checkIn();
}
If a device whose name starts with 'Headquarters' enters geofence abc, move the device to the ABC folder. To set this up, perform the following steps:
- Create the ABC folder (device group). Then configure the folder with a specific payload (for
example, Disable Camera) and XML custom data geofence.xml,
with the name
isInAbc
and XPath expression/isInAbc
. - Create a relocation policy from the original folder to the ABC folder when
isInAbc
becomestrue
. - Create a relocation policy from ABC to the original folder when
isInAbc
becomesfalse
. - Create a rule for entering the abc geofence with the following
script:
#!/usr/bin/env js if (mobicontrol.device.name.startsWith('Headquarters')) { var xmlFile = new mobicontrol.io.File(mobicontrol.storage.internal.dataDirectory + '/geofence.xml'); var config = new XML(xmlFile.readText()); config.isInAbc = true; xmlFile.writeText(config.toString()); mobicontrol.agent.checkIn(); }
- Create a rule for exiting abc geofence with the same script as above, but with
false
instead oftrue
. - Ensure a device relocates when it enters or exits the abc geofence.
Here is the same script with some custom troubleshooting code:
#!/usr/bin/env js
if (mobicontrol.device.name.startsWith('Headquarters')) {
try {
var xmlFile = new mobicontrol.io.File(mobicontrol.storage.internal.dataDirectory + '/geofence.xml');
var config = new XML(xmlFile.readText());
config.isInAbc = true;
xmlFile.writeText(config.toString());
mobicontrol.agent.checkIn();
} catch(err) {
if (err.statusCode == mobicontrol.io.IoError.FILE_NOT_FOUND) {
mobicontrol.log.err("XML file is missing");
} else if (err.statusCode == mobicontrol.io.IoError.NOT_ACCESSIBLE) {
mobicontrol.log.err("XML file is not accessible");
}
}
}
Upgrade application if it is not runnning in the foreground
Installs an application if it is not currently running in the foreground. The device battery must be charging past a threshold before the upgrade can begin. When the installation is complete, the agent automatically checks in so that the WebConsole immediately reflects the change.
#!/usr/bin/env js
function isBatteryFullOrCharging() {
return mobicontrol.battery.level > 0.75 || mobicontrol.battery.isCharging;
}
function isForegroundApp(app) {
return mobicontrol.app.foregroundActivities.some(function(activity) {
return activity.packageName == app;
});
}
if (!isForegroundApp('com.example.bundleid') && isBatteryFullOrCharging()) {
mobicontrol.app.install('sdcard/PathTo/ExampleApp.apk', onFinish);
} else {
mobicontrol.log.info('Either Secure web is running or the battery is low and not charging')
}
function onFinish(result) {
if (result.isSuccessful) {
mobicontrol.agent.checkIn();
mobicontrol.log.info('Application ' + result.apkFileName + ' successfully installed');
} else {
mobicontrol.log.error('Application ' + result.apkFileName + ' installation failure: ' + result.statusCode);
}
}