【问题标题】:How to parse and plot gpx file has an android MapView如何解析和绘制 gpx 文件有一个 android MapView
【发布时间】:2011-09-17 00:38:36
【问题描述】:

我正在为给定的 gpx 文件实现 MapView 以显示路点和轨迹,请任何人指导我用示例代码实现它。 p>

提前致谢。

【问题讨论】:

    标签: android map


    【解决方案1】:

    工作正常

    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 文件内容

    <?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】:

      基于 Kandha 的回答,对于实际的 GPX 解析,您可以轻松地使用现有库之一来完成它。见this other StackOverflow question

      【讨论】:

        猜你喜欢
        • 2013-09-10
        • 1970-01-01
        • 2018-12-28
        • 2010-10-14
        • 2011-02-28
        • 2022-08-02
        • 2012-01-28
        • 2019-01-19
        • 2020-08-15
        相关资源
        最近更新 更多