0

我試圖弄清楚如何顯示從當前位置到四個已知位置的行駛距離。我沒有在屏幕上顯示地圖,我只需要顯示用戶目前距離這些地點有多少英里。我以Here爲例做了一些修改。它正在帶回正確的距離,但我無法弄清楚如何通過每個4個終端位置,或者區分它們。谷歌地圖API v2 - 獲取從當前位置到已知位置的行車距離

我需要做些什麼才能獲得到4個位置的距離,並在不同的TextView中顯示每個距離?

更新問題:如何分別計算每個4個TextView的距離?

有了下面的代碼,我能夠做我想做的第一個TextView的

的Java

public class Locations extends Fragment { 

private Location currentLocation = null; 
private LocationManager locationManager; 
private GeoPoint currentPoint; 

TextView location1; 

ArrayList<LatLng> markerPoints; 
GoogleMap map; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    getLastLocation(); 
} 

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.activity_locations, container, false); 
    ...some other stuff being done here... 
    // Return view 
    return view; 
} 

public void getLastLocation(){ 
    String provider = getBestProvider(); 
    currentLocation = locationManager.getLastKnownLocation(provider); 

    this.markerPoints = new ArrayList<LatLng>(); 

    LatLng fromPosition = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()); 
    LatLng toPosition = new LatLng(29.633289, -82.305838); 
    // These are the other 3 end locations 
    LatLng toPosition1 = new LatLng(35.205374, -82.614587); 
    LatLng toPosition2 = new LatLng(35.405342, -82.316587); 
    LatLng toPosition3 = new LatLng(35.702354, -82.515837); 

    Locations.this.markerPoints.add(fromPosition); 
    Locations.this.markerPoints.add(toPosition); 

    // Getting URL to the Google Directions API 
    String url = Locations.this.getDirectionsUrl(fromPosition, toPosition); 

    DownloadTask downloadTask = new DownloadTask(); 

    // Start downloading json data from Google Directions API 
    downloadTask.execute(url); 

    if(currentLocation != null) { 
     setCurrentLocation(currentLocation); 
    } else { 
     // do something 
    } 
} 

public String getBestProvider() { 
    locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE); 
    Criteria criteria = new Criteria(); 
    criteria.setPowerRequirement(Criteria.NO_REQUIREMENT); 
    criteria.setAccuracy(Criteria.NO_REQUIREMENT); 
    String bestProvider = locationManager.getBestProvider(criteria, true); 
    return bestProvider; 
} 

public void setCurrentLocation(Location location){ 
    // Get current location 
    int currLatitude = (int) (location.getLatitude()*1E6); 
    int currLongitude = (int) (location.getLongitude()*1E6); 
    currentPoint = new GeoPoint(currLatitude,currLongitude); 
    // Set current location 
    currentLocation = new Location(""); 
    currentLocation.setLatitude(currentPoint.getLatitudeE6()/1e6); 
    currentLocation.setLongitude(currentPoint.getLongitudeE6()/1e6); 
} 

private String 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; 

    return url; 
} 

/** A method to download json data from url */ 
private String downloadUrl(String strUrl) throws IOException { 
    String data = ""; 
    InputStream iStream = null; 
    HttpURLConnection urlConnection = null; 
    try 
    { 
     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 
     iStream = urlConnection.getInputStream(); 
     BufferedReader br = new BufferedReader(new InputStreamReader(iStream)); 
     StringBuffer sb = new StringBuffer(); 
     String line = ""; 
     while ((line = br.readLine()) != null) { 
      sb.append(line); 
     } 

     data = sb.toString(); 
     br.close(); 
    } catch (Exception e) { 
     Log.d("Exception while downloading url", e.toString()); 
    } finally { 
     iStream.close(); 
     urlConnection.disconnect(); 
    } 
    return data; 
} 

// Fetches data from url passed 
private class DownloadTask extends AsyncTask<String, Void, ArrayList<String>> { 
    @Override 
    protected ArrayList<String> doInBackground(String... urlList) { 
     try { 
      ArrayList<String> returnList = new ArrayList<String>(); 
      for (String url : urlList) { 
       // Fetching the data from web service 
       String data = Locations.this.downloadUrl(url); 
       returnList.add(data); 
      } 
      return returnList; 
     } catch (Exception e) { 
      Log.d("Background Task", e.toString()); 
      return null; // Failed, return null 
     } 
    } 

    // Executes in UI thread, after the execution of 
    // doInBackground() 
    @Override 
    protected void onPostExecute(ArrayList<String> results) { 
     super.onPostExecute(results); 

     ParserTask parserTask = new ParserTask(); 

     for (String url : results) { 
      parserTask.execute(url); 
     } 

     // Invokes the thread for parsing the JSON data 
     // parserTask.execute(results); 
    } 
} 

/** A class to parse the Google Places in JSON format */ 
private class ParserTask extends AsyncTask<String, Integer, ArrayList<List<HashMap<String, String>>>> { 
    // Parsing the data in non-ui thread 
    @Override 
    protected ArrayList<List<HashMap<String, String>>> doInBackground(String... jsonData) { 
     try { 
      ArrayList<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String, String>>>(); 

      // for (String url : jsonData) { 
      for (int i = 0; i < jsonData.length; i++) { 
       JSONObject jObject = new JSONObject(jsonData[i]); 

       DirectionsJSONParser parser = new DirectionsJSONParser(); 
       // Starts parsing data 
       routes = (ArrayList<List<HashMap<String, String>>>) parser.parse(jObject); 
      } 
      return routes; 
     } catch (Exception e) { 
      Log.d("Background task", e.toString()); 
      return null; // Failed, return null 
     } 
    } 

    // Executes in UI thread, after the parsing process 
    @Override 
    protected void onPostExecute(ArrayList<List<HashMap<String, String>>> result) { 
     if (result.size() < 1) { 
      Toast.makeText(getActivity(), "No Points", Toast.LENGTH_LONG).show(); 
      return; 
     } 

     TextView tv1 = (TextView) getActivity().findViewById(R.id.location1); 
     TextView tv2 = (TextView) getActivity().findViewById(R.id.location2); 
     TextView tv3 = (TextView) getActivity().findViewById(R.id.location3); 
     TextView tv4 = (TextView) getActivity().findViewById(R.id.location4); 

     TextView[] views = { tv1, tv2, tv3, tv4 }; 

     // Traversing through all the routes 
     for (int i = 0; i < result.size(); i++) { 
      // Fetching i-th route 
      List<HashMap<String, String>> path = result.get(i); 
      String distance = "No distance"; 

      // Fetching all the points in i-th route 
      for (int j = 0; j < path.size(); j++) { 
       HashMap<String, String> point = path.get(j); 

       if (j == 0) { 
        distance = point.get("distance"); 
        continue; 
       } 
      } 

      Log.d("Distance: ", distance); 

      // Set text 
      views[i].setText(distance); 
     } 
    } 
} 

XML

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" > 

<LinearLayout 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:orientation="vertical" > 
    <TextView 
     android:id="@+id/location1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 
    <TextView 
     android:id="@+id/location2" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_marginTop="5dp" 
     android:text="TextView" /> 
    <TextView 
     android:id="@+id/location3" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_marginTop="5dp" 
     android:text="TextView" /> 
    <TextView 
     android:id="@+id/location4" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_marginTop="5dp" 
     android:text="TextView" /> 
</LinearLayout> 
</RelativeLayout> 

任何搞清楚了這幫助出來和/或建議,以更好的代碼將非常感激d。

+0

您是否嘗試過單獨計算所有4條路徑,或者使用不同於'R.id.location1'的'TextView'? – crocboy

+0

我已經嘗試過每個人,例如,傳遞「toPosition1」並設置TextView在同一地點(非常最後一行在java文件中)和R.id.location2,它返回正確的距離,但我一次只能得到一個是正確的。如果我同時通過它們,它將爲每個4個TextView設置「距離」。 (希望是有道理的......) – Brian

+1

所以你需要做的是創建一個'TextView'數組,並在最後你得到你通過該數組循環的距離,所以每個距離設置爲不同的'TextView' – crocboy

回答

2

這是你的現有代碼的更新:

// Executes in UI thread, after the parsing process 
@Override 
protected void onPostExecute(List<List<HashMap<String, String>>> result) 
{ 
    if (result.size() < 1) 
    { 
     Toast.makeText(getActivity(), "No Points", Toast.LENGTH_SHORT).show(); 
     return; 
    } 

    TextView tv1 = (TextView) getActivity().findViewById(R.id.location1); 
    TextView tv2 = (TextView) getActivity().findViewById(R.id.location2); 
    TextView tv3 = (TextView) getActivity().findViewById(R.id.location3); 
    TextView tv4 = (TextView) getActivity().findViewById(R.id.location4); 

    TextView[] views = {tv1, tv2, tv3, tv4}; 


    // Traversing through all the routes 
    for (int i = 0; i < result.size(); i++) 
    { 
     // Fetching i-th route 
     List<HashMap<String, String>> path = result.get(i); 
     String distance = "No distance"; 

     // Fetching all the points in i-th route 
     for (int j = 0; j < path.size(); j++) 
     { 
      HashMap<String, String> point = path.get(j); 

      if (j == 0) 
      { 
       distance = point.get("distance"); 
       continue; 
      } 
     } 

     // Set text 
     views[i].setText(distance); 
    } 
} 

該代碼使得不那麼好的假設:它假設的result尺寸大小爲views,而你的情況應該是相同的4.當您運行此代碼時,如果您有超過4個結果(不應發生這種情況),則可能會收到IndexOutOfBounds錯誤。最終,您需要驗證result的大小是4還是TextView的數量。如果您有任何疑問或本不工作的權利,只是讓我知道:)

編輯:要獲得所有距離一下子,你可以修改你DownloadTask採取在多個網址。

更改類的定義:

private class DownloadTask extends AsyncTask<String, Void, ArrayList<String>> 

這表示您的後臺操作將返回String的列表。

修改doInBackground(),現在可以處理多個網址:

// Downloading data in non-ui thread 
@Override 
protected ArrayList<String> doInBackground(String... urlList) 
{ 
    try 
    { 
     ArrayList<String> returnList = new ArrayList<String>(); 
     for(String url : urlList) 
     { 
      // Fetching the data from web service 
      String data = Locations.this.downloadUrl(url); 
      returnList.add(data); 
     } 

     return returnList; 
    } 
    catch (Exception e) 
    { 
     Log.d("Background Task", e.toString()); 
     return null; // Failed, return null 
    } 
} 

然後你onPostExecute()成爲

// Executes in UI thread, after the execution of 
// doInBackground() 
@Override 
protected void onPostExecute(ArrayList<String> results) 
{ 
    super.onPostExecute(results); 

    ParserTask parserTask = new ParserTask(); 

    // Invokes the thread for parsing the JSON data 
    parserTask.execute(results); 

} 

現在,你將不得不修改ParserTask代碼採取JSON字符串列表,而不僅僅是一個JSON字符串。只需更改您的ParserTask輸入參數,並將for循環中的所有內容循環遍歷每個JSON字符串。您還必須修改onPostExecute()的參數,以獲取List的任何內容,這樣它就不會處理一個結果,而是處理一個結果列表。我可以在這裏你不能顯示這些修改,因爲這將是太長時間,然後就沒有挑戰你:)

編輯兩個:getLastLocation()你只調用DownloadTask使用同一個URL,但你應該把四個URL這樣的downloadTask.execute(url1, url2, url3, url4)。另外,因爲ParserTask仍然只處理一個JSON字符串,所以應該取出四個TextView和數組循環出onPostExecute()。要告訴ParserTask要填充哪個TextView,請向ParserTask添加一個構造函數,該函數將TextView作爲參數。然後在構造函數中分配的ParserTask中創建一個實例變量,並在onPostExecute()中使用該實例變量顯示距離。

然後,拿這個TextView陣列的東西我給你之前,並把它在 DownloadTask。循環查看字符串結果時,還會循環訪問TextView數組,並傳入ParserTask構造函數中的TextView

基本上,你在ParserTask中添加一個構造函數來告訴它在哪個TextView上繪製。當您的DownloadTask完成後,您將該URL傳遞給合適的TextView。例如,R.id.location3爲第三個網址。

+0

這樣可以,但是我怎樣才能在LatLng中傳遞其他3個末端位置(全部同時) ? – Brian

+0

如果我添加另一個「String url1 = Locations.this.getDirectiosnUrl(fromPosition,toPosition1);」並嘗試執行「url」和「url1」,LogCat顯示非法狀態異常。無法執行任務:任務已在運行。我似乎無法弄清楚如何在同一時間到達所有4個終點的距離。 – Brian

+0

查看我的編輯 – crocboy

0
public static double distFrom(double lat1, double lng1, double lat2, double lng2) { 
double earthRadius = 3958.75; 
double dLat = Math.toRadians(lat2-lat1); 
double dLng = Math.toRadians(lng2-lng1); 
double sindLat = Math.sin(dLat/2); 
double sindLng = Math.sin(dLng/2); 
double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2) 
     * Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)); 
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
double dist = earthRadius * c; 

return dist; 
} 

該方法將計算從一個位置到另一個位置的距離,精確度取決於lat,lng的頻率。拉特更多,拉特更準確。 請記住,距離和位移有所不同。

+0

以下發布了我的答案這不會給我「飛越」的距離,而不是實際的駕駛距離嗎? – Brian

+0

這取決於如果你是直走,那麼它可以給幾乎準確的,你可以使用更多經緯度得到準確的結果...這就是爲什麼我寫的距離和位移.. – Sandeep

+0

這是我最初使用的公式,但作爲到最終位置的距離增加,實際駕駛距離相差太多,我試圖完成。當我回應時,我沒有考慮到你提到這種差異的道歉。 – Brian

相關問題