2012-12-17 58 views
9

Tôi đang phát triển một ứng dụng mà tôi cần biết đường dẫn giữa vị trí hiện tại của người dùng và điểm ưa thích.Google Maps Android V2 và API hướng

Tôi đang sử dụng android 2.3.3, google maps android v2 và api chỉ đường. Vấn đề của tôi là tất cả mã tôi đã tìm thấy là dành cho phiên bản cũ của bản đồ và tôi cũng đã cố gắng điều chỉnh mã nhưng tôi đã thất bại. Tôi cố gắng thay đổi GeoPoint (không được hỗ trợ trong phiên bản mới này) trong LatLng. vấn đề là tôi không thể hiển thị đường dẫn, để làm điều đó tôi tạo một polyline mới và tôi thêm nó vào bản đồ.

tôi gửi mã của tôi:

Parser:

public interface Parser { 
    public Route parse(); 
} 

XMLParser

public class XMLParser { 
    // names of the XML tags 
    protected static final String MARKERS = "markers"; 
    protected static final String MARKER = "marker"; 

    protected URL feedUrl; 

    protected XMLParser(final String feedUrl) { 
      try { 
        this.feedUrl = new URL(feedUrl); 
      } catch (MalformedURLException e) { 
        Log.e(e.getMessage(), "XML parser - " + feedUrl); 
      } 
    } 

    protected InputStream getInputStream() { 
      try { 
        return feedUrl.openConnection().getInputStream(); 
      } catch (IOException e) { 
        Log.e(e.getMessage(), "XML parser - " + feedUrl); 
        return null; 
      } 
    } 
} 

JsonParser (phân tích theo hướng json google)

public class JsonParser extends XMLParser implements Parser { 
    /** Distance covered. **/ 
    private int distance; 

    public JsonParser(String feedUrl) { 
     super(feedUrl); 
    } 

    /** 
    * Parses a url pointing to a Google JSON object to a Route object. 
    * @return a Route object based on the JSON object. 
    */ 

    public Route parse() { 
     // turn the stream into a string 
     final String result = convertStreamToString(this.getInputStream()); 
     //Create an empty route 
     final Route route = new Route(); 
     //Create an empty segment 
     final Segment segment = new Segment(); 
     try { 
      //Tranform the string into a json object 
      final JSONObject json = new JSONObject(result); 
      //Get the route object 
      final JSONObject jsonRoute = json.getJSONArray("routes").getJSONObject(0); 
      //Get the leg, only one leg as we don't support waypoints 
      final JSONObject leg = jsonRoute.getJSONArray("legs").getJSONObject(0); 
      //Get the steps for this leg 
      final JSONArray steps = leg.getJSONArray("steps"); 
      //Number of steps for use in for loop 
      final int numSteps = steps.length(); 
      //Set the name of this route using the start & end addresses 
      route.setName(leg.getString("start_address") + " to " + leg.getString("end_address")); 
      //Get google's copyright notice (tos requirement) 
      route.setCopyright(jsonRoute.getString("copyrights")); 
      //Get the total length of the route. 
      route.setLength(leg.getJSONObject("distance").getInt("value")); 
      //Get any warnings provided (tos requirement) 
      if (!jsonRoute.getJSONArray("warnings").isNull(0)) { 
       route.setWarning(jsonRoute.getJSONArray("warnings").getString(0)); 
      } 
      /* Loop through the steps, creating a segment for each one and 
      * decoding any polylines found as we go to add to the route object's 
      * map array. Using an explicit for loop because it is faster! 
      */ 
      for (int i = 0; i < numSteps; i++) { 
       //Get the individual step 
       final JSONObject step = steps.getJSONObject(i); 
       //Get the start position for this step and set it on the segment 
       final JSONObject start = step.getJSONObject("start_location"); 
       final LatLng position = new LatLng(start.getDouble("lat"), start.getDouble("lng")); 
       segment.setPoint(position); 
       //Set the length of this segment in metres 
       final int length = step.getJSONObject("distance").getInt("value"); 
       distance += length; 
       segment.setLength(length); 
       segment.setDistance(distance/1000); 
       //Strip html from google directions and set as turn instruction 
       segment.setInstruction(step.getString("html_instructions").replaceAll("<(.*?)*>", "")); 
       //Retrieve & decode this segment's polyline and add it to the route. 
       route.addPoints(decodePolyLine(step.getJSONObject("polyline").getString("points"))); 
       //Push a copy of the segment to the route 
       route.addSegment(segment.copy()); 
      } 
     } catch (JSONException e) { 
      Log.e(e.getMessage(), "Google JSON Parser - " + feedUrl); 
     } 
     return route; 
    } 

    /** 
    * Convert an inputstream to a string. 
    * @param input inputstream to convert. 
    * @return a String of the inputstream. 
    */ 

    private static String convertStreamToString(final InputStream input) { 
     final BufferedReader reader = new BufferedReader(new InputStreamReader(input)); 
     final StringBuilder sBuf = new StringBuilder(); 

     String line = null; 
     try { 
      while ((line = reader.readLine()) != null) { 
       sBuf.append(line); 
      } 
     } catch (IOException e) { 
      Log.e(e.getMessage(), "Google parser, stream2string"); 
     } finally { 
      try { 
       input.close(); 
      } catch (IOException e) { 
       Log.e(e.getMessage(), "Google parser, stream2string"); 
      } 
     } 
     return sBuf.toString(); 
    } 

    /** 
    * Decode a polyline string into a list of LatLng. 
    * @param poly polyline encoded string to decode. 
    * @return the list of GeoPoints represented by this polystring. 
    */ 

    private List<LatLng> decodePolyLine(final String poly) { 
     int len = poly.length(); 
     int index = 0; 
     List<LatLng> decoded = new LinkedList<LatLng>(); 
     int lat = 0; 
     int lng = 0; 

     while (index < len) { 
      int b; 
      int shift = 0; 
      int result = 0; 
      do { 
       b = poly.charAt(index++) - 63; 
       result |= (b & 0x1f) << shift; 
       shift += 5; 
      } while (b >= 0x20); 
      int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
      lat += dlat; 

      shift = 0; 
      result = 0; 
      do { 
       b = poly.charAt(index++) - 63; 
       result |= (b & 0x1f) << shift; 
       shift += 5; 
      } while (b >= 0x20); 
      int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
      lng += dlng; 

      decoded.add(new LatLng((lat/1E5),(lng/1E5))); 
     } 

     return decoded; 
    } 
} 

Route (để tiết kiệm json thông tin)

public class Route { 
    private String name; 
    private final List<LatLng> points; 
    private List<Segment> segments; 
    private String copyright; 
    private String warning; 
    private String country; 
    private int length; 
    private String polyline; 

    public Route() { 
     points = new LinkedList<LatLng>(); 
     segments = new LinkedList<Segment>(); 
    } 

    public void addPoint(final LatLng p) { 
     points.add(p); 
    } 

    public void addPoints(final List<LatLng> points) { 
     this.points.addAll(points); 
    } 

    public List<LatLng> getPoints() { 
     return points; 
    } 

    public void addSegment(final Segment s) { 
     segments.add(s); 
    } 

    public List<Segment> getSegments() { 
     return segments; 
    } 

    /** 
    * @param name the name to set 
    */ 
    public void setName(final String name) { 
     this.name = name; 
    } 

    /** 
    * @return the name 
    */ 
    public String getName() { 
     return name; 
    } 

    /** 
     * @param copyright the copyright to set 
     */ 
    public void setCopyright(String copyright) { 
     this.copyright = copyright; 
    } 

    /** 
     * @return the copyright 
     */ 
    public String getCopyright() { 
     return copyright; 
    } 

    /** 
     * @param warning the warning to set 
     */ 
    public void setWarning(String warning) { 
     this.warning = warning; 
    } 

    /** 
     * @return the warning 
     */ 
    public String getWarning() { 
     return warning; 
    } 

    /** 
     * @param country the country to set 
     */ 
    public void setCountry(String country) { 
     this.country = country; 
    } 

    /** 
     * @return the country 
     */ 
    public String getCountry() { 
     return country; 
    } 

    /** 
     * @param length the length to set 
     */ 
    public void setLength(int length) { 
     this.length = length; 
    } 

    /** 
     * @return the length 
     */ 
    public int getLength() { 
     return length; 
    } 


    /** 
     * @param polyline the polyline to set 
     */ 
    public void setPolyline(String polyline) { 
     this.polyline = polyline; 
    } 

    /** 
     * @return the polyline 
     */ 
    public String getPolyline() { 
     return polyline; 
    } 

} 

Segment:

public class Segment { 
    /** Points in this segment. **/ 
    private LatLng start; 
    /** Turn instruction to reach next segment. **/ 
    private String instruction; 
    /** Length of segment. **/ 
    private int length; 
    /** Distance covered. **/ 
    private double distance; 

    /** 
    * Create an empty segment. 
    */ 

    public Segment() { 
    } 


    /** 
    * Set the turn instruction. 
    * @param turn Turn instruction string. 
    */ 

    public void setInstruction(final String turn) { 
      this.instruction = turn; 
    } 

    /** 
    * Get the turn instruction to reach next segment. 
    * @return a String of the turn instruction. 
    */ 

    public String getInstruction() { 
      return instruction; 
    } 

    /** 
    * Add a point to this segment. 
    * @param point LatLng to add. 
    */ 

    public void setPoint(LatLng point) { 
      start = point; 
    } 

    /** Get the starting point of this 
    * segment. 
    * @return a LatLng 
    */ 

    public LatLng startPoint() { 
      return start; 
    } 

    /** Creates a segment which is a copy of this one. 
    * @return a Segment that is a copy of this one. 
    */ 

    public Segment copy() { 
      final Segment copy = new Segment(); 
      copy.start = start; 
      copy.instruction = instruction; 
      copy.length = length; 
      copy.distance = distance; 
      return copy; 
    } 

    /** 
    * @param length the length to set 
    */ 
    public void setLength(final int length) { 
      this.length = length; 
    } 

    /** 
    * @return the length 
    */ 
    public int getLength() { 
      return length; 
    } 

    /** 
    * @param distance the distance to set 
    */ 
    public void setDistance(double distance) { 
      this.distance = distance; 
    } 

    /** 
    * @return the distance 
    */ 
    public double getDistance() { 
      return distance; 
    } 

} 

MainActivity của tôi (có 326 dòng mã vì nội địa sử dụng, bạn có thể tìm thấy nó trên trang web của nhà phát triển google, vì vậy chúng tôi chỉ có thể giả sử có hai điểm tĩnh A và B và tôi muốn đi từ A đến B):

public class MainActivity extends FragmentActivity{ 
    private GoogleMap map; 
    private Marker currentLocation; 
    private PolylineOptions pathLine; 
    private LatLng imhere = new LatLng(41.8549038,12.4618208); 
     private LatLng poi = new LatLng(41.89000,12.49324); 


    private LocationManager mLocationManager; 
    private Handler mHandler; 
    private boolean mUseBoth; 
    private Context context; 
    // Keys for maintaining UI states after rotation. 
    private static final String KEY_BOTH = "use_both"; 
    // UI handler codes. 
    private static final int UPDATE_LATLNG = 2; 

    private static final int FIVE_SECONDS = 5000; 
    private static final int THREE_METERS = 3; 
    private static final int TWO_MINUTES = 1000 * 60 * 2; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); 
     Marker colosseoMarker = map.addMarker(new MarkerOptions() 
     .position(colosseo) 
     .title("Start") 
     .snippet("poi") 
     .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher))); 

       Marker current pos = map.addMarker(new MarkerOptions() 
     .position(imhere) 
     .title("i'm here") 
     .snippet("here!") 
     .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher))); 

     context =this ; 
     map.setOnMarkerClickListener(new OnMarkerClickListener() { 

      @Override 
      public boolean onMarkerClick(Marker marker) { 
       final String[] options = {"Calcola il Percorso"}; 
       AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); 
       builder.setTitle("Ottieni Informazioni aggiuntive"); 
       builder.setPositiveButton("Calcola Percorso",new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog,int id) { 
         LatLng start = new LatLng(imhere.latitude,imhere.longitude); 
         LatLng dest = new LatLng(poi.latitude, poi.longitude); 
         Route route = drawPath(start, dest); 

         List<LatLng> list= route.getPoints(); 

if(pathLine!= null) pathline =null;       
pathLine = new PolylineOptions(); 

         pathLine.addAll(list); 
         pathLine.color(Color.rgb(0,191,255)); 

         map.addPolyline(pathLine); 

        } 
        }); 

       AlertDialog alert = builder.create(); 
       alert.show(); 
       Toast.makeText(MainActivity.this, marker.getSnippet(),Toast.LENGTH_SHORT).show(); 
       return true; 
      } 
     }); 


        map.animateCamera(CameraUpdateFactory.newLatLngZoom(imhere, 12)); 
       } 
      } 
     }; 
     // Get a reference to the LocationManager object. 
     mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
    } 


    private Route drawPath(LatLng start, LatLng dest) { 
      Parser parser; 
      String jsonURL = "http://maps.google.com/maps/api/directions/json?"; 
      final StringBuffer sBuf = new StringBuffer(jsonURL); 
      sBuf.append("origin="); 
      sBuf.append(start.latitude); 
      sBuf.append(','); 
      sBuf.append(start.longitude); 
      sBuf.append("&destination="); 
      sBuf.append(dest.latitude); 
      sBuf.append(','); 
      sBuf.append(dest.longitude); 
      sBuf.append("&sensor=true&mode=walking"); 
      parser = new JsonParser(sBuf.toString()); 
      Route r = parser.parse(); 
      return r; 
     } 
} 

mỗi gợi ý cũng được chấp nhận

+0

trong JsonParser tôi đã thay đổi decoded.add (mới LatLng ((lat * 1E6/1E5), (lng * 1E6/1E5))); với decoded.add (new LatLng ((lat/1E5), (lng/1E5))); để có được gấp đôi (tôi nghĩ ...) và nó hoạt động, nhưng đôi khi ứng dụng ngừng hoạt động khi tôi yêu cầu nó để redrow đường dẫn – antedesk

+2

Một vài vấn đề trong 'Hoạt động'. Cuộc gọi JSON sử dụng 'drawPath' phải được thực hiện trong một' AsyncTask'. Trước khi làm việc với 'map', hãy chắc chắn rằng nó đã sẵn sàng để sử dụng, xem mã mẫu trong SDK cho' setUpMapIfNeeded' được khuyên nên chạy trong 'onResume()'. 'map.clear()' để xóa bản đồ trước khi vẽ lại. – qubz

+0

có cảm ơn bạn, tôi sử dụng một 'AsyncTask' và bây giờ nó tốt hơn. Bây giờ tôi đang cố gắng để sử dụng 'setUpMapIfNeeded' và 'map.clear()' – antedesk

Trả lời

-1

Tôi đang làm như sau. Tôi nghĩ rằng điều này sẽ giúp bạn.

Marker interestedMarker; 
    private void plot_direction(){ 
     if (currentSelectedPin !=null) { 
      LatLng origin = new LatLng(currentLocation.getLatitude(),currentLocation.getLongitude()); 
      new GoogleMapDirection(getActivity(), origin, interestedMarker.getPosition(), new DirectionListener() { 
       @Override 
       public void onDirectionPointsReceived(ArrayList<RouteModel> routeList, String distance, String duration) { 
        PolylineOptions lineOptions = null; 
        for (RouteModel route : routeList) { 
         lineOptions = new PolylineOptions(); 
         lineOptions.addAll(route.getSteps()); 
         lineOptions.width(20); 
         lineOptions.color(ContextCompat.getColor(getContext(), R.color.map_route)); 
        } 

        //For removing existing line 
        if (routeMap!=null){ 
         routeMap.remove(); 
        } 
        if(lineOptions != null) { 
         routeMap = mMap.addPolyline(lineOptions); 
        } 
       } 
      }); 
     } 
    } 

lớp GoogleMapDirection như sau

public class GoogleMapDirection { 
    private DirectionListener listener; 
    public GoogleMapDirection(final Activity activity, LatLng source, LatLng destination, DirectionListener listener){ 
     this.listener=listener; 
     String url = null; 
     try { 
      url = "https://maps.googleapis.com/maps/api/directions/json?origin="+ URLEncoder.encode(Double.toString(source.latitude) + "," + Double.toString(source.longitude), "UTF-8") + "&destination=" + URLEncoder.encode(Double.toString(destination.latitude) + "," + Double.toString(destination.longitude), "UTF-8") + "&mode=driving&sensor=false&key=" + Config.GOOGLE_API_BROWSER_KEY; 
      Print.d(url); 
     } catch (UnsupportedEncodingException e) { 
      Print.exception(e); 
     } 

     JSONObject parameters = new JSONObject(); 
     VolleyJsonBodyRequest.execute(activity, url, parameters, new VolleyResponseListener() { 
      @Override 
      public void onResponse(JSONObject response) { 
       try { 
        if (response.getString("status").equals("OK")) { 
         String distance = "NA"; 
         String duration = "NA"; 
         if (response.has("routes")){ 
          JSONArray routesJArray = response.getJSONArray("routes"); 
          if (routesJArray.length()>0){ 
           if (routesJArray.getJSONObject(0).has("legs")){ 
            JSONArray legsJArray = routesJArray.getJSONObject(0).getJSONArray("legs"); 
            if (legsJArray.length()>0){ 
             JSONObject firstLegsJObj = legsJArray.getJSONObject(0); 
             if (firstLegsJObj.has("distance")){ 
              distance = firstLegsJObj.getJSONObject("distance").getString("text"); 
             } 
             if (firstLegsJObj.has("duration")){ 
              duration = firstLegsJObj.getJSONObject("duration").getString("text"); 
             } 


            } 
           } 
          } 
         } 
         GoogleResponseParserTask task = new GoogleResponseParserTask(distance,duration); 
         task.execute(response); 
        } 
       } catch (JSONException e) { 
        Print.exception(e); 
        DialogWindow.showOK(activity, Config.MESSAGE_INVALID_RESPONSE_FORMAT, new DialogListenerOK() { 
         @Override 
         public void onOK() { 

         } 
        }); 
       } 
      } 
      @Override 
      public void onErrorResponse(VolleyResponseError error) { 
       Print.e(error.getDetails()); 
       DialogWindow.showOK(activity, error.getMessage(), new DialogListenerOK() { 
        @Override 
        public void onOK() { 

        } 
       }); 
      } 
     }); 
    } 


    /** 
    * A class to parse the Google Places in JSON format 
    */ 
    private class GoogleResponseParserTask extends AsyncTask<JSONObject, Integer, ArrayList<RouteModel>> { 

     String distance; 
     String duration; 
     private GoogleResponseParserTask(String distance, String duration){ 
      this.distance=distance; 
      this.duration=duration; 

     } 
     @Override 
     protected ArrayList<RouteModel> doInBackground(JSONObject... jsonResponse) { 
      ArrayList<RouteModel> routes = null; 
      try { 
       routes = parse(jsonResponse[0]); 
      } catch (Exception e) { 
       Print.exception(e); 
      } 
      return routes; 
     } 
     @Override 
     protected void onPostExecute(ArrayList<RouteModel> result) { 
      listener.onDirectionPointsReceived(result,distance,duration); 
     } 
    } 


    /** Receives a JSONObject and returns a list of lists containing latitude and longitude */ 
    public ArrayList<RouteModel> parse(JSONObject jObject){ 

     ArrayList<RouteModel> routeList = new ArrayList<>() ; 
     JSONArray jRoutes; 
     JSONArray jLegs; 
     JSONArray jSteps; 

     try { 

      jRoutes = jObject.getJSONArray("routes"); 

      /** Traversing all routes */ 
      for(int i=0;i<jRoutes.length();i++){ 
       jLegs = ((JSONObject)jRoutes.get(i)).getJSONArray("legs"); 
       ArrayList<LatLng> pointList = new ArrayList<>(); 

       /** Traversing all legs */ 
       for(int j=0;j<jLegs.length();j++){ 
        jSteps = ((JSONObject)jLegs.get(j)).getJSONArray("steps"); 
        JSONObject jDistance = ((JSONObject) jLegs.get(j)).getJSONObject("distance"); 
        JSONObject jDuration = ((JSONObject) jLegs.get(j)).getJSONObject("duration"); 

        String distance = jDistance.getString("text"); 
        String duration = jDuration.getString("text"); 

        /** Traversing all steps */ 
        for(int k=0;k<jSteps.length();k++){ 
         String polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points"); 
         ArrayList<LatLng> stepList = decodePoly(polyline); 

         /** Traversing all points */ 
         for(int l=0;l<stepList.size();l++){ 
          LatLng point = new LatLng((stepList.get(l)).latitude, (stepList.get(l)).longitude); 
          pointList.add(point); 
         } 
        } 
        RouteModel routeModel = new RouteModel(); 
        routeModel.setSteps(pointList); 
        routeModel.setDistance(distance); 
        routeModel.setDuration(duration); 
        routeList.add(routeModel); 
       } 
      } 

     } catch (JSONException e) { 
      e.printStackTrace(); 
     }catch (Exception e){ 
     } 


     return routeList; 
    } 


    /** 
    * Method to decode polyline points 
    * Courtesy : http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java 
    * */ 
    private ArrayList<LatLng> decodePoly(String encoded) { 

     ArrayList<LatLng> poly = new ArrayList<>(); 
     int index = 0, len = encoded.length(); 
     int lat = 0, lng = 0; 

     while (index < len) { 
      int b, shift = 0, result = 0; 
      do { 
       b = encoded.charAt(index++) - 63; 
       result |= (b & 0x1f) << shift; 
       shift += 5; 
      } while (b >= 0x20); 
      int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
      lat += dlat; 

      shift = 0; 
      result = 0; 
      do { 
       b = encoded.charAt(index++) - 63; 
       result |= (b & 0x1f) << shift; 
       shift += 5; 
      } while (b >= 0x20); 
      int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 
      lng += dlng; 

      LatLng p = new LatLng((((double) lat/1E5)), 
        (((double) lng/1E5))); 
      poly.add(p); 
     } 

     return poly; 
    } 
Các vấn đề liên quan