Skip to content
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.

Arena data handler Tutorial

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:

  1. 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
  2. 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).
  3. Create an android Service class, the service class is responsible for forwarding the calls to the data handler.
  4. 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>
  1. 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() {
        ...
  1. Next we need to create a Arena data handler. Data handlers are java classes that extend org.mixare.lib.data.PluginDataProcessor Below 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;
				}		
			}
		}.
  1. 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>();
					}
				}
	
			};

	
		}

Clone this wiki locally