Jerry
Jerry

Reputation: 106

Markers on Google Maps v2 from remote XML

I managed to render a map, get position and such in a android project of mine

But I´m struggling with finding some basic or advanced examples on how to place markers on a google map v2 from a remote xml file.

So, how can I fetch markers from remote xml and display them using Google Maps API v2?

Here is example on format of XML file:

<?xml version="1.0" encoding="UTF-8"?>
<maintag>
   <item>
      <id>1</id>
      <name>Place</name>
      <lat>60.1736245</lat>
      <lng>12.0283267</lng>
      <description>Nice Place</description>
      <type>2</type>
      <spotid>191712</spotid>
      <image>placeimage</image>
   </item>
   <item>
      <id>2</id>
      <name>Place</name>
      <lat>61.1736245</lat>
      <lng>13.0283267</lng>
      <description>Nice Place</description>
      <type>3</type>
      <spotid>291712</spotid>
      <image>placeimage</image>
   </item>
</maintag>

Upvotes: 2

Views: 192

Answers (1)

Daniel Nugent
Daniel Nugent

Reputation: 43322

You just need to access the XML in a network operation on a background Thread, parse the XML, and then display the Markers accordingly on the UI Thread.

I just got this working using this answer as a guide for the XML parsing.

Imports:

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

Here is the full Activity class, which includes an AsyncTask as an inner class that downloads and parses the XML from the URL in doInBackground(), then draws the Markers in onPostExecute():

public class MapFromXML extends AppCompatActivity implements OnMapReadyCallback {

    GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_map_from_xml);
    }

    @Override
    public void onResume() {
        super.onResume();

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        if (mapFragment != null) {
            if (mMap == null) {
                mapFragment.getMapAsync(this);
            } else {
                new GetXmlAsync().execute();
            }
        }
    }

    @Override
    public void onPause() {
        super.onPause();
    }


    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);

        new GetXmlAsync().execute();
    }


    public class GetXmlAsync extends AsyncTask<URL, Void, List<MarkerInfo>> {

        @Override
        protected List<MarkerInfo> doInBackground(URL... params) {

            List<MarkerInfo> markerInfoList = new ArrayList<>();
            Document doc = null;
            URL url = null;
            try {
                url = new URL("http://www.example.com/GoogleMapXML.xml");

                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                DocumentBuilder db = null;
                db = dbf.newDocumentBuilder();
                doc = db.parse(new InputSource(url.openStream()));

            } catch (ParserConfigurationException e1) {
                e1.printStackTrace();
            } catch (MalformedURLException e1) {
                e1.printStackTrace();
            } catch (SAXException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();

            }

            doc.getDocumentElement().normalize();

            NodeList nodeList = doc.getElementsByTagName("item");

            try {
                for (int i = 0; i < nodeList.getLength(); i++) {

                    Node node = nodeList.item(i);
                    Element fstElmnt = (Element) node;

                    NodeList nameList = fstElmnt.getElementsByTagName("name");
                    Element nameElement = (Element) nameList.item(0);
                    nameList = nameElement.getChildNodes();
                    String name = ((Node) nameList.item(0)).getNodeValue();

                    NodeList latList = fstElmnt.getElementsByTagName("lat");
                    Element latElement = (Element) latList.item(0);
                    latList = latElement.getChildNodes();
                    String lat = ((Node) latList.item(0)).getNodeValue();

                    NodeList lonList = fstElmnt.getElementsByTagName("lng");
                    Element lonElement = (Element) lonList.item(0);
                    lonList = lonElement.getChildNodes();
                    String lng = ((Node) lonList.item(0)).getNodeValue();

                    MarkerInfo info = new MarkerInfo(name, Double.parseDouble(lat), Double.parseDouble(lng));
                    markerInfoList.add(info);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            return markerInfoList;
        }

        @Override
        protected void onPostExecute(List<MarkerInfo> markerList) {

            for (MarkerInfo info : markerList) {
                mMap.addMarker(new MarkerOptions().position(new LatLng(info.lat, info.lon))
                        .title(info.name)
                        .icon(BitmapDescriptorFactory
                                .defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
            }

            if (markerList.size() > 0) {
                mMap.moveCamera(CameraUpdateFactory
                        .newLatLng(new LatLng(markerList.get(0).lat, markerList.get(0).lon)));
                mMap.animateCamera(CameraUpdateFactory.zoomTo(5));
            }
        }
    }

    public class MarkerInfo {
        double lat;
        double lon;
        String name;
        public MarkerInfo(String n, double la, double lo) {
            name = n;
            lat = la;
            lon = lo;
        }
    }

}

Here is the res/layout/content_map_from_xml.xml layout file for the Activity:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MapFromXML"
    tools:showIn="@layout/activity_map_from_xml">

    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment" />

</RelativeLayout>

Result:

enter image description here

Upvotes: 2

Related Questions