How it works?

Headwind MDM has a built-in open source Push notification platform which doesn’t use any cloud services. Push notifications can be therefore sent in LANs or other secured networks, and the Android devices receiving notifications do not need to be certified by Google.

Devices are using a persistent TCP connection with the server. Once a message is created on the server, it is sent to the device by using a TCP channel, so the delivery is almost instant.

As a bearer protocol, Headwind MDM uses MQTT. Web panel embeds a MQTT broker (Apache ActiveMQ) which is responsible for Push notification transport.

To make the connection persistent, the mobile agent sends heartbeats (each 5 minutes) and implements the automatic reconnection algorithm. Headwind MDM uses an improved open source MQTT client library “Eclipse Paho”.

Push message structure

Headwind MDM’s push notification has three fields:

  • Type – a string defining the message type. Your application can listen for one or more message types. There are also predefined message types.
  • Payload – an optional JSON string containing the message data.
  • DeviceNumber – the target address of the message (it is the device number in Headwind MDM).

There is a class MDMPushMessage in the Headwind MDM mobile SDK library related to the Push notification.

Examples

Headwind MDM launcher processes the following Push notifications.

Configuration update

When the admin updates the configuration in the web panel, a message of type configUpdated (no payload) is sent to each device having that configuration.

Your application can also listen to this message type and refresh its settings when a configuration is updated. This mechanism is implemented in most Headwind MDM plugins.

Run application

When the plugin needs to start a mobile agent remotely, a message of type runApp is sent to a device.

The payload is:

{
  "pkg": "Package ID of the running app",
  "action": "Action for the Android intent, optional",
  "extra": {
    "ExtraKey1": "Extra Value 1",
    "ExtraKey2": "Extra Value 2",
    ...
  }
}

The pkg attribute is required, other attributes are optional.

REST API to send a Push notification

You can send Push notifications to the managed devices by using the REST API.

Prior to calling an API method to send a notification, you need to authorize and get an authorization token. See details about the REST API authentication here.

The REST method to send a Push notification is:

POST /rest/private/push
Authorization: Bearer current_authorization_token_here
Content-Type: application/json

{
  "messageType": "Type of your message",
  "payload": "Message payload in a string form",
  "broadcast": true/false,
  "deviceNumbers": [ "DeviceNumber1", "DeviceNumber2", ... ],
  "groups": [ "GroupName1", "GroupName2", ... ]
}

You can send message to a set of devices, groups, or to all available devices. Set the variable broadcast to true to send to all devices.

Important: the payload variable is not an object, it is a string encapsulating a JSON object, for example, "{\"pkg\": \"com.android.settings\"}".

On success, the method returns 200 OK and messages are sent to the specified devices.

Receiving push notifications in a mobile app

Headwind MDM launcher forwards Push notifications received from the server to all mobile applications through an Android broadcast message. The action is com.hmdm.push.MessageType and the extra for key com.hmdm.PUSH_DATA contains the string for the payload.

We recommend using a wrapper class MDMPushHandler to receive messages. The implementation is the following.

public class MyActivity extends Activity {
    
    private MDMPushHandler pushHandler = new MDMPushHandler() {
        public void onMessageReceived(MDMPushMessage message) {
            Log.d("MyApp", "MDM Push received: type " + message.getType());
            // Do something with message.getData() which is a JSONObject object.
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        pushHandler.register("myMessageType", this);
    }

    @Override
    protected void onDestroy() {
        pushHandler.unregister(this);
        super.onDestroy();
    }
}