Google Map o cualquier otra aplicación similar tiene métodos para generar una ruta entre dos ubicaciones. En general, hay muchos parámetros como la distancia más cercana, la distancia más rápida, rutas alternativas, etc. para satisfacer las necesidades. Estas aplicaciones son realmente atractivas, pero el desarrollador conoce el dolor detrás del desarrollo de aplicaciones tan hermosas.
XML
<!--Give it an ID as we will call this in the Main code--> <fragment android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/map" tools:context=".MapsActivity" android:name="com.google.android.gms.maps.SupportMapFragment"/>
Kotlin
if (!Places.isInitialized()) { Places.initialize(applicationContext, apiKey) }
Kotlin
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this)
Kotlin
// GeeksforGeeks coordinates private var originLatitude: Double = 28.5021359 private var originLongitude: Double = 77.4054901 // Coordinates of a park nearby private var destinationLatitude: Double = 28.5151087 private var destinationLongitude: Double = 77.3932163
Kotlin
private lateinit var mMap: GoogleMap
Kotlin
override fun onMapReady(p0: GoogleMap?) { mMap = p0!! val originLocation = LatLng(originLatitude, originLongitude) mMap.clear() mMap.addMarker(MarkerOptions().position(originLocation)) mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(originLocation, 18F)) }
Kotlin
private fun getDirectionURL(origin:LatLng, dest:LatLng, secret: String) : String{ return "https://maps.googleapis.com/maps/api/directions/json?origin=${origin.latitude},${origin.longitude}" + "&destination=${dest.latitude},${dest.longitude}" + "&sensor=false" + "&mode=driving" + "&key=$secret" }
Kotlin
fun decodePolyline(encoded: String): List<LatLng> { val poly = ArrayList<LatLng>() var index = 0 val len = encoded.length var lat = 0 var lng = 0 while (index < len) { var b: Int var shift = 0 var result = 0 do { b = encoded[index++].code - 63 result = result or (b and 0x1f shl shift) shift += 5 } while (b >= 0x20) val dlat = if (result and 1 != 0) (result shr 1).inv() else result shr 1 lat += dlat shift = 0 result = 0 do { b = encoded[index++].code - 63 result = result or (b and 0x1f shl shift) shift += 5 } while (b >= 0x20) val dlng = if (result and 1 != 0) (result shr 1).inv() else result shr 1 lng += dlng val latLng = LatLng((lat.toDouble() / 1E5),(lng.toDouble() / 1E5)) poly.add(latLng) } return poly }
Kotlin
class MapData { var routes = ArrayList<Routes>() } class Routes { var legs = ArrayList<Legs>() } class Legs { var distance = Distance() var duration = Duration() var end_address = "" var start_address = "" var end_location =Location() var start_location = Location() var steps = ArrayList<Steps>() } class Steps { var distance = Distance() var duration = Duration() var end_address = "" var start_address = "" var end_location =Location() var start_location = Location() var polyline = PolyLine() var travel_mode = "" var maneuver = "" } class Duration { var text = "" var value = 0 } class Distance { var text = "" var value = 0 } class PolyLine { var points = "" } class Location{ var lat ="" var lng ="" }
Kotlin
@SuppressLint("StaticFieldLeak") private inner class GetDirection(val url : String) : AsyncTask<Void, Void, List<List<LatLng>>>(){ override fun doInBackground(vararg params: Void?): List<List<LatLng>> { val client = OkHttpClient() val request = Request.Builder().url(url).build() val response = client.newCall(request).execute() val data = response.body!!.string() val result = ArrayList<List<LatLng>>() try{ val respObj = Gson().fromJson(data,MapData::class.java) val path = ArrayList<LatLng>() for (i in 0 until respObj.routes[0].legs[0].steps.size){ path.addAll(decodePolyline(respObj.routes[0].legs[0].steps[i].polyline.points)) } result.add(path) }catch (e:Exception){ e.printStackTrace() } return result } override fun onPostExecute(result: List<List<LatLng>>) { val lineoption = PolylineOptions() for (i in result.indices){ lineoption.addAll(result[i]) lineoption.width(10f) lineoption.color(Color.GREEN) lineoption.geodesic(true) } mMap.addPolyline(lineoption) } }
Kotlin
// MainActivity.kt import android.annotation.SuppressLint import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.graphics.Color import android.os.AsyncTask import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.MarkerOptions import com.google.android.gms.maps.model.PolylineOptions import com.google.android.libraries.places.api.Places import com.google.gson.Gson import okhttp3.OkHttpClient import okhttp3.Request class MainActivity : AppCompatActivity(), OnMapReadyCallback { private lateinit var mMap: GoogleMap private var originLatitude: Double = 28.5021359 private var originLongitude: Double = 77.4054901 private var destinationLatitude: Double = 28.5151087 private var destinationLongitude: Double = 77.3932163 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Fetching API_KEY which we wrapped val ai: ApplicationInfo = applicationContext.packageManager .getApplicationInfo(applicationContext.packageName, PackageManager.GET_META_DATA) val value = ai.metaData["com.google.android.geo.API_KEY"] val apiKey = value.toString() // Initializing the Places API with the help of our API_KEY if (!Places.isInitialized()) { Places.initialize(applicationContext, apiKey) } // Map Fragment val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) val gd = findViewById<Button>(R.id.directions) gd.setOnClickListener{ mapFragment.getMapAsync { mMap = it val originLocation = LatLng(originLatitude, originLongitude) mMap.addMarker(MarkerOptions().position(originLocation)) val destinationLocation = LatLng(destinationLatitude, destinationLongitude) mMap.addMarker(MarkerOptions().position(destinationLocation)) val urll = getDirectionURL(originLocation, destinationLocation, apiKey) GetDirection(urll).execute() mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(originLocation, 14F)) } } } override fun onMapReady(p0: GoogleMap?) { mMap = p0!! val originLocation = LatLng(originLatitude, originLongitude) mMap.clear() mMap.addMarker(MarkerOptions().position(originLocation)) mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(originLocation, 18F)) } private fun getDirectionURL(origin:LatLng, dest:LatLng, secret: String) : String{ return "https://maps.googleapis.com/maps/api/directions/json?origin=${origin.latitude},${origin.longitude}" + "&destination=${dest.latitude},${dest.longitude}" + "&sensor=false" + "&mode=driving" + "&key=$secret" } @SuppressLint("StaticFieldLeak") private inner class GetDirection(val url : String) : AsyncTask<Void, Void, List<List<LatLng>>>(){ override fun doInBackground(vararg params: Void?): List<List<LatLng>> { val client = OkHttpClient() val request = Request.Builder().url(url).build() val response = client.newCall(request).execute() val data = response.body!!.string() val result = ArrayList<List<LatLng>>() try{ val respObj = Gson().fromJson(data,MapData::class.java) val path = ArrayList<LatLng>() for (i in 0 until respObj.routes[0].legs[0].steps.size){ path.addAll(decodePolyline(respObj.routes[0].legs[0].steps[i].polyline.points)) } result.add(path) }catch (e:Exception){ e.printStackTrace() } return result } override fun onPostExecute(result: List<List<LatLng>>) { val lineoption = PolylineOptions() for (i in result.indices){ lineoption.addAll(result[i]) lineoption.width(10f) lineoption.color(Color.GREEN) lineoption.geodesic(true) } mMap.addPolyline(lineoption) } } fun decodePolyline(encoded: String): List<LatLng> { val poly = ArrayList<LatLng>() var index = 0 val len = encoded.length var lat = 0 var lng = 0 while (index < len) { var b: Int var shift = 0 var result = 0 do { b = encoded[index++].code - 63 result = result or (b and 0x1f shl shift) shift += 5 } while (b >= 0x20) val dlat = if (result and 1 != 0) (result shr 1).inv() else result shr 1 lat += dlat shift = 0 result = 0 do { b = encoded[index++].code - 63 result = result or (b and 0x1f shl shift) shift += 5 } while (b >= 0x20) val dlng = if (result and 1 != 0) (result shr 1).inv() else result shr 1 lng += dlng val latLng = LatLng((lat.toDouble() / 1E5),(lng.toDouble() / 1E5)) poly.add(latLng) } return poly } }
Kotlin
// MapData.kt class MapData { var routes = ArrayList<Routes>() } class Routes { var legs = ArrayList<Legs>() } class Legs { var distance = Distance() var duration = Duration() var end_address = "" var start_address = "" var end_location =Location() var start_location = Location() var steps = ArrayList<Steps>() } class Steps { var distance = Distance() var duration = Duration() var end_address = "" var start_address = "" var end_location =Location() var start_location = Location() var polyline = PolyLine() var travel_mode = "" var maneuver = "" } class Duration { var text = "" var value = 0 } class Distance { var text = "" var value = 0 } class PolyLine { var points = "" } class Location{ var lat ="" var lng ="" }
XML
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <fragment android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/map" tools:context=".MapsActivity" android:name="com.google.android.gms.maps.SupportMapFragment"/> <Button android:id="@+id/directions" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true" android:text = "Click" tools:ignore="MissingConstraints" /> </RelativeLayout>
Publicación traducida automáticamente
Artículo escrito por aashaypawar y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA