如何使用 kml 文件在地图上绘制路径?

Posted

技术标签:

【中文标题】如何使用 kml 文件在地图上绘制路径?【英文标题】:How to draw a path on a map using kml file? 【发布时间】:2011-03-07 18:05:14 【问题描述】:

我可以解析 kml 文件以在 android 中显示路径或点吗?请问你能帮我解决这个问题吗?

这是我想在 android 谷歌地图中显示的 kml 示例代码:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Paths</name>
<description>Examples of paths. Note that the tessellate tag is by default
  set to 0. If you want to create tessellated lines, they must be authored
  (or edited) directly in KML.</description>
<Style id="yellowLineGreenPoly">
  <LineStyle>
    <color>7f00ffff</color>
    <width>4</width>
  </LineStyle>
  <PolyStyle>
    <color>7f00ff00</color>
  </PolyStyle>
</Style>
<Placemark>
  <name>Absolute Extruded</name>
  <description>Transparent green wall with yellow outlines</description>
  <styleUrl>#yellowLineGreenPoly</styleUrl>
  <LineString>
    <extrude>1</extrude>
    <tessellate>1</tessellate>
    <altitudeMode>absolute</altitudeMode>
    <coordinates> -112.2550785337791,36.07954952145647,2357
      -112.2549277039738,36.08117083492122,2357
      -112.2552505069063,36.08260761307279,2357
      -112.2564540158376,36.08395660588506,2357
      -112.2580238976449,36.08511401044813,2357
      -112.2595218489022,36.08584355239394,2357
      -112.2608216347552,36.08612634548589,2357
      -112.262073428656,36.08626019085147,2357
      -112.2633204928495,36.08621519860091,2357
      -112.2644963846444,36.08627897945274,2357
      -112.2656969554589,36.08649599090644,2357 
    </coordinates>
    <LineString>
    </Placemark>
    </Document>
    </kml>

当我将此文件加载到标准网络谷歌地图时,它会很好地显示它,但是当我尝试使用 android 谷歌地图做同样的事情时,它不会那样做。它只是带我去一些地方,就是这样。我正在考虑改变听众班。目前看起来是这样的:

private class MyLocationListener implements LocationListener 

    @Override
    public void onLocationChanged(Location loc) 
        if (loc != null) 
            latitude = (loc.getLatitude() * 1E6);
            longitude = (loc.getLongitude() * 1E6);
             Toast.makeText(getBaseContext(), 
                     "Location changed : Lat: " + latitude + 
                     " Lng: " + longitude, 
                     Toast.LENGTH_SHORT).show();

             GeoPoint p = new GeoPoint(
                     (int) (loc.getLatitude() * 1E6), 
                     (int) (loc.getLongitude() * 1E6));

             mc.animateTo(p);
             mapView.invalidate();
           
    

//---------------------------------------------------------------
    @Override
    public void onProviderDisabled(String provider) 
        // TODO Auto-generated method stub
    

    @Override
    public void onProviderEnabled(String provider) 
        // TODO Auto-generated method stub
    

    @Override
    public void onStatusChanged(String provider, int status, 
        Bundle extras) 
        //TODO Auto-generated method stub
    

请有人告诉我我在这里做错了什么?

【问题讨论】:

【参考方案1】:

据我所知,在上面的代码中,您不会将 kml 数据传递到代码中的任何地方的 mapView。 要显示路线,您应该解析 kml 数据,即通过 SAX 解析器,然后在地图上显示路线标记。

请参阅下面的代码以获取示例,但它并不完整 - 仅供您参考并获得一些想法。

这是一个简单的 bean,用于保存我将要解析的路由信息​​。

package com.myapp.android.model.navigation;

import java.util.ArrayList;
import java.util.Iterator;


public class NavigationDataSet  

private ArrayList<Placemark> placemarks = new ArrayList<Placemark>();
private Placemark currentPlacemark;
private Placemark routePlacemark;

public String toString() 
    String s= "";
    for (Iterator<Placemark> iter=placemarks.iterator();iter.hasNext();) 
        Placemark p = (Placemark)iter.next();
        s += p.getTitle() + "\n" + p.getDescription() + "\n\n";
    
    return s;


public void addCurrentPlacemark() 
    placemarks.add(currentPlacemark);


public ArrayList<Placemark> getPlacemarks() 
    return placemarks;


public void setPlacemarks(ArrayList<Placemark> placemarks) 
    this.placemarks = placemarks;


public Placemark getCurrentPlacemark() 
    return currentPlacemark;


public void setCurrentPlacemark(Placemark currentPlacemark) 
    this.currentPlacemark = currentPlacemark;


public Placemark getRoutePlacemark() 
    return routePlacemark;


public void setRoutePlacemark(Placemark routePlacemark) 
    this.routePlacemark = routePlacemark;



以及解析 kml 的 SAX 处理程序:

package com.myapp.android.model.navigation;

import android.util.Log;
import com.myapp.android.myapp;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.myapp.android.model.navigation.NavigationDataSet;
import com.myapp.android.model.navigation.Placemark;


public class NavigationSaxHandler extends DefaultHandler 

 // =========================================================== 
 // Fields 
 // =========================================================== 

 private boolean in_kmltag = false; 
 private boolean in_placemarktag = false; 
 private boolean in_nametag = false;
 private boolean in_descriptiontag = false;
 private boolean in_geometrycollectiontag = false;
 private boolean in_linestringtag = false;
 private boolean in_pointtag = false;
 private boolean in_coordinatestag = false;

 private StringBuffer buffer;

 private NavigationDataSet navigationDataSet = new NavigationDataSet(); 

 // =========================================================== 
 // Getter & Setter 
 // =========================================================== 

 public NavigationDataSet getParsedData() 
      navigationDataSet.getCurrentPlacemark().setCoordinates(buffer.toString().trim());
      return this.navigationDataSet; 
  

 // =========================================================== 
 // Methods 
 // =========================================================== 
 @Override 
 public void startDocument() throws SAXException  
      this.navigationDataSet = new NavigationDataSet(); 
  

 @Override 
 public void endDocument() throws SAXException  
      // Nothing to do
  

 /** Gets be called on opening tags like: 
  * <tag> 
  * Can provide attribute(s), when xml was like: 
  * <tag attribute="attributeValue">*/ 
 @Override 
 public void startElement(String namespaceURI, String localName, 
           String qName, Attributes atts) throws SAXException  
      if (localName.equals("kml"))  
           this.in_kmltag = true;
       else if (localName.equals("Placemark"))  
           this.in_placemarktag = true; 
           navigationDataSet.setCurrentPlacemark(new Placemark());
       else if (localName.equals("name"))  
           this.in_nametag = true;
       else if (localName.equals("description"))  
          this.in_descriptiontag = true;
       else if (localName.equals("GeometryCollection"))  
          this.in_geometrycollectiontag = true;
       else if (localName.equals("LineString"))  
          this.in_linestringtag = true;              
       else if (localName.equals("point"))  
          this.in_pointtag = true;          
       else if (localName.equals("coordinates")) 
          buffer = new StringBuffer();
          this.in_coordinatestag = true;                        
      
  

 /** Gets be called on closing tags like: 
  * </tag> */ 
 @Override 
 public void endElement(String namespaceURI, String localName, String qName) 
           throws SAXException  
       if (localName.equals("kml")) 
           this.in_kmltag = false; 
        else if (localName.equals("Placemark"))  
           this.in_placemarktag = false;

       if ("Route".equals(navigationDataSet.getCurrentPlacemark().getTitle())) 
               navigationDataSet.setRoutePlacemark(navigationDataSet.getCurrentPlacemark());
        else navigationDataSet.addCurrentPlacemark();

        else if (localName.equals("name"))  
           this.in_nametag = false;           
        else if (localName.equals("description"))  
           this.in_descriptiontag = false;
        else if (localName.equals("GeometryCollection"))  
           this.in_geometrycollectiontag = false;
        else if (localName.equals("LineString"))  
           this.in_linestringtag = false;              
        else if (localName.equals("point"))  
           this.in_pointtag = false;          
        else if (localName.equals("coordinates"))  
           this.in_coordinatestag = false;
       
  

 /** Gets be called on the following structure: 
  * <tag>characters</tag> */ 
 @Override 
public void characters(char ch[], int start, int length)  
    if(this.in_nametag) 
        if (navigationDataSet.getCurrentPlacemark()==null) navigationDataSet.setCurrentPlacemark(new Placemark());
        navigationDataSet.getCurrentPlacemark().setTitle(new String(ch, start, length));            
     else 
    if(this.in_descriptiontag) 
        if (navigationDataSet.getCurrentPlacemark()==null) navigationDataSet.setCurrentPlacemark(new Placemark());
        navigationDataSet.getCurrentPlacemark().setDescription(new String(ch, start, length));          
     else
    if(this.in_coordinatestag)        
        if (navigationDataSet.getCurrentPlacemark()==null) navigationDataSet.setCurrentPlacemark(new Placemark());
        //navigationDataSet.getCurrentPlacemark().setCoordinates(new String(ch, start, length));
        buffer.append(ch, start, length);
    
 

