Advanced Symbology
Advanced Symbology
Advanced Symbology is a feature in the ArcGIS Android API which allows you to process messages from external resources and display as a graphic symbol in your mapping application. The external resources include a dictionary file and message file. We currently support the MIL-STD-2525A standard military symbols and provide default message files which can be extended to customize the symbols.
Setting up your device
In order to use the Advanced Symbology feature API you must provide the Symbol Dictionary resource to the MessageProcessor class. We currently support MIL2525C symbology which you can download from Esri download site. After downloading the resource bundle extract it to your desktop and copy the contents to your target device. The default location on your device is /sdcard/ArcGIS/SymbolDictionary. You will need to understand how to use the Android Debug Bridge (adb) tool provided by your Android SDK. We offer a sample which explains how to set up the device in more detail. Please refer to these resources to set up your device for application development to support Advanced Symbology.
Message Processing
The MessageProcessor class allows you to process a Message from external resources, e.g. display a military symbol by passing a 2525C message to the MessageProcessor for processing. Each MessageProcessor comes with a DictionaryType which dictates the message format to be processed. Each DictionaryType is backed by a resource bundle which includes a dictionary data file and message files in JavaScript Object Notation (JSON). The path to the resource files are stored on a device and needs to be specified when the MessageProcessor is initialized. Internally a message processor of the required type, e.g. 2525C, will be created and knows where the data resource is lcoated on device. The default location is /sdcard/ArcGIS/SymbolDictionary. The MessageProcessor has an overloaded constructor which takes a Java String path to the custom Symbol Dictionary path. A MessageProcessor is bound to a GroupLayer which is used to display, update, and remove symbols associated with messages. The GroupLayer has to be added to a MapView for the message processing to function properly.
Group LayerA group layer is a collection of layers that could be of any type. It extends from the Layer class hence it has properties such as visibility, opacity, extent etc. The most basic functionality that should be provided is the ability to manipulate sub layer visibility, opacity, order. The layer collection object provides these functions, its essentially a synchronized arraylist/queue of layers. For military purposes, the group layer is one of the arguments that will be to the message processor constructor. Hence its the message processor that will add the graphics layers to the group layer. The group layer must be added to an initialized map, if the map is not initialized the user will be prompted with an error message.
Creating a Message Processor
//group layer to be used by message processor
GroupLayer myGroupLyr = new GroupLayer();
//create a message processor for 2525C
// in default location
MessageProcessor msgProcessor = new MessageProcessor(DictionaryType.MIL2525C, myGroupLyr);
The message processor handles an incoming message by using message properties to create, delete, updating or otherwise change the state of a graphic (geometry and attributes). The message processor determines which message properties should be persisted on the graphic as attributes. If necessary, the layer (and associated renderer) for the graphic is created and added to the group layer. In the case of 2525C, only one type of geometry type will be stored in a graphics layer, and the layers will be z-ordered points->lines->polygons (ordering of layers with the same geometry type is arbitrary).
//create a message
Message msg = new Message();
//set the properties of the message
//this is the message ID which directly related to an individual symbol
//if we want to update this symbol after adding it, the same message identifier
//must be used
msg.setID("ABC47576");
msg.setProperty(":ACTION", "UPDATE");
msgProcessor.processMessage(msg);
Messages are logically transient in that they have no (direct) representation in the map / message processor. For update scenarios (e.g. military chemlight) the message processor will allow the re-creation of a message from a graphic, or previous message id. For 2525C this will be the same as the message previously passed in, the only exception being the action property (e.g. update, delete, etc), which will be empty. Initially all properties of the message (except action) will be persisted on the graphic to support this.
Graphic clickedGraphic = null;
Message newMsg = msgProcessor.createMessageFrom(clickedGraphic);
//if we want to use the message (perform an update), we 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 this is omitted, then the default spatial reference is used. This will default to WGS84.
MessageMessage contains properties which 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 which supports functionality to allow for the filtering of symbols contained in a dictionary renderer are SymbolDictionary, SymbolDictionaryQuery, and SymbolDictionaryFilter. Given a filtered list of symbols, other methods can be used to return attributes, keywords and the graphic for a symbol. The Symbol Dictionary class contains functionality to get information about the dictionary including lists of symbols and their associated information. The Symbol Dictionary Query and Filter classes are for building up queries against the symbol dictionary to return a list of symbols which are relevant to the application user. To perform a search for symbols which contain given keywords, the code would look 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 Symbol Dictionary Query which contains the keywords (applied can be listed using the
//getKeywords method on the query class) is then passed into the getSymbolNames method
//to return the list of matching symbols.
List<string> symbolNames = symbDict.getSymbolNames(query);
Filters are applied to a query with a value which is contained against a symbol. For example this could be a filter for "Category" of "Ground Vehicle". A filter would be added to a search using the following process:
//get a list of filters from the dictionary
List<string> filterNames = symbDict.getFilterNames();
//we now need to get the filter values available
List<string> filterValues = symbDict.getFilterValues("Category");
//make a filter and apply it to the query
SymbolDictionaryFilter myFilter = new SymbolDictionaryFilter{
name = "Category",
value = "Ground Vehicle"
};
SymbolDictionaryQuery myQuery = new SymbolDictionaryQuery();
myQuery.addFilter(myFilter);
//return the list of symbols
List<string> moreSybolNames = symbDict.getSymbolNames(query);
The symbol graphic can be obtained using the getSymbolImage method. This takes a symbol name which will have come 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 is symbol was successfully generated
boolean = symbDict.getSymbolImage("Utility Vehicle U", bitMapImg);