【发布时间】:2018-03-31 03:40:29
【问题描述】:
注意:抱歉我的英语不好,因为英语不是我的母语,我为此使用了谷歌翻译。
我正在开发一个 Android 地图应用程序,用户可以在该应用程序中找到他们朋友的当前位置。为了存储当前位置,我使用 Firebase 实时数据库。在 Lalit Singh 之前的帮助下,它现在显示时间和距离,但仍未更新 2 个不同地点之间的折线。我的更新代码如下。
mapsActivity.java(我从火力基地获取朋友位置并更新时间、距离和折线方法)
public void proceed(final View view) { DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Email"); ref.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) { UserInformation details = dataSnapshot1.getValue(UserInformation.class); if (mMap != null) { mMap.clear(); } MarkerOptions markerOptions = new MarkerOptions(); LatLng latLng1 = new LatLng(details.getLatitude(), details.getLongitude()); markerOptions.position(latLng1); markerOptions.title(String.valueOf(latLng1)); mMap.addMarker(markerOptions).setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)); mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng1)); mMap.animateCamera(CameraUpdateFactory.zoomTo(14)); distance_task.getDirectionsUrl(latLng1, markerOptions.getPosition()); distance_task.setLoadListener(new CalculateDistanceTime.taskCompleteListener() { @Override public void taskCompleted(String[] time_distance) { text1.setText(time_distance[0]); //Distance text2.setText(time_distance[1]); //Time } }); String url = getDirectionsUrl(latLng1, markerOptions.getPosition()); DownloadTask downloadTask = new DownloadTask(); downloadTask.execute(url); } } @Override public void onCancelled(DatabaseError databaseError) { } }); }
CalculateDistanceTime.java(添加新类)
class CalculateDistanceTime { private taskCompleteListener mTaskListener; private Context mContext; CalculateDistanceTime(Context context) { mContext = context; } void setLoadListener(taskCompleteListener taskListener) { mTaskListener = taskListener; } void getDirectionsUrl(LatLng origin, LatLng dest) { // Origin of route String str_origin = "origin=" + origin.latitude + "," + origin.longitude; // Destination of route String str_dest = "destination=" + dest.latitude + "," + dest.longitude; // Sensor enabled String sensor = "sensor=false"; // Building the parameters to the web service String parameters = str_origin + "&" + str_dest + "&" + sensor; // Output format String output = "json"; // Building the url to the web service String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters; DownloadTask downloadTask = new DownloadTask(); // Start downloading json data from Google Directions API downloadTask.execute(url); } private String downloadUrl(String strUrl) throws IOException { String data = ""; HttpURLConnection urlConnection; URL url = new URL(strUrl); // Creating an http connection to communicate with url urlConnection = (HttpURLConnection) url.openConnection(); // Connecting to url urlConnection.connect(); // Reading data from url try (InputStream iStream = urlConnection.getInputStream()) { BufferedReader br = new BufferedReader(new InputStreamReader(iStream)); StringBuilder sb = new StringBuilder(); String line; while ((line = br.readLine()) != null) { sb.append(line); } data = sb.toString(); br.close(); } catch (Exception e) { Log.d("Excp. while downloading", e.toString()); } finally { urlConnection.disconnect(); } return data; } interface taskCompleteListener { void taskCompleted(String[] time_distance); } private class DownloadTask extends AsyncTask<String, Void, String> { // Downloading data in non-ui thread @Override protected String doInBackground(String... url) { // For storing data from web service String data = ""; try { // Fetching the data from web service data = downloadUrl(url[0]); } catch (Exception e) { Log.d("Background Task", e.toString()); } return data; } // Executes in UI thread, after the execution of // doInBackground() @Override protected void onPostExecute(String result) { super.onPostExecute(result); ParserTask parserTask = new ParserTask(); // Invokes the thread for parsing the JSON data parserTask.execute(result); } } private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String, String>>> { // Parsing the data in non-ui thread @Override protected List<HashMap<String, String>> doInBackground(String... jsonData) { JSONObject jObject; List<HashMap<String, String>> routes = null; try { jObject = new JSONObject(jsonData[0]); DistanceTimeParser parser = new DistanceTimeParser(); // Starts parsing data routes = parser.parse(jObject); } catch (Exception e) { e.printStackTrace(); } return routes; } // Executes in UI thread, after the parsing process @Override protected void onPostExecute(List<HashMap<String, String>> result) { String duration_distance = ""; if (result.size() < 1) { Log.e("Error : ", "No Points found"); return; } String[] date_dist = new String[2]; // Traversing through all the routes for (int i = 0; i < result.size(); i++) { // Fetching i-th route HashMap<String, String> tmpData = result.get(i); Set<String> key = tmpData.keySet(); Iterator it = key.iterator(); while (it.hasNext()) { String hmKey = (String) it.next(); duration_distance = tmpData.get(hmKey); System.out.println("Key: " + hmKey + " & Data: " + duration_distance); it.remove(); // avoids a ConcurrentModificationException } date_dist[i] = duration_distance; } mTaskListener.taskCompleted(date_dist); } } }
DistanceTimeParser.java(添加新类)
public class DistanceTimeParser { public List<HashMap<String, String>> parse(JSONObject jObject) { List<HashMap<String, String>> routes = new ArrayList<HashMap<String, String>>(); JSONArray jRoutes = null; JSONArray jLegs = null; JSONObject jDistance = null; JSONObject jDuration = null; try { jRoutes = jObject.getJSONArray("routes"); jLegs = ((JSONObject) jRoutes.get(0)).getJSONArray("legs"); List<HashMap<String, String>> path = new ArrayList<HashMap<String, String>>(); /** Getting distance from the json data */ jDistance = ((JSONObject) jLegs.get(0)).getJSONObject("distance"); HashMap<String, String> hmDistance = new HashMap<String, String>(); hmDistance.put("distance", jDistance.getString("text")); /** Getting duration from the json data */ jDuration = ((JSONObject) jLegs.get(0)).getJSONObject("duration"); HashMap<String, String> hmDuration = new HashMap<String, String>(); hmDuration.put("duration", jDuration.getString("text")); routes.add(hmDistance); routes.add(hmDuration); } catch (JSONException e) { e.printStackTrace(); } catch (Exception e) { } return routes; } }
DirectionsJSONParser.java(添加新类)
public class DirectionsJSONParser { List<List<HashMap<String,String>>> parse(JSONObject jObject){ List<List<HashMap<String, String>>> routes = new ArrayList<>() ; JSONArray jRoutes ; JSONArray jLegs ; JSONArray jSteps ; try { jRoutes = jObject.getJSONArray("routes"); for(int i=0;i<jRoutes.length();i++){ jLegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs"); List path = new ArrayList<>(); for(int j=0;j<jLegs.length();j++){ jSteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps"); for(int k=0;k<jSteps.length();k++){ String polyline; polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points"); List<LatLng> list = decodePoly(polyline); for(int l=0;l<list.size();l++){ HashMap<String, String> hm = new HashMap<>(); hm.put("lat", Double.toString((list.get(l)).latitude) ); hm.put("lng", Double.toString((list.get(l)).longitude) ); path.add(hm); } } routes.add(path); } } } catch (JSONException e) { e.printStackTrace(); }catch (Exception ignored){ } return routes; } private List<LatLng> decodePoly(String encoded) { List<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; } }
mapsActivity.java中添加的这4个方法
private String getDirectionsUrl(LatLng origin, LatLng dest) { String str_origin = "origin=" + origin.latitude + "," + origin.longitude; String str_dest = "destination=" + dest.latitude + "," + dest.longitude; String sensor = "sensor=false"; String parameters = str_origin + "&" + str_dest + "&" + sensor; String output = "json"; return "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters; } @SuppressLint("NewApi") public static String downloadUrl(String strUrl) throws IOException { String data = ""; HttpURLConnection urlConnection; URL url = new URL(strUrl); // Creating an http connection to communicate with url urlConnection = (HttpURLConnection) url.openConnection(); // Connecting to url urlConnection.connect(); // Reading data from url try (InputStream iStream = urlConnection.getInputStream()) { BufferedReader br = new BufferedReader(new InputStreamReader(iStream)); StringBuilder sb = new StringBuilder(); String line; while ((line = br.readLine()) != null) { sb.append(line); } data = sb.toString(); br.close(); } catch (Exception e) { Log.d("Exception while down", e.toString()); } finally { urlConnection.disconnect(); } return data; } private class DownloadTask extends AsyncTask<String, Void, String> { // Downloading data in non-ui thread @Override protected String doInBackground(String... url) { // For storing data from web service String data = ""; try { // Fetching the data from web service data = downloadUrl(url[0]); } catch (Exception e) { Log.d("Background Task", e.toString()); } return data; } // Executes in UI thread, after the execution of // doInBackground() @Override protected void onPostExecute(String result) { super.onPostExecute(result); ParserTask parserTask = new ParserTask(); // Invokes the thread for parsing the JSON data parserTask.execute(result); } } private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> { @Override protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) { JSONObject jObject; List<List<HashMap<String, String>>> routes = null; try { jObject = new JSONObject(jsonData[0]); DirectionsJSONParser parser = new DirectionsJSONParser(); // Starts parsing data routes = parser.parse(jObject); } catch (Exception e) { e.printStackTrace(); } return routes; } @Override protected void onPostExecute(List<List<HashMap<String, String>>> result) { ArrayList<LatLng> points = new ArrayList<>(); PolylineOptions lineOptions = new PolylineOptions(); for (int i = 0; i < result.size(); i++) { List<HashMap<String, String>> path = result.get(i); for (int j = 0; j < path.size(); j++) { HashMap<String, String> point = path.get(j); double lat = Double.parseDouble(point.get("lat")); double lng = Double.parseDouble(point.get("lng")); LatLng position = new LatLng(lat, lng); points.add(position); } lineOptions.addAll(points); lineOptions.width(10); lineOptions.color(Color.WHITE); mMap.addPolyline(lineOptions); } } }
mapsActivity.java(我在地图中的当前位置)
@Override public void onLocationChanged(Location location) { Log.d("onLocationChanged", "entered"); mLastLocation = location; DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); Date date = new Date(); mLastUpdateTime = ((dateFormat.format(date).toString())); saveToFirebase(); if (mCurrLocationMarker != null) { mCurrLocationMarker.remove(); } latitude = location.getLatitude(); longitude = location.getLongitude(); LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(latLng); markerOptions.draggable(false); markerOptions.title("Current Position"); markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)); mCurrLocationMarker = mMap.addMarker(markerOptions); //move map camera mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)); mMap.animateCamera(CameraUpdateFactory.zoomTo(11)); Toast.makeText(MapsActivity.this, "Your Current Location", Toast.LENGTH_LONG).show(); //stop location updates if (mGoogleApiClient != null) { LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); Log.d("onLocationChanged", "Removing Location Updates"); } }
Fire Base 方法中保存的数据
public void saveToFirebase() { DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Email").push(); String email = FirebaseAuth.getInstance().getCurrentUser().getEmail(); UserInformation userInformation = new UserInformation(email, mLastLocation.getLatitude(), mLastLocation.getLongitude()); ref.setValue(userInformation); }
【问题讨论】:
-
你的
DataParser.parseDirections方法是错误的,它只考虑了第一个leg的第一个step。可能还有其他问题,但这对我来说是最明显的。 -
@Titus 在此之前,我真的没有在地图上工作,并且在 youtube 上观看了大量教程并创建了这个,但现在我不知道如何实现这一点。
-
@LalitSinghFauzdar 使用单独的类,因为在 mapsActivity.java 中还可以使用其他功能,例如附近的医院、学校等,并在 youtube 教程上观看并创建了单独的类。我认为这是调用不同方法的简单方法。
-
您可以从尝试了解代码的作用开始。
DataParser类似乎用于处理来自 Google Maps Directions API 的响应 JSON。您可以找到该 JSON HERE 的格式您需要做的是从route的所有legs中的所有steps中提取所有坐标,并使用它们创建折线。 -
@Titus 我已经更新了我错过的代码。
标签: java android google-maps android-maps-v2