How to parse and plot gpx file has an android MapV

2020-05-29 11:40发布

问题:

I'm working to implement MapView for the given gpx file to show way points and tracks,please any one guide me to implement it with sample code.

Thanks in advance.

回答1:

It is working correctly

package com.lightcone.mapoverlaydemo;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

public class ShowTheMap extends MapActivity {

    private static double lat;
    private static double lon;
    private int latE6;
    private int lonE6;
    private MapController mapControl;
    private GeoPoint gp;
    private MapView mapView;

    private Button overlayButton, accessButton;
    private Button routeButton;
    private List<Overlay> mapOverlays;
    private Drawable drawable1, drawable2;
    private MyItemizedOverlay itemizedOverlay1, itemizedOverlay2;
    private boolean foodIsDisplayed = false;

    // Define an array containing the food overlay items

    private OverlayItem[] foodItem = {
            new OverlayItem(new GeoPoint(35952967, -83929158), "Food Title 1",
                    "Food snippet 1"),
            new OverlayItem(new GeoPoint(35953000, -83928000), "Food Title 2",
                    "Food snippet 2"),
            new OverlayItem(new GeoPoint(35955000, -83929158), "Food Title 3",
                    "Food snippet 3") };

    // Define an array containing the access overlay items

    private OverlayItem[] accessItem = {
            new OverlayItem(new GeoPoint(35953700, -83926158),
                    "Access Title 1", "Access snippet 1"),
            new OverlayItem(new GeoPoint(35954000, -83928200),
                    "Access Title 2", "Access snippet 2"),
            new OverlayItem(new GeoPoint(35955000, -83927558),
                    "Access Title 3", "Access snippet 3"),
            new OverlayItem(new GeoPoint(35954000, -83927158),
                    "Access Title 4", "Access snippet 4") };

