forked from mixare/mixare
-
Notifications
You must be signed in to change notification settings - Fork 1
Data handler
abduegal edited this page Jun 27, 2012
·
6 revisions
Data handler plugins are custom services that can proces raw http data to a marker. Datahandler plugins should have the following action name in the activity manifest: org.mixare.plugin.datahandler and their plugin type is called: DATAHANDLER.
Below is a tutorial that describes how to create a data handler plgugin, using the arena-processor found in the plugin folder as example.
The arena data handler can convert json data to image markers. Below is an example of json data it can process:
{
"stats":"OK",
"num_results":0,
"results":[
{
"id":7041,
"lat":51.92323,
"lng":4.463539,
"elevation":0,
"title":"Verhaal 1",
"distance":0.0,
"has_detail_page":1,
"webpage":"http://ad-arena.finalist.com/arena-server/item/show/4949/7073/rood.item",
"object_type":"question",
"object_url":"http://ad-arena.finalist.com/arena-server/images/red-question.png"
}]
}
Extra attributes in this json array are object_type and object_url. they are needed to create an custom image for the marker.
Here are the steps to create a plugin for this datasource:
- Create a new project without a main Activity. For convenience packages should be named: org.mixare.plugin.[pluginname], in this case: org.mixare.plugin.arenaprocessor
- Import the mixarelib folder in the plugin directory by going to properties -> android -> library -> add (Make sure that the mixarelib project is imported in the workspace).
- Create an android Service class, the service class is responsible for forwarding the calls to the data handler.
- Add the android service class into your application manifest. You also need to set the android:exported="true" and add the action name in the intent filter.
In this case, the data handler will get a bitmap from an url, so I also added this:<uses-permission android:name="android.permission.INTERNET" />
<service
android:name=".service.ImageMarkerService"
android:exported="true" >
<intent-filter>
<action android:name="org.mixare.plugin.marker"/>
<category android:name="mixare.intent.category.MARKER_PLUGIN"/>
</intent-filter>
</service>- Next we are going to build the service. A datahandler service will have to use the AIDL binder org.mixare.lib.service.IDataHandlerService. We also need to override the onBind(Intent intent) method
@Override
public IBinder onBind(Intent intent) {
return binder;
}
private final IDataHandlerService.Stub binder = new IDataHandlerService.Stub() {
...- Next we need to create a Arena data handler. Data handlers are java classes that extend
org.mixare.lib.data.PluginDataProcessorBelow is the full class:
public class ArenaProcessor extends PluginDataProcessor {
public static final int MAX_JSON_OBJECTS = 1000;
@Override
public String[] getUrlMatch() {
String[] str = { "arena" };
return str;
}
@Override
public String[] getDataMatch() {
String[] str = { "arena" };
return str;
}
@Override
public List<InitialMarkerData> load(String rawData, int taskId, int colour)
throws JSONException {
List<InitialMarkerData> initialMarkerDatas = new ArrayList<InitialMarkerData>();
JSONObject root = convertToJSON(rawData);
JSONArray dataArray = root.getJSONArray("results");
int top = Math.min(MAX_JSON_OBJECTS, dataArray.length());
for (int i = 0; i < top; i++) {
JSONObject jo = dataArray.getJSONObject(i);
if (jo.has("title") && jo.has("lat") && jo.has("lng")
&& jo.has("elevation")) {
String link = null;
if (jo.has("has_detail_page")
&& jo.getInt("has_detail_page") != 0
&& jo.has("webpage"))
link = jo.getString("webpage");
Bitmap image = null;
if (jo.getString("object_type").equals("information")) {
image = BitmapFactory.decodeResource(
ArenaProcessorService.instance.getResources(),
R.drawable.information);
} else if (jo.getString("object_type").equals("question")) {
image = getBitmapFromURL(jo.getString("object_url"));
} else if (jo.getString("object_type").equals("image")) {
image = getBitmapFromURL(jo.getString("object_url"));
}
InitialMarkerData ma = new InitialMarkerData(jo.getInt("id"),
HtmlUnescape.unescapeHTML(jo.getString("title"), 0),
jo.getDouble("lat"), jo.getDouble("lng"),
jo.getDouble("elevation"), link, taskId, colour);
ma.setMarkerName("imagemarker");
ma.setExtras("bitmap", new ParcelableProperty(
"android.graphics.Bitmap", image));
initialMarkerDatas.add(ma);
}
}
return initialMarkerDatas;
}
public Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
return BitmapFactory.decodeStream(input);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}.- The final step is to forward the functions in the server to the datahandler. Below is the full code:
public class ArenaProcessorService extends Service{
public final String pluginName = "arenaProcessor";
private Map<String, ArenaProcessor> processor = new HashMap<String, ArenaProcessor>();
public static ArenaProcessorService instance;
private Integer count = 0;
@Override
public IBinder onBind(Intent intent) {
instance = this;
return binder;
}
public final IDataHandlerService.Stub binder = new IDataHandlerService.Stub() {
@Override
public String build() throws RemoteException {
ArenaProcessor arenaProcessor = new ArenaProcessor();
String processorName = "arenaProcessor-"+count+"-"+arenaProcessor.hashCode();
processor.put(processorName, arenaProcessor);
return processorName;
}
@Override
public String[] getDataMatch(String processorName) throws RemoteException {
return processor.get(processorName).getDataMatch();
}
@Override
public int getPid() throws RemoteException {
return 0;
}
@Override
public String getPluginName() throws RemoteException {
return pluginName;
}
@Override
public String[] getUrlMatch(String processorName) throws RemoteException {
return processor.get(processorName).getUrlMatch();
}
@Override
public List<InitialMarkerData> load(String processorName, String rawData,
int taskId, int colour) throws RemoteException {
try {
return processor.get(processorName).load(rawData, taskId, colour);
} catch (JSONException e) {
e.printStackTrace();
return new ArrayList<InitialMarkerData>();
}
}
};
}