还有一个简单的placeMark bean:

package com.myapp.android.model.navigation;

public class Placemark 

String title;
String description;
String coordinates;
String address;

public String getTitle() 
    return title;

public void setTitle(String title) 
    this.title = title;

public String getDescription() 
    return description;

public void setDescription(String description) 
    this.description = description;

public String getCoordinates() 
    return coordinates;

public void setCoordinates(String coordinates) 
    this.coordinates = coordinates;

public String getAddress() 
    return address;

public void setAddress(String address) 
    this.address = address;



最后是我模型中调用计算的服务类:

package com.myapp.android.model.navigation;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import com.myapp.android.myapp;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import android.util.Log;

public class MapService 

public static final int MODE_ANY = 0;
public static final int MODE_CAR = 1;
public static final int MODE_WALKING = 2;


public static String inputStreamToString (InputStream in) throws IOException 
    StringBuffer out = new StringBuffer();
    byte[] b = new byte[4096];
    for (int n; (n = in.read(b)) != -1;) 
        out.append(new String(b, 0, n));
    
    return out.toString();



public static NavigationDataSet calculateRoute(Double startLat, Double startLng, Double targetLat, Double targetLng, int mode) 
    return calculateRoute(startLat + "," + startLng, targetLat + "," + targetLng, mode);


public static NavigationDataSet calculateRoute(String startCoords, String targetCoords, int mode) 
    String urlPedestrianMode = "http://maps.google.com/maps?" + "saddr=" + startCoords + "&daddr="
            + targetCoords + "&sll=" + startCoords + "&dirflg=w&hl=en&ie=UTF8&z=14&output=kml";

    Log.d(myapp.APP, "urlPedestrianMode: "+urlPedestrianMode);

    String urlCarMode = "http://maps.google.com/maps?" + "saddr=" + startCoords + "&daddr="
            + targetCoords + "&sll=" + startCoords + "&hl=en&ie=UTF8&z=14&output=kml";

    Log.d(myapp.APP, "urlCarMode: "+urlCarMode);

    NavigationDataSet navSet = null;
    // for mode_any: try pedestrian route calculation first, if it fails, fall back to car route
    if (mode==MODE_ANY||mode==MODE_WALKING) navSet = MapService.getNavigationDataSet(urlPedestrianMode);
    if (mode==MODE_ANY&&navSet==null||mode==MODE_CAR) navSet = MapService.getNavigationDataSet(urlCarMode);
    return navSet;


/**
 * Retrieve navigation data set from either remote URL or String
 * @param url
 * @return navigation set
 */
public static NavigationDataSet getNavigationDataSet(String url) 

    // urlString = "http://192.168.1.100:80/test.kml";
    Log.d(myapp.APP,"urlString -->> " + url);
    NavigationDataSet navigationDataSet = null;
    try
                   
        final URL aUrl = new URL(url);
        final URLConnection conn = aUrl.openConnection();
        conn.setReadTimeout(15 * 1000);  // timeout for reading the google maps data: 15 secs
        conn.connect();

        /* Get a SAXParser from the SAXPArserFactory. */
        SAXParserFactory spf = SAXParserFactory.newInstance(); 
        SAXParser sp = spf.newSAXParser(); 

        /* Get the XMLReader of the SAXParser we created. */
        XMLReader xr = sp.getXMLReader();

        /* Create a new ContentHandler and apply it to the XML-Reader*/ 
        NavigationSaxHandler navSax2Handler = new NavigationSaxHandler(); 
        xr.setContentHandler(navSax2Handler); 

        /* Parse the xml-data from our URL. */ 
        xr.parse(new InputSource(aUrl.openStream()));

        /* Our NavigationSaxHandler now provides the parsed data to us. */ 
        navigationDataSet = navSax2Handler.getParsedData(); 

        /* Set the result to be displayed in our GUI. */ 
        Log.d(myapp.APP,"navigationDataSet: "+navigationDataSet.toString());

     catch (Exception e) 
        // Log.e(myapp.APP, "error with kml xml", e);
        navigationDataSet = null;
       

    return navigationDataSet;



绘图:

/**
 * Does the actual drawing of the route, based on the geo points provided in the nav set
 *
 * @param navSet     Navigation set bean that holds the route information, incl. geo pos
 * @param color      Color in which to draw the lines
 * @param mMapView01 Map view to draw onto
 */
public void drawPath(NavigationDataSet navSet, int color, MapView mMapView01) 

    Log.d(myapp.APP, "map color before: " + color);        

    // color correction for dining, make it darker
    if (color == Color.parseColor("#add331")) color = Color.parseColor("#6C8715");
    Log.d(myapp.APP, "map color after: " + color);

    Collection overlaysToAddAgain = new ArrayList();
    for (Iterator iter = mMapView01.getOverlays().iterator(); iter.hasNext();) 
        Object o = iter.next();
        Log.d(myapp.APP, "overlay type: " + o.getClass().getName());
        if (!RouteOverlay.class.getName().equals(o.getClass().getName())) 
            // mMapView01.getOverlays().remove(o);
            overlaysToAddAgain.add(o);
        
    
    mMapView01.getOverlays().clear();
    mMapView01.getOverlays().addAll(overlaysToAddAgain);

    String path = navSet.getRoutePlacemark().getCoordinates();
    Log.d(myapp.APP, "path=" + path);
    if (path != null && path.trim().length() > 0) 
        String[] pairs = path.trim().split(" ");

        Log.d(myapp.APP, "pairs.length=" + pairs.length);

        String[] lngLat = pairs[0].split(","); // lngLat[0]=longitude lngLat[1]=latitude lngLat[2]=height

        Log.d(myapp.APP, "lnglat =" + lngLat + ", length: " + lngLat.length);

        if (lngLat.length<3) lngLat = pairs[1].split(","); // if first pair is not transferred completely, take seconds pair //TODO 

        try 
            GeoPoint startGP = new GeoPoint((int) (Double.parseDouble(lngLat[1]) * 1E6), (int) (Double.parseDouble(lngLat[0]) * 1E6));
            mMapView01.getOverlays().add(new RouteOverlay(startGP, startGP, 1));
            GeoPoint gp1;
            GeoPoint gp2 = startGP;

            for (int i = 1; i < pairs.length; i++) // the last one would be crash
            
                lngLat = pairs[i].split(",");

                gp1 = gp2;

                if (lngLat.length >= 2 && gp1.getLatitudeE6() > 0 && gp1.getLongitudeE6() > 0
                        && gp2.getLatitudeE6() > 0 && gp2.getLongitudeE6() > 0) 

                    // for GeoPoint, first:latitude, second:longitude
                    gp2 = new GeoPoint((int) (Double.parseDouble(lngLat[1]) * 1E6), (int) (Double.parseDouble(lngLat[0]) * 1E6));

                    if (gp2.getLatitudeE6() != 22200000)  
                        mMapView01.getOverlays().add(new RouteOverlay(gp1, gp2, 2, color));
                        Log.d(myapp.APP, "draw:" + gp1.getLatitudeE6() + "/" + gp1.getLongitudeE6() + " TO " + gp2.getLatitudeE6() + "/" + gp2.getLongitudeE6());
                    
                
                // Log.d(myapp.APP,"pair:" + pairs[i]);
            
            //routeOverlays.add(new RouteOverlay(gp2,gp2, 3));
            mMapView01.getOverlays().add(new RouteOverlay(gp2, gp2, 3));
         catch (NumberFormatException e) 
            Log.e(myapp.APP, "Cannot draw route.", e);
        
    
    // mMapView01.getOverlays().addAll(routeOverlays); // use the default color
    mMapView01.setEnabled(true);

这是 RouteOverlay 类:

package com.myapp.android.activity.map.nav;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

public class RouteOverlay extends Overlay  

private GeoPoint gp1;
private GeoPoint gp2;
private int mRadius=6;
private int mode=0;
private int defaultColor;
private String text="";
private Bitmap img = null;

public RouteOverlay(GeoPoint gp1,GeoPoint gp2,int mode)  // GeoPoint is a int. (6E)
    this.gp1 = gp1;
    this.gp2 = gp2;
    this.mode = mode;
    defaultColor = 999; // no defaultColor


public RouteOverlay(GeoPoint gp1,GeoPoint gp2,int mode, int defaultColor) 
    this.gp1 = gp1;
    this.gp2 = gp2;
    this.mode = mode;
    this.defaultColor = defaultColor;


public void setText(String t) 
    this.text = t;


public void setBitmap(Bitmap bitmap)  
    this.img = bitmap;


public int getMode() 
    return mode;


@Override
public boolean draw (Canvas canvas, MapView mapView, boolean shadow, long when) 
    Projection projection = mapView.getProjection();
    if (shadow == false) 
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        Point point = new Point();
        projection.toPixels(gp1, point);
        // mode=1&#65306;start
        if(mode==1) 
            if(defaultColor==999)
            paint.setColor(Color.BLACK); // Color.BLUE
            else
            paint.setColor(defaultColor);
            RectF oval=new RectF(point.x - mRadius, point.y - mRadius,
            point.x + mRadius, point.y + mRadius);
            // start point
            canvas.drawOval(oval, paint);
        
        // mode=2&#65306;path
        else if(mode==2) 
            if(defaultColor==999)
            paint.setColor(Color.RED);
            else
            paint.setColor(defaultColor);
            Point point2 = new Point();
            projection.toPixels(gp2, point2);
            paint.setStrokeWidth(5);
            paint.setAlpha(defaultColor==Color.parseColor("#6C8715")?220:120);
            canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);
        
        /* mode=3&#65306;end */
        else if(mode==3) 
            /* the last path */

            if(defaultColor==999)
                paint.setColor(Color.BLACK);  // Color.GREEN
            else
                paint.setColor(defaultColor);

            Point point2 = new Point();
            projection.toPixels(gp2, point2);
            paint.setStrokeWidth(5);
            paint.setAlpha(defaultColor==Color.parseColor("#6C8715")?220:120);
            canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);
            RectF oval=new RectF(point2.x - mRadius,point2.y - mRadius,
            point2.x + mRadius,point2.y + mRadius);
            /* end point */
            paint.setAlpha(255);
            canvas.drawOval(oval, paint);
        
    
    return super.draw(canvas, mapView, shadow, when);



【讨论】:

另外,您可能会对这个链接感兴趣:csie-tw.blogspot.com/2009/06/… 您能否提供一个您在 SO 中提交的代码的工作示例。也许是 KML 和 SAxParsing 的一个简单示例。或者我可以下载的某个网站。我是新手,我更喜欢从工作示例中学习。谢谢。 我没有独立的样本/apk。我的示例紧密集成到我已经完成的商业应用程序中。您可以从谷歌地图网络服务器获取任何 kml,只需计算一条路线,然后从浏览器获取该路线计算的 url,并将 &output=kml 添加到 url,这将为您提供 kml 文件。 我已经在 public void characters(char ch[], int start, int length) 方法中打印了一个,这样我就可以检查所有的解析值。几乎在解析文件的最后,它显示了两点之间的完整距离 -->900 m(约 11 分钟)地图数据 ©2011 Google。有人知道如何获得这个值吗?是否需要在 end- 和 startElement 方法中创建额外的标签? 警告未来发现此代码的人,characters() 方法不正确。你永远不应该假设单个 characters() 方法调用将包含标签的所有文本内容。【参考方案2】:

感谢 Mathias Lin,测试成功!

另外,在activity中Mathias方法的示例实现如下。

public class DirectionMapActivity extends MapActivity 

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.directionmap);

        MapView mapView = (MapView) findViewById(R.id.mapview);
        mapView.setBuiltInZoomControls(true);

        // Acquire a reference to the system Location Manager
        LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

        String locationProvider = LocationManager.NETWORK_PROVIDER;
        Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);

        StringBuilder urlString = new StringBuilder();
        urlString.append("http://maps.google.com/maps?f=d&hl=en");
        urlString.append("&saddr=");//from
        urlString.append( Double.toString(lastKnownLocation.getLatitude() ));
        urlString.append(",");
        urlString.append( Double.toString(lastKnownLocation.getLongitude() ));
        urlString.append("&daddr=");//to
        urlString.append( Double.toString((double)dest[0]/1.0E6 ));
        urlString.append(",");
        urlString.append( Double.toString((double)dest[1]/1.0E6 ));
        urlString.append("&ie=UTF8&0&om=0&output=kml");

        try
            // setup the url
            URL url = new URL(urlString.toString());
            // create the factory
            SAXParserFactory factory = SAXParserFactory.newInstance();
            // create a parser
            SAXParser parser = factory.newSAXParser();
            // create the reader (scanner)
            XMLReader xmlreader = parser.getXMLReader();
            // instantiate our handler
            NavigationSaxHandler navSaxHandler = new NavigationSaxHandler();
            // assign our handler
            xmlreader.setContentHandler(navSaxHandler);
            // get our data via the url class
            InputSource is = new InputSource(url.openStream());
            // perform the synchronous parse           
            xmlreader.parse(is);
            // get the results - should be a fully populated RSSFeed instance, or null on error
            NavigationDataSet ds = navSaxHandler.getParsedData();

            // draw path
            drawPath(ds, Color.parseColor("#add331"), mapView );

            // find boundary by using itemized overlay
            GeoPoint destPoint = new GeoPoint(dest[0],dest[1]);
            GeoPoint currentPoint = new GeoPoint( new Double(lastKnownLocation.getLatitude()*1E6).intValue()
                                                ,new Double(lastKnownLocation.getLongitude()*1E6).intValue() );

            Drawable dot = this.getResources().getDrawable(R.drawable.pixel);
            MapItemizedOverlay bgItemizedOverlay = new MapItemizedOverlay(dot,this);
            OverlayItem currentPixel = new OverlayItem(destPoint, null, null );
            OverlayItem destPixel = new OverlayItem(currentPoint, null, null );
            bgItemizedOverlay.addOverlay(currentPixel);
            bgItemizedOverlay.addOverlay(destPixel);

            // center and zoom in the map
            MapController mc = mapView.getController();
            mc.zoomToSpan(bgItemizedOverlay.getLatSpanE6()*2,bgItemizedOverlay.getLonSpanE6()*2);
            mc.animateTo(new GeoPoint(
                    (currentPoint.getLatitudeE6() + destPoint.getLatitudeE6()) / 2
                    , (currentPoint.getLongitudeE6() + destPoint.getLongitudeE6()) / 2));

         catch(Exception e) 
            Log.d("DirectionMap","Exception parsing kml.");
        

    
    // and the rest of the methods in activity, e.g. drawPath() etc...

MapItemizedOverlay.java

public class MapItemizedOverlay extends ItemizedOverlay
    private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
    private Context mContext;

    public MapItemizedOverlay(Drawable defaultMarker, Context context) 
          super(boundCenterBottom(defaultMarker));
          mContext = context;
    

    public void addOverlay(OverlayItem overlay) 
        mOverlays.add(overlay);
        populate();
    

    @Override
    protected OverlayItem createItem(int i) 
      return mOverlays.get(i);
    

    @Override
    public int size() 
      return mOverlays.size();
    


【讨论】:

嗨 alvinsj,是否可以公开一个执行上述功能的工作项目?非常感谢。【参考方案3】:

Google Maps KML Importing Utility 现在有一个测试版。

它是Google Maps Android API Utility Library 的一部分。如文档所述,它允许从流中加载 KML 文件

KmlLayer layer = new KmlLayer(getMap(), kmlInputStream, getApplicationContext());

或本地资源

KmlLayer layer = new KmlLayer(getMap(), R.raw.kmlFile, getApplicationContext());

创建 KmlLayer 后,调用 addLayerToMap() 将导入的数据添加到地图上。

layer.addLayerToMap();

【讨论】:

【参考方案4】:

Mathias Lin 代码运行良好。但是,您可能需要考虑在 drawPath 方法中更改此部分:

 if (lngLat.length >= 2 && gp1.getLatitudeE6() > 0 && gp1.getLongitudeE6() > 0
                    && gp2.getLatitudeE6() > 0 && gp2.getLongitudeE6() > 0) 

GeoPoint 也可以小于零,我切换到:

     if (lngLat.length >= 2 && gp1.getLatitudeE6() != 0 && gp1.getLongitudeE6() != 0
                    && gp2.getLatitudeE6() != 0 && gp2.getLongitudeE6() != 0) 

谢谢你:D

【讨论】:

以上是关于如何使用 kml 文件在地图上绘制路径?的主要内容,如果未能解决你的问题,请参考以下文章

Android:如何加载 KML

如何在自定义地图上进行离线地理定位,phonegap+kml

在地图上绘制 10 万个经纬度位置

google maps api v3 导出当前地图的 kml 文件

使用 kml 文件时,Google 地图缩放被覆盖

如何将 kml 多边形几何数据转换为谷歌多边形坐标