    String TAG = "GPStest";
    // Set up the array of GeoPoints defining the route
    int numberRoutePoints;
    GeoPoint routePoints[]; // Dimension will be set in class RouteLoader below
    int routeGrade[]; // Index for slope of route from point i to point i+1
    RouteSegmentOverlay route; // This will hold the route segments
    boolean routeIsDisplayed = false;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE); // Suppress title bar for
                                                        // more space
        setContentView(R.layout.showthemap);

        // Add map controller with zoom controls
        mapView = (MapView) findViewById(R.id.mv);
        mapView.setSatellite(false);
        mapView.setTraffic(false);
        mapView.setBuiltInZoomControls(true); // Set android:clickable=true in
                                                // main.xml
        int maxZoom = mapView.getMaxZoomLevel();
        int initZoom = maxZoom - 2;
        mapControl = mapView.getController();
        mapControl.setZoom(initZoom);
        // Convert lat/long in degrees into integers in microdegrees
        latE6 = (int) (35.955 * 1e6);
        lonE6 = (int) (-83.9265 * 1e6);
        gp = new GeoPoint(latE6, lonE6);
        mapControl.animateTo(gp);

        // // Button to control food overlay
        // overlayButton = (Button)findViewById(R.id.doOverlay);
        // overlayButton.setOnClickListener(new OnClickListener(){
        // public void onClick(View v) {
        // setOverlay1();
        // }
        // });
        //      
        // // Button to control access overlay
        // accessButton = (Button)findViewById(R.id.doAccess);
        // accessButton.setOnClickListener(new OnClickListener(){
        // public void onClick(View v) {
        // setOverlay2();
        // }
        // });

        // Button to control route overlay
        routeButton = (Button) findViewById(R.id.doRoute);
        routeButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (!routeIsDisplayed) {
                    routeIsDisplayed = true;
                    loadRouteData();
                } else {
                    if (route != null)
                        route.setRouteView(false);
                    route = null; // To prevent multiple route instances if key
                                    // toggled rapidly (see line 235)
                    routeIsDisplayed = false;
                    mapView.postInvalidate();
                }
            }
        });

    }

    /*
     * Methods to set map overlays. In this case we will place a small overlay
     * image at a specified location. Place the marker image as a png file in
     * res > drawable-* . For example, the reference to
     * R.drawable.knifefork_small below is to an image file called
     * knifefork_small.png in the project folder res > drawable-hdpi. Can only
     * use lower case letters a-z, numbers 0-9, ., and _ in these image file
     * names. In this example the single overlay item is specified by drawable
     * and the location of the overlay item is specified by overlayitem.
     */

    // Display food location overlay. If not already displayed, clicking button
    // displays all
    // food overlays. If already displayed successive clicks remove items one by
    // one. This
    // illustrates ability to change individual overlay items dynamically at
    // runtime.

    public void setOverlay1() {
        int foodLength = foodItem.length;
        // Create itemizedOverlay2 if it doesn't exist and display all three
        // items
        if (!foodIsDisplayed) {
            mapOverlays = mapView.getOverlays();
            drawable1 = this.getResources().getDrawable(
                    R.drawable.knifefork_small);
            itemizedOverlay1 = new MyItemizedOverlay(drawable1);
            // Display all three items at once
            for (int i = 0; i < foodLength; i++) {
                itemizedOverlay1.addOverlay(foodItem[i]);
            }
            mapOverlays.add(itemizedOverlay1);
            foodIsDisplayed = !foodIsDisplayed;
            // Remove each item successively with button clicks
        } else {
            itemizedOverlay1.removeItem(itemizedOverlay1.size() - 1);
            if ((itemizedOverlay1.size() < 1))
                foodIsDisplayed = false;
        }
        // Added symbols will be displayed when map is redrawn so force redraw
        // now
        mapView.postInvalidate();
    }

    // Display accessibility overlay. If not already displayed, successive
    // button clicks display each of
    // the three icons successively, then the next removes them all. This
    // illustrates the ability to
    // change individual overlay items dynamically at runtime.

    public void setOverlay2() {
        int accessLength = accessItem.length;
        // Create itemizedOverlay2 if it doesn't exist
        if (itemizedOverlay2 == null) {
            mapOverlays = mapView.getOverlays();
            drawable2 = this.getResources().getDrawable(
                    R.drawable.accessibility);
            itemizedOverlay2 = new MyItemizedOverlay(drawable2);
        }
        // Add items with each click
        if (itemizedOverlay2.size() < accessLength) {
            itemizedOverlay2.addOverlay(accessItem[itemizedOverlay2.size()]);
            mapOverlays.add(itemizedOverlay2);
            // Remove all items with one click
        } else {
            for (int i = 0; i < accessLength; i++) {
                itemizedOverlay2.removeItem(accessLength - 1 - i);
            }
        }
        // Added symbols will be displayed when map is redrawn so force redraw
        // now
        mapView.postInvalidate();
    }

    // Method to insert latitude and longitude in degrees
    public static void putLatLong(double latitude, double longitude) {
        lat = latitude;
        lon = longitude;
    }

    // This sets the s key on the phone to toggle between satellite and map view
    // and the t key to toggle between traffic and no traffic view (traffic view
    // relevant only in urban areas where it is reported).

    public boolean onKeyDown(int keyCode, KeyEvent e) {
        if (keyCode == KeyEvent.KEYCODE_S) {
            mapView.setSatellite(!mapView.isSatellite());
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_T) {
            mapView.setTraffic(!mapView.isTraffic());
            mapControl.animateTo(gp); // To ensure change displays immediately
        }
        return (super.onKeyDown(keyCode, e));
    }

    // Required method since class extends MapActivity
    @Override
    protected boolean isRouteDisplayed() {
        return false; // Don't display a route
    }

    // Method to read route data from server as XML

    public void loadRouteData() {
        try {
            String url = "http://eagle.phys.utk.edu/reubendb/UTRoute.php";
            String data = "?lat1=35952967&lon1=-83929158&lat2=35956567&lon2=-83925450";
            // RouteLoader RL = new RouteLoader();
            // RL.execute(new URL(url+data));
            new RouteLoader().execute(new URL(url + data));
        } catch (MalformedURLException e) {
            Log.i("NETWORK", "Failed to generate valid URL");
        }
    }

    // Overlay a route. This method is only executed after loadRouteData()
    // completes
    // on background thread.

    public void overlayRoute() {
        if (route != null)
            return; // To prevent multiple route instances if key toggled
                    // rapidly (see also line 116)
        // Set up the overlay controller
        route = new RouteSegmentOverlay(routePoints, routeGrade); // My class
                                                                    // defining
                                                                    // route
                                                                    // overlay
        mapOverlays = mapView.getOverlays();
        mapOverlays.add(route);

        // Added symbols will be displayed when map is redrawn so force redraw
        // now
        mapView.postInvalidate();
    }

    /*
     * Class to implement single task on background thread without having to
     * manage the threads directly. Launch with
     * "new RouteLoader().execute(new URL(urlString)". Must be launched from the
     * UI thread and may only be invoked once. Adapted from example in Ch. 10 of
     * Android Wireless Application Development. Use this to do data load from
     * network on separate thread from main user interface to prevent locking
     * main UI if there is network delay.
     */

    private class RouteLoader extends AsyncTask<URL, String, String> {

        @Override
        protected String doInBackground(URL... params) {
            // This pattern takes more than one param but we'll just use the
            // first
            try {
                URL text = params[0];

                XmlPullParserFactory parserCreator;

                parserCreator = XmlPullParserFactory.newInstance();

                XmlPullParser parser = parserCreator.newPullParser();

                // parser.setInput(text.openStream(), null);
                parser.setInput(getResources()
                        .openRawResource(R.raw.fells_loop), null);

                publishProgress("Parsing XML...");

                int parserEvent = parser.getEventType();
                int pointCounter = -1;
                int wptCounter = -1;
                int totalWaypoints = -1;
                int lat = -1;
                int lon = -1;
                String wptDescription = "";
                int grade = -1;

                // Parse the XML returned on the network
                while (parserEvent != XmlPullParser.END_DOCUMENT) {
                    switch (parserEvent) {
                    case XmlPullParser.START_TAG:
                        String tag = parser.getName();
                        if (tag.compareTo("number") == 0) {
                            numberRoutePoints = Integer.parseInt(parser
                                    .getAttributeValue(null, "numpoints"));
                            totalWaypoints = Integer.parseInt(parser
                                    .getAttributeValue(null, "numwpts"));
                            routePoints = new GeoPoint[numberRoutePoints];
                            routeGrade = new int[numberRoutePoints];
                            Log.i(TAG, "   Total points = " + numberRoutePoints
                                    + " Total waypoints = " + totalWaypoints);
                        }
                        if (tag.compareTo("trkpt") == 0) {
                            pointCounter++;
                            lat = Integer.parseInt(parser.getAttributeValue(
                                    null, "lat"));
                            lon = Integer.parseInt(parser.getAttributeValue(
                                    null, "lon"));
                            grade = Integer.parseInt(parser.getAttributeValue(
                                    null, "grade"));
                            routePoints[pointCounter] = new GeoPoint(lat, lon);
                            routeGrade[pointCounter] = grade;
                            Log.i(TAG, "   trackpoint=" + pointCounter
                                    + " latitude=" + lat + " longitude=" + lon
                                    + " grade=" + grade);
                        } else if (tag.compareTo("wpt") == 0) {
                            wptCounter++;
                            lat = Integer.parseInt(parser.getAttributeValue(
                                    null, "lat"));
                            lon = Integer.parseInt(parser.getAttributeValue(
                                    null, "lon"));
                            wptDescription = parser.getAttributeValue(null,
                                    "description");
                            Log.i(TAG, "   waypoint=" + wptCounter
                                    + " latitude=" + lat + " longitude=" + lon
                                    + " " + wptDescription);
                        }
                        break;
                    }

                    parserEvent = parser.next();
                }

            } catch (Exception e) {
                Log.i("RouteLoader", "Failed in parsing XML", e);
                return "Finished with failure.";
            }

            return "Done...";
        }

        protected void onCancelled() {
            Log.i("RouteLoader", "GetRoute task Cancelled");
        }

        // Now that route data are loaded, execute the method to overlay the
        // route on the map
        protected void onPostExecute(String result) {
            Log.i(TAG, "Route data transfer complete");
            overlayRoute();
        }

        protected void onPreExecute() {
            Log.i(TAG, "Ready to load URL");
        }

        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
        }

    }

}

feel_loop.xml file content from raw folder

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<gpx
 version="1.0"
 creator="ExpertGPS 1.1.1 - http://www.topografix.com"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://www.topografix.com/GPX/1/0"
 xmlns:topografix="http://www.topografix.com/GPX/Private/TopoGrafix/0/1"
 xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd">
  <number numpoints="23" numwpts="2"></number>
  <wpt lat="35952967" lon="-83929158" description="Construction"></wpt>
  <wpt lat="35955038" lon="-83929126" description="Heavy traffic"></wpt>
  <trk>
    <trkseg>
        <trkpt lat="35952967" lon="-83929158" grade="1"></trkpt>
        <trkpt lat="35954021" lon="-83930341" grade="1"></trkpt>
        <trkpt lat="35954951" lon="-83929075" grade="1"></trkpt>

        <trkpt lat="35955038" lon="-83929126" grade="4"></trkpt>
        <trkpt lat="35955203" lon="-83928973" grade="1"></trkpt>
        <trkpt lat="35955212" lon="-83928855" grade="1"></trkpt>
        <trkpt lat="35955603" lon="-83928273" grade="2"></trkpt>
        <trkpt lat="35955807" lon="-83928369" grade="1"></trkpt>
        <trkpt lat="35955974" lon="-83927943" grade="1"></trkpt>
        <trkpt lat="35956063" lon="-83927720" grade="1"></trkpt>
        <trkpt lat="35956291" lon="-83927358" grade="1"></trkpt>
        <trkpt lat="35956471" lon="-83927229" grade="1"></trkpt>

        <trkpt lat="35956541" lon="-83927176" grade="2"></trkpt>
        <trkpt lat="35956397" lon="-83927044" grade="3"></trkpt>
        <trkpt lat="35956274" lon="-83926685" grade="1"></trkpt>
        <trkpt lat="35956213" lon="-83926642" grade="1"></trkpt>
        <trkpt lat="35956239" lon="-83926261" grade="1"></trkpt>
        <trkpt lat="35956202" lon="-83925722" grade="1"></trkpt>
        <trkpt lat="35956226" lon="-83925467" grade="1"></trkpt>
        <trkpt lat="35956343" lon="-83925502" grade="1"></trkpt>
        <trkpt lat="35956324" lon="-83925617" grade="1"></trkpt>

        <trkpt lat="35956445" lon="-83925379" grade="1"></trkpt>
        <trkpt lat="35956567" lon="-83925450" grade="1"></trkpt>
    </trkseg>
  </trk>
</gpx>


回答2:

Building on Kandha's answer, for the actual GPX parsing you can easily use one of the existing libraries to do it. See this other StackOverflow question.



标签: android map