GeoAR Datasource
GeoAR provides a kind of plugin pattern for extensibility that offers a framework for straightforward addition of data sources to the application. Through this it is possible to write own data sources without going deep into the code.
Datasources
Available by 52°North
Some
DataSources provided by 52°North are already available. All these are listed at
http://geoviqua.dev.52north.org/geoar/codebase and can be downloaded via the Codebase download interface in
GeoAR. These include:
Source Code
API:
https://github.com/52North/geoar-ds
Datasources:
https://github.com/52North/geoar-datasources
Possible/Whishlist
- Twitter
- Flickr
- OpenPOI Datasource: Find points of interest based on the OGC POI registry > Currently on hold because of slow API.
Framework
The framework provides a small set of classes, interfaces and annotations, enabling
GeoAR to integrate custom data sources wrapped as plugins. This allows customized visualization of spatial information for map and augmented reality experiences, as well as tight interactions with the user, for instance by defining individual user interface elements. Datasource plugins are deployed as regular Android Application Packages (apk) which are loaded by
GeoAR on demand at runtime. These plugins are also installable from within the app using a central remote codebase.
Package |
Name |
Description |
org.n52.android.newdata |
Annotations |
... |
|
DataSource |
... |
|
Filter |
... |
|
SpatialEntity |
... |
|
Visualization |
... |
org.n52.android.newdata.vis |
DataSourceVisualization |
... |
Source code is available in the SVN:
https://svn.52north.org/svn/projects/android/GeoARDataSource/
Plugins
A GeoAR plugin is a regular Android Application Package (apk) which gets loaded by the GeoAR app at runtime. The plugin loading mechanism ensures full support of additional external libraries and all features of the Android resources framework. There are no changes to the usual Android package structures.
To be accessible, plugins have to be placed in the external files directory of the application (usually /mnt/sdcard/Android/data/org.n52.android/files/) or downloaded from the codebase using the application. Metadata should be specified using a plugin descriptor XML file (
geoar-plugin.xml
) and an icon may be set using an image file (
icon.png
), both placed in the root directory of the plugin apk.
Plugin Descriptor
A plugin descriptor is an XML file in the root of a plugin apk which describes metadata and identifiers of a plugin. The following shows the general layout with placeholders to be filled with valid information, in this case automatically during packaging using Maven parameters:
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<name>${project.name}</name>
<publisher>${project.organization.name}</publisher>
<identifier>${project.groupId}.${project.artifactId}</identifier>
<description>${project.description}</description>
<version>${project.version}</version>
</plugin>
If a plugin does
not include such a descriptor, its filename will be used as internal identifier and name. GeoAR will also try to extract version information from the filename (e.g. from xxx-datasource-0.2.2-xxx.apk).
If there are multiple datasource plugins with the same identifier accessible, the one with the highest version number will be loaded by GeoAR.
Logging
The plugin framework defines the
DataSourceLoggerFactory to perfom logging operations within the logging system used by the main
GeoAR application. This allows to include your custom data source logging messages in user generated error reports to track data source errors:
public class Test {
private static final Logger LOG = DataSourceLoggerFactory
.getLogger(Test.class);
public Test{
LOG.info("Object created");
}
}
Development: Push Plugin to Device/Emulator with Maven
It is possible to automatically build and push datasource plugins to the device into the right folder. The following configuration has to be added to the maven pom.xml.
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<configuration>
<push>
<source>${project.build.directory}/${project.build.finalName}.apk</source>
<destination>/mnt/sdcard/Android/data/org.n52.android/files/</destination>
</push>
</configuration>
</plugin>
In order to perform the push onto the device:
- Right-click on the datasource project
- Add a new run configuration (Run As -> Run Configurations...)
- Name: push Android Datasource
- Base directory:
- Click Browse Workspace..., then select project folder. The field should show
${workspace_loc:/geoar-app}
- Goals:
android:push
- It is recommended to combine clean, install, and push to optimize the building process
- Goals:
clean install android:push
- Run the configuration
Implementing a Datasource
The main entry point for developing own GeoAR datasources is to implement the provided
DataSource
interface. The purpose of this interface is to allow access to your own data by calling the
getMeasurements
function.
To set the scope of the requested data, the plugin framework provides the abstract
Filter
class.
Filter
instances will get passed with each function call, setting at least the geographic bounding box to query data for. The generic parameter of the
DataSource
interface furthemore allows to use a custom implementation of
Filter
with additional individual filtering parameters.
To return requested data, the
SpatialEntity
class is used.
Visualizations of data are realized by implementing appropriate
Visualization
interfaces provided by the framework. In general, these interfaces consist of functions to transform
SpatialEntity
objects into graphical representations and interactive elements such as regular Android View instances.
DataSource interface
A minimal plugin contains at least one class implementing
DataSource
. Each
DataSource
implementation has to be annotated by a
@DataSource
annotation to provide additional metadata and a
@SupportedVisualization
annotation to assign supported classes of visualizations:
@Annotations.DataSource(name = "Test", cacheZoomLevel = 0, minReloadInterval = -1, description = "Example for a description")
@Annotations.SupportedVisualization(visualizationClasses = { TestMapVisualization.class, TestARVisualization.class })
public class TestSource implements DataSource<TestFilter> {
public List<? extends SpatialEntity> getMeasurements(F filter) { ... }
public boolean isAvailable() { ... };
}
Note
-
DataSource
method calls are always in a threading context and it is not required to spawn new threads for perfoming long lasting operations.
- The purpose of this interface is to access raw data. Visualizations of these information are handled by the associated
Visualization
classes.
- If a single
DataSource
requires configuration settings to access data, settings field may get added using the GeoAR Settings Framework. This renders a datasource stateful and GeoAR will automatically maintain multiple instances of the implemented class and its states as well as the user interface to set the necessary configuration settings.
- To perfom initialization work, make use of
@PostConstruct
methods (see Annotations). It is not guaranteed that these methods will be called outside the UI thread.
Filter class
Filter
instances are required to filter data queries. They are passed by GeoAR to
DataSource
instances in order to request data for a specific geographic bounding box described by the
Filter
. Datasource developers can extend the provided
Filter
class to provide customized filtering attributes and to adapt it to own
SpatialEntity
implementations. Filters are associated with a
DataSource
using its corresponding generic interface parameter.
All fields to be used as filtering attributes are required to be annotated following the GeoAR Settings Framework rules. The necessary user interface to show (including groups), set, validate and maintain these filtering values is generated automatically.
The follogin snippet shows a
Filter
extension adapted to noise measurements with additional attributes to set noise limits to be excluded from the results:
public class NoiseFilter extends Filter {
private static final long serialVersionUID = 1L;
@Setting
@Group("Noise")
@Name("Min dB")
@Min("0")
@Max("100")
@NotNull
private float minDB;
@Setting
@Group("Noise")
@Name("Max dB")
@Min("0")
@Max("100")
@NotNull
private float maxDB;
public boolean filter(NoiseMeasurement measurement) {
return !(measurement.value < minDB || measurement.value > maxDB);
}
}
Visualization interfaces
Annotations
The framework defines multiple annotations to interact with GeoAR and the Android framework directly.
Applicable for fields:
-
@SystemService(<name>)
- Directly injects an Android system service from the plugin context with the given name.
-
@SharedHttpClient
- Injects a DefaulHttpClient to efficiently use network within plugin code to share a single connection pool.
-
@PluginContext
- Injects a Context, for example to inflate Views or to access plugin resources
-
@Setting
- Indicates that a field has to be used by the GeoAR Settings Framework
Applicable for methods:
-
@PostConstruct
- Indicates a method to be called directly after all fields of a class were injected, i.e. the object is constructed. Injection takes place when a datasource/visualization/filter is about to be used by the application. Methods with this annotation can be used to perform initialization work.
Settings Framework
Adding aditional parameters to data sources is as simple as defining the corresponding data field. GeoAR will automatically create all required user interfaces and save the state of your data sources based on a simple
@Setting
annotation.
For example, when a
DataSource
implementation includes Settings as defined in this paragraph, the source will automatically get treated as stateful, allowing the user to create multiple instances of a single data source having different parameter values.
Settings are also very important for defining filters. Adding the following fields to a Filter implementation results in the settings view on the right:
@Setting
@Group("A Group Name")
@Name("Parameter float")
@Min("0")
@Max("100")
private float floatWithConstraints;
@Setting
@Group("A Group Name")
@Name("Parameter Enumeration")
@NoValue("All")
private SomeEnumeration locationProvider;
@Setting
@Group("A Group Name")
@Name("Parameter String")
private String testString;
@Setting
@Name("Parameter Calendar")
private Calendar testCalendar;
@Setting
@Name("Parameter Calendar Time")
@Temporal(TemporalType.TIME)
private Calendar testCalTime;
@Setting
@Name("Parameter Calendar Date")
@Temporal(TemporalType.DATE)
private Calendar testCalDate;
Note
- As GeoAR does not instanciate fields on its own, already set values will be treated as default values.
- Settings without
@Group
annotation will always get placed at the beginning of a settings view.
- There is no proper way to influence the ordering of parameters.
Supported Types
- Float, Double
- Wrapped and primitive types are supported.
@Min
and @Max
may be used to limit valid value range. @NotNull
forces input for wrapped types.
- Date, Calendar
- Supports both types transparently, using current user locale for providing date and time user interfaces.
@Temporal
may be used to restrict input to only date or time values, whereas the default shows date and time inputs. @NotNull
forces user to input valid values.
- String
-
@NotNull
requires a non-empty string
- Enumerations
- Supports enums by automatically detecting enumeration types and displaying a selection spinner. Using
@NoValue
allows to set a display value allowing the user to set null or undefined values. Using the following enum declaration within the previous example generates a spinner menu as displayed on the right, if the user interacts with the corresponding property: public enum SomeEnumeration {
USER("User"), GPS("GPS"), NETWORK("W-LAN"), OTHER("Other");
private String title;
private SomeEnumeration(String title) {
this.title = title;
}
@Override
public String toString() {
return title;
}
};
Predefined Data Source Instances
If there are
@Setting
annotations within a
DataSource
class, a user can generate multiple different data source instances using custom setting values. To specify a default set of these instances with predefined setting values, a
DataSource
can get augmented by a
@DefaultInstances
annotation:
@DefaultInstances({
@DefaultSettingsSet({
@DefaultSetting(name = "setting1", value = "predefined value 1"),
@DefaultSetting(name = "setting2", value = "predefined value 2") }),
@DefaultSettingsSet({
@DefaultSetting(name = "setting1", value = "another predefined value 1"),
@DefaultSetting(name = "setting2", value = "another predefined value 2") })
})
...
public class CustomDataSource implements DataSource<CustomFilter> {
...
}
The example above defines two default data source instances. Each instance is described by the settings defined using a
@DefaultSettingsSet
. Every settings set describes values corrseponding to setting field names (fields with a
@Setting
annotation) using the
@DefaultSetting
annotation. All assigments are based on String representations of the targeted field type.
- Topic created by: ArneDeWall
- Topic created on: 2012-06-27