Display military messages
In this topic
About military messages
Military software used for Situation Awareness and Command & Control pass secure communications between mobile devices in the field and command centers. These special communications consist of either voice or data transmissions. Data communications can contain military messages that define where specific military symbols are located on a map.
You can build an application using the ArcGIS Runtime SDKs for Java or Android to take these military messages and convert them into military symbols to be displayed in a map control on a desktop or laptop device. Currently the messages can be displayed using symbology from the Department of Defense (DoD) MIL-STD-2525C symbol dictionary, or from the North Atlantic Treaty Organization (NATO) APP-6B symbol dictionary.
Set up your device
The ArcGIS Runtime SDK for Android supports MIL-STD-2525C and APP-6B symbol dictionaries. The symbol dictionaries are provided in the local SDK download
You will need to copy the resource contents to your target device. The default location on your device is:
Example Default directory structure
+ mnt + sdcard + ArcGIS +SymbolDictionary + MessageTypes - Chemlight.json - PositionReport.json - SpotReport.json - mil2525c.dat <or> app6b.dat
The directory structure above is dependent on your device structure's external sdcard location and which symbol dictionary you have installed in the default location. Both the MIL-STD-2525C and APP-6B symbol dictionaries are dependent on their specific message types.
We currently do not support both the MIL-STD-2525C and APP-6B symbol dictionaries installed in the default directory location. The
MessageProcessor class provides an overloaded constructor which takes a
String representing the directory location for the symbols. Use this constructor for one of the symbol dictionaries to have both resources provisioned to a single device.
You can use the Android Debug Bridge (adb) tool provided by your Android SDK to push the resource to your device. An advanced symbology sample is available and explains how to set up the device in more detail. Refer to these resources to set up your device for application development to support military messages.
MessageProcessor class allows you to process a message from external resources, for example, display a military symbol by passing a 2525C message to the
MessageProcessor for processing. Each
MessageProcessor comes with a
DictionaryType that dictates the message format to process. Each
MessageProcessor initializes. Internally, a message processor of the required type, for example, 2525C, is created and knows the data resource location on the device. The
MessageProcessor has an overloaded constructor that takes a Java string path to the custom symbol dictionary path. A
MessageProcessor is bound to a
MessageGroupLayer that is used to display, update, and remove
MultiLayerSymbol associated with messages. Add the
MessageGroupLayer to a
MapView for the message processing to function properly.
MessageGroupLayer extends a
GroupLayer as a collection of layers that can be of any type. It extends from the
Layer class and has properties such as visibility, opacity, extent and so on. The most basic functionality that should be provided is the ability to manipulate sublayer visibility, opacity, and order. The layer collection object provides these functions and is essentially a synchronized arraylist and queue of layers. For military purposes, the
MessageGroupLayer has a default constructor which creates a new message group layer without a
MessageProcessor and can use this instance to create a
MessageProcessor. The overloaded constructors provided by the
MessageGroupLayer take a
SymbolDictionary.DictionaryType parameter to create a
MessageProcessor for the given type. It's the
MessageProcessor that adds the graphics layers to the
MessageGroupLayer must be added to an initialized map. If the map is not initialized, an error message shows. Below is an example of creating the
MessageProcessor from the constructed
Creating a message processor
// create a new MessageGroupLayer for MIL 2525C symbol type MessageGroupLayer messageGroupLayer = new MessageGroupLayer(DictionaryType.MIL2525C); // Add layer to the map mMapView.addLayer(messageGroupLayer); // Get the message processor from the GroupLayer MessageProcessor processor = messageGroupLayer.getMessageProcessor();
The message processor handles an incoming message by using message properties to create, delete, update, or otherwise change the state of a graphic (geometry and attributes). The message processor determines which message properties should persist on graphic as attributes. If necessary, the layer (and associated renderer) for the graphic is created and added to the group layer. With 2525C, only one geometry type is stored in a graphics layer, and the layers are z-ordered points->lines->polygons (ordering of layers with the same geometry type is arbitrary).
There are 2 ways to create a message object and process it.
- Setting properties programmatically
- Using the
The workflow for createing a
Message and processing it programmatically:
Message message = new Message(); UUID uuid = UUID.randomUUID(); message.setID(uuid.toString()); message.setProperty("_Type", "position_report"); message.setProperty("_Action", "update"); message.setProperty("_Control_Points", "7846271.25206,4091857.83028"); message.setProperty("sic", "SFGPUCRRL--E---"); message.setProperty("_WKID", "3857"); message.setProperty("UniqueDesignation", "Mad dog"); processor.processMessage(message);
MessageHelper class provides user-friendly property names and convenience methods to create messsages:
// create a list of control points for input into message Point point1 = new Point(x1, x2); ArrayList<Point> controlPoints = new ArrayList<Point>(1); controlPoints.add(point1); // create the Map of properties HashMap<String, Object> properties = new HashMap<String, Object>(); properties.put("sic", "SFGPEVC--------"); properties.put("uniquedesignation", "Tex"); Message msg1 = MessageHelper.create2525CUpdateMessage(UUID.randomUUID() .toString(), "position_report", controlPoints, properties); // process message and add point processor.processMessage(msg1);
Messages are logically transient in that they have no (direct) representation in the map or message processor. For update scenarios (for example, military chemlight), the message processorallows the re-creation of a message from a graphic or previous message ID. For 2525C, this is the same as the message previously passed in. The only exception is the action property (for example, update, delete and so on), which is empty. Initially, all properties of the message (except action) persist on the graphic to support this.
Graphic clickedGraphic = null; Message newMsg = msgProcessor.createMessageFrom(clickedGraphic); //if you want to use the message (perform an update), you need to set the action msg.setProperty(":ACTION", "UPDATE"); //process the message msgProcessor.processMessage(newMsg);
Messages can contain the WKID for the spatial reference but if omitted, the default spatial reference is used. This defaults to WGS84.Message
Message contains properties that can be processed by the message processor. All properties are name-value pairs except for the message ID.
Symbol dictionary searching
The group of classes that support functionality to allow for the
filtering of symbols contained in a dictionary renderer are
SymbolDictionaryFilter. Given a
filtered list of symbols, other methods can be used to return
attributes, keywords, and the graphic for a symbol. The
SymbolDictionary class contains functionality to get information about
the dictionary including lists of symbols and their associated
SymbolDictionaryFilter classes build queries against the symbol dictionary to return a list
of symbols relevant to the application user.
To perform a search for symbols that contain given keywords, the code looks as follows:
//The getKeywords() method is called on the SymbolDictionary class //which will return a list of keywords used in that dictionary. SymbolDictionary symbDict = new SymbolDictionary(DictionaryType.MIL2525C); List<string> keywords = symbDict.getKeywords(); //code goes here to take the keywords list and add the names into a picker //One or more of these keywords will be added to the instance of the //SymbolDictionaryQuery class using the addKeyword method. SymbolDictionaryQuery query = new SymbolDictionaryQuery(); query.addKeyword("Appendix X"); query.addKeyword("Friendly"); //The SymbolDictionaryFilter class is used with SymbolDictionaryQuery to // query the symbol dictionary to get a filtered list of symbols SymbolDictionaryFilter symDictFilter = new SymbolDictionaryFilter(); symbDict.addFilter(symDictFilter); String symbolName = symDictFilter.getName();
The symbol graphic can be obtained using the
This takes a symbol name that came from a list of
symbol names returned in a
getSymbolNames call and an Android Bitmap.
//get the symbol graphic from the name and Android Bitmap image // returns true if symbol was successfully generated boolean = symbDict.getSymbolImage("Utility Vehicle U", bitMapImg);