paint-brush
Jetpack Compose ile Mobil Haritaları Dönüştürme: Geliştiriciler için Google I/O'dan Analizlerile@darrylbayliss
Yeni tarih

Jetpack Compose ile Mobil Haritaları Dönüştürme: Geliştiriciler için Google I/O'dan Analizler

ile Darryl Bayliss22m2024/07/09
Read on Terminal Reader

Çok uzun; Okumak

Jetpack Compose for Maps, modern Android gelişimini dönüştürerek mobil haritalamayı daha kolay ve daha verimli hale getirdi. Google Haritalar'ı Jetpack Compose projelerinize nasıl entegre edeceğinize ilişkin Google I/O Extended 2023'teki temel teknikleri ve ipuçlarını keşfedin.
featured image - Jetpack Compose ile Mobil Haritaları Dönüştürme: Geliştiriciler için Google I/O'dan Analizler
Darryl Bayliss HackerNoon profile picture
0-item



Bu yayın, Temmuz 2023'te Londra'da Google Developers Group için Google I/O Extended'da yapılan bir konuşmaya dayanmaktadır. Konuşmanın slaytlarına buradan ulaşabilirsiniz.

Haritalar için Jetpack Oluşturma

Jetpack Compose 1.0'ın Temmuz 2021'de yayınlandığını hayal etmek zor. İki yıl ileri sardığımızda Google Play'deki en iyi 1000 uygulamanın %24'ünün Compose'u benimsemesinin nedenini anlamak kolaydır.



Bütün bu heyecanın arasında, Modern Android Geliştirme'nin çok az ilgi gördüğünü düşündüğüm bir köşesi de Google Haritalar'dır. SDK'yı kullanmayalı uzun zaman oldu, bu nedenle Google Haritalar'ın çağa ayak uydurduğunu ve kendi Compose kitaplığını yayınladığını görmek beni çok şaşırttı.


Bu, haritalama alanında çalışan şirketler ve mühendisler için hoş bir haber olacak. Mobil haritalama, 35,5 milyar dolarlık bir endüstridir ve %19,83'lük Bileşik Yıllık Büyüme Oranı (CAGR) ile 2028 yılına kadar 87,7 milyar dolara çıkacağı tahmin edilmektedir. Kaynak


Büyüyen Piyasalar Grafiği


Bu neden önemli? Daha büyük bir pazar, şirketlerin mobil haritalama uygulamalarından gelir elde etmesi için daha fazla fırsat anlamına gelir. Bunlar olağan kullanım durumları, yiyecek, market alışverişi teslimatı ve araç çağırma hizmetlerinden oluşur. Ancak derinlere inerseniz, hemen belli olmayan uygulamalar vardır.


Kısa bir araştırma sonucu bulabildiğim örnekleri aşağıda bulabilirsiniz:


Büyüyen Pazar Alanları Mobil haritalar Akıllı Şehirler için harikadır; bir şehrin kalp atışını yönetmeye yardımcı olur ve verileri, zorlukları daha iyi anlayıp bunlara tepki verecek şekilde görselleştirir. Şehir planlamacıları, acil müdahale kuruluşları veya sıradan sakinler için kullanışlıdır.


Kaynak yönetimi aynı zamanda haritalama çözümlerinden de yararlanır. Tarımdan balıkçılığa, madencilikten ormancılığa kadar uzanan haritalar, bu iş kolunda çalışan kişilere malzemeleri sürdürülebilir bir şekilde hasat etmek için doğru kararları verme perspektifini sağlar.


Ulaşım büyük ölçüde haritalama teknolojisine dayanmaktadır. Yalnızca Google Haritalar veya Uber gibi tüketici uygulamaları değil, aynı zamanda bir işletmenin araç filosunun nerede bulunduğunu anlamak gibi işletme düzeyindeki işlevler de vardır. Ulaştırma kurumları ayrıca trafiği yönetmek ve akışı kolaylaştırmak için trafiğin nereye yönlendirileceği konusunda karar verilmesine yardımcı olmak için haritaları kullanır.


Son olarak, iklim değişikliği ve havanın giderek daha öngörülemez hale gelmesiyle birlikte haritalar, meteoroloji kurumlarının, acil müdahale birimlerinin ve yaban hayatı koruma uzmanlarının dünyamızın nasıl değiştiğini ve bunu azaltmak için olumlu adımlar atmak için neler yapabileceğimizi anlamalarına olanak tanıyor.

Kaynaklar:Mordor Intelligence , GMInsights , Allied Market Research , EMR Research , Google Earth Sosyal Yardımı , Research & Markets


Dünya giderek daha fazla veri sağlarken, bu verileri bir haritaya nasıl yerleştireceğinizi öğrenmenin tam zamanı. Bunu yapalım ve koda geri dönelim.


Compose için Google Haritalar'ı kullanma

Compose için Google Haritalar aşağıdaki bağımlılıklara dayanır:

 dependencies { implementation "com.google.maps.android:maps-compose:2.11.4" implementation "com.google.android.gms:play-services-maps:18.1.0" // Optional Util Library implementation "com.google.maps.android:maps-compose-utils:2.11.4" implementation 'com.google.maps.android:maps-compose-widgets:2.11.4' // Optional Accompanist permissions to request permissions in compose implementation "com.google.accompanist:accompanist-permissions:0.31.5-beta" }


Compose için Google Haritalar, Google Haritalar SDK'sının üzerine inşa edilmiştir; dolayısıyla Compose kitaplığını ve Haritalar SDK'sını içe aktarmanız gerekir. Oluşturma kitaplığı bunların çoğunu Oluşturulabilir Öğeler'de kapsadığından, Google Haritalar SDK'sındaki çoğu nesneyi kullanmanıza gerek kalmayacaktır.


Yardımcı programlar ve widget kitaplıkları isteğe bağlı bir bağımlılıktır. Utils kitaplığı, işaretleyicileri haritalarda kümeleme yeteneği sağlarken widget'lar ek kullanıcı arayüzü bileşenleri sağlar. Daha sonra bunların kullanıldığını göreceksiniz.


Bu gönderiye, haritalarda sıklıkla kullanılan bir izin olan konum izinlerinin nasıl talep edileceğini göstermek için Accompanist'in istek izinleri kitaplığını ekledim. Accompanist, Google'ın henüz Jetpack Compose'un parçası olmayan özellikleri deneyip geri bildirim toplamasına yönelik deneysel bir kitaplıktır.


Son olarak Google Geliştirici Konsolu'na gitmeniz, bir Google Haritalar SDK API anahtarına kaydolmanız ve bunu projenize eklemeniz gerekir. Bunun nasıl yapılacağına ilişkin Google Haritalar Geliştirici Dokümanları'nda bir kılavuz bulunmaktadır.


Güvenlik İpucu: Google Developer Console'da API anahtarınızı kilitleyerek yalnızca uygulamanızla çalışmasını sağlayın. Bu, yetkisiz kullanımın önlenmesini sağlar.


Harita Gösterme

Bir haritayı göstermek aşağıdaki kadar basittir:


 setContent { val hydePark = LatLng(51.508610, -0.163611) val cameraPositionState = rememberCameraPositionState { position = CameraPosition.fromLatLngZoom(hydePark, 10f) } GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState) { Marker( state = MarkerState(position = hydePark), title = "Hyde Park", snippet = "Marker in Hyde Park" ) } }


Bir alanın konumunu içeren bir LatLng nesnesi oluşturun ve kameranın başlangıç konumunu ayarlamak için bunu rememberCameraPositionState ile birlikte kullanın. Bu yöntem, ellerinizi kullanarak veya programlı olarak hareket ettiğinizde haritanın konumunu hatırlar . Bu yöntem olmadan Compose, her durum değişikliğinde haritayı başlangıç konumuna yeniden hesaplar.


Ardından, bir GoogleMap oluşturun ve seçtiğiniz bir değiştiriciyi ve kamera durumunu iletin. GoogleMap ayrıca ek şekillendirilebilir öğeler aktarmak için bir Slot API'si de sağlar; bu şekillendirilebilir öğeler, harita üzerinde çizmek istediğiniz şeylerdir.


Bir Marker oluşturulabilir ekleyin, ardından içindeki işaretçinin konumunu içeren bir MarkerState ekleyin. Son olarak işaretçinin başlığını ve açıklamasını ekleyin.


Bunu çalıştırmak, Hyde Park'ta bir işaretleyiciyle Batı Londra'nın güzel bir havadan görüntüsünü verir.


Hyde Park'taki İşaretçi

İşaretleyici Penceresini Özelleştirme

MarkerInfoWindowContent Composable'ı kullanarak işaretçinin penceresini özelleştirebilirsiniz. Bunun aynı zamanda slot tabanlı bir API'si vardır; bu, özel kullanıcı arayüzünüzü pencerede oluşturmak için oluşturulabilir öğelerinizi aktarabileceğiniz anlamına gelir.


 setContent { val hydePark = LatLng(51.508610, -0.163611) val cameraPositionState = rememberCameraPositionState { position = CameraPosition.fromLatLngZoom(hydePark, 10f) } GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState) { MarkerInfoWindowContent( state = MarkerState(position = hydePark), title = "Hyde Park", snippet = "Marker in Hyde Park" ) { marker -> Column(horizontalAlignment = Alignment.CenterHorizontally) { Text( modifier = Modifier.padding(top = 6.dp), text = marker.title ?: "", fontWeight = FontWeight.Bold ) Text("Hyde Park is a Grade I-listed parked in Westminster") Image( modifier = Modifier .padding(top = 6.dp) .border( BorderStroke(3.dp, color = Color.Gray), shape = RectangleShape ), painter = painterResource(id = R.drawable.hyde_park), contentDescription = "A picture of hyde park" ) } } } }


Bunu çalıştırmak, üzerine dokunduğunuzda işaretçinin üzerindeki özel pencereyi gösterir.


Hyde Park'ta Özel Pencere İşaretleyicisi

Birden fazla işaretçi gösteriliyor

Birden fazla işaretçiyi göstermek, ihtiyacınız olduğu kadarını eklemek kadar basittir. Batı Londra'daki birkaç farklı park için işaretçiler ekleyelim.


 setContent { val hydePark = LatLng(51.508610, -0.163611) val regentsPark = LatLng(51.531143, -0.159893) val primroseHill = LatLng(51.539556, -0.16076088) val cameraPositionState = rememberCameraPositionState { position = CameraPosition.fromLatLngZoom(hydePark, 10f) } GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState) { // Marker 1 Marker( state = MarkerState(position = hydePark), title = "Hyde Park", snippet = "Marker in Hyde Park" ) // Marker 2 Marker( state = MarkerState(position = regentsPark), title = "Regents Park", snippet = "Marker in Regents Park" ) // Marker 3 Marker( state = MarkerState(position = primroseHill), title = "Primrose Hill", snippet = "Marker in Primrose Hill" ) } }


Kodu çalıştırın ve işaretçilerinizin haritada göründüğünü göreceksiniz.


Çoklu Park İşaretleri


Kümeleme İşaretleyicileri

Bir harita kısa sürede meşgul olabilir. 300 işaretçi göstermeye çalışıyorsanız kullanıcının neler olduğunu anlaması görsel olarak zor olacaktır. Google Haritalar ve cihazınız da size teşekkür etmeyecektir çünkü her bir işaretçiyi oluşturmak zorunda kalacak, bu da performansı ve pil ömrünü etkileyecektir.


Bunun çözümü, birbirine yakın işaretleyicileri tek bir işaretleyicide gruplandıran bir teknik olan Kümeleme'dir . Bu Kümeleme yakınlaştırma düzeyinde gerçekleşir. Haritayı uzaklaştırdıkça işaretçiler bir küme halinde gruplanacak, yakınlaştırdıkça küme ayrı işaretçilere bölünecektir.


Compose için Google Haritalar, bunu bir Clustering oluşturulabilir aracılığıyla kullanıma hazır bir şekilde sağlar. Kümelemenin gerçekleşmesi için karmaşık sıralama veya filtreleme yazmaya gerek yoktur.


 setContent { val hydePark = LatLng(51.508610, -0.163611) val regentsPark = LatLng(51.531143, -0.159893) val primroseHill = LatLng(51.539556, -0.16076088) val crystalPalacePark = LatLng(51.42153, -0.05749) val greenwichPark = LatLng(51.476688, 0.000130) val lloydPark = LatLng(51.364188, -0.080703) val cameraPositionState = rememberCameraPositionState { position = CameraPosition.fromLatLngZoom(hydePark, 10f) } GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState) { val parkMarkers = remember { mutableStateListOf( ParkItem(hydepark, "Hyde Park", "Marker in hyde Park"), ParkItem(regentspark, "Regents Park", "Marker in Regents Park"), ParkItem(primroseHill, "Primrose Hill", "Marker in Primrose Hill"), ParkItem(crystalPalacePark, "Crystal Palace", "Marker in Crystal Palace"), ParkItem(greenwichPark, "Greenwich Park", "Marker in Greenwich Park"), ParkItem(lloydPark, "Lloyd park", "Marker in Lloyd Park"), ) } Clustering(items = parkMarkers, onClusterClick = { // Handle when the cluster is tapped }, onClusterItemClick = { marker -> // Handle when a marker in the cluster is tapped }) } } data class ParkItem( val itemPosition: LatLng, val itemTitle: String, val itemSnippet: String) : ClusterItem { override fun getPosition(): LatLng = itemPosition override fun getTitle(): String = itemTitle override fun getSnippet(): String = itemSnippet }


ParkItem veri sınıfının eklendiğine dikkat edin. Buna ihtiyacımız var çünkü bir Clustering oluşturulabilirine aktarılan öğelerin ClusterItem arayüzüne uyması gerekiyor. Arayüz, Kümeye her işaretçi için konumu, başlığı ve parçacığı sağlar.

Yakınlaştırın ve uzaklaştırın; kümelemeyi çalışırken göreceksiniz.


Konum İzni Alma

Haritalar ve kullanıcı konumu genellikle el ele gider, bu nedenle bazı haritalama uygulamalarının kullanıcının konumu için izin istemesi mantıklıdır.

Bunu yaparsanız kullanıcının iznine saygı gösterin ; konum izni, bir kullanıcıdan alınabilecek en hassas izinlerden biridir.


Kullanıcıyı bu izne neden ihtiyaç duyduğunuz konusunda bilgilendirdiğinizden ve bu izni vermenin faydalarını aktif olarak gösterdiğinizden emin olun. Uygulamanız kısmen izne ihtiyaç duymadan çalışıyorsa bonus puanlar.


Google, kullanıcıların konumunun nasıl ele alınacağı konusunda bazı harika kılavuzların yanı sıra, arka planda konum verilerine erişim için ayrı bir kılavuz da sağlar.


Böylece gerekli incelemeyi yaptınız ve konuma erişim için kullanıcının iznine ihtiyacınız olduğuna karar verdiniz. Accompanist'teki izin kitaplığıyla bunu şu şekilde yapabilirsiniz:


 // Don't forget to add the permissions to AndroidManifest.xml val allLocationPermissionState = rememberMultiplePermissionsState( listOf(android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION) ) // Check if we have location permissions if (!allLocationPermissionsState.allPermissionsGranted) { // Show a component to request permission from the user Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, modifier = Modifier .padding(horizontal = 36.dp) .clip(RoundedCornerShape(16.dp)) .background(Color.white) ) { Text( modifier = Modifier.padding(top = 6.dp), textAlign = TextAlign.Center, text = "This app functions 150% times better with percise location enabled" ) Button(modifier = Modifier.padding(top = 12.dp), onClick = { allLocationPermissionsState.launchMultiplePermissionsRequest() }) { Text(text = "Grant Permission") } } }


Eşlikçi aracılığıyla, uygulamanın ACCESS_FINE_LOCATION iznine erişimi olup olmadığını veya İngilizce dilinde yüksek düzeyde GPS doğruluğu olup olmadığını kontrol ediyoruz. Aksi halde izin isteyemeyeceğiniz için, istenen izinleri Android bildirimine dahil etmek önemlidir.


Android sistemi ve Google Play mağazası da uygulamanızın nasıl çalıştığını anlamak ve kullanıcıları bilgilendirmek için manifest'i kullanır.

İzin verilmezse, izin ihtiyacını açıklayan küçük bir iletişim kutusu ve sistem aracılığıyla izin isteğini başlatmak için bir düğme gösterilir.



Haritayı Canlandırmak

Çoğu harita uygulaması kullanıcının haritayı dokunarak taşımasını gerektirirken, Compose için Google Haritalar, haritayı programlı olarak taşımak için API'ler sağlar. Bir etkinliğe yanıt olarak belirli bir alana gitmek istiyorsanız bu yararlı olabilir.


Bu örnekte, işaretçi koleksiyonumuz aracılığıyla uygulamada yavaşça gezineceğiz.


 Box(contentAlignment = Alignment.Center) { GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState ) { Clustering(items = parkMarkers, onClusterClick = { // Handle when the click is tapped false }, onClusterItemClick = { marker -> // Handle when the marker is tapped }) LaunchedEffect(key1 = "Animation") { for (marker in parkMarkers) { cameraPositionState.animate( CameraUpdateFactory.newLatLngZoom( marker.itemPosition, // LatLng 16.0f), // Zoom level 2000 // Animation duration in millis ), delay(4000L) // Delay in millis } } } }


Buradaki anahtar kısım LaunchedEffect içindeki koddur. Uygulama, her işaretçi için işaretçiye gitmek üzere bir cameraPositionState.animate() çağrısı ayarlar. Kamera bu bilgiyi CameraUpdateFactory.newLatLngZoom() kullanılarak oluşturulan bir kamera güncellemesi yoluyla alır.


Bu yöntem, haritanın yakınlaştırma düzeyini belirten bir kayan nokta olan LatLng ve animasyonun süresini ayarlamak için uzun bir değeri alır.

Son olarak, animasyonlar arasında boşluk bırakmak için her animasyonun arasına 4 saniyelik bir duraklama eklemek üzere delay() kullanırız.


Sokak Görünümü Gösteriliyor

Compose için Google Haritalar'ın size yardımcı olduğu yalnızca bir hava haritası değildir. Uygulamaların, bir konumun 360 derece görünümünü gösteren Street View'a erişmesine de izin verebilirsiniz. Bunu StreetView oluşturulabilir özelliğini kullanarak yaparsınız:


 var selectedMarker: ParkItem? by remember { mutableStateOf(null) } if (selectedMarker != null) { StreetView(Modifier.fillMaxSize(), streetViewPanoramaOptionsFactory = { StreetViewPanoramaOptions().position(selectedMarker!!.position) }) } else { Box(contentAlignment = Alignment.Center) { GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState ) { Clustering(items = parkMarkers, onClusterClick = { // Handle when the cluster is clicked false }, onClusterItemClick = { marker -> // Handle when a marker in the cluster is clicked selectedMarker = marker false }) } } }


Bu örnekte, bir işaretçiye her dokunulduğunda selectedMarker değişkenini ayarlıyoruz. Bir işaretçi seçilirse, işaretçinin konumundan geçen Sokak Görünümü'nü gösteririz.



Şekil Çizimi

Haritaya kendi şekillerinizi ve açıklamalarınızı çizmek isteyebilirsiniz. Compose için Google Haritalar bunu yapmak için bir dizi oluşturulabilir öğe sağlar; bu yazıda Circle oluşturulabilir öğesini kullanacağız.


Uygulamanız, kullanıcının konumundaki değişikliklere tepki vermek için Geofence kullanıyorsa daire iyi bir şekildir. Bir daire, coğrafi çitin aktif olduğu alanı temsil edebilir.


 Box(contentAlignment = Alignment.Center) { GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState ) { Clustering(items = parkMarkers, onClusterClick = { // Handle when the cluster is clicked false }, onClusterItemClick = { marker -> // Handle when a marker in the cluster is clicked selectedMarker = marker false }) } } parkMarkers.forEach { Circle( center = it.position, radius = 120.0, fillColor = Color.Green, strokeColor = Color.Green ) }


Burada işaretçilerimizin her biri için bir daire oluşturduk. Bir daire oluşturmak, ona dairenin yarıçapının bir konumunu ve boyutunu aktarmayı içerir. Ayrıca kenarlığın rengini ayarlamak ve dairenin rengini doldurmak için iki isteğe bağlı parametre kullanırız.



ScaleBar'ı Gösterme

İyi bir harita genellikle haritadaki alan ölçüsünün mesafeye eşdeğer olduğunu gösteren açıklamalar ve diyagramlarla birlikte gelir. Her harita aynı ölçüm biçimini kullanmayabileceğinden, bu size haritada yer alan alanlar hakkında bir fikir verir.


Yakınlaştırıp uzaklaştırabilen dijital haritalar için bu, temsil edilen mesafelerin dinamik olarak değişebilmesi nedeniyle belirli bir karmaşıklık katmanı ekler. Neyse ki Compose için Google Haritalar ihtiyacınızı karşılıyor.


Widget kitaplığını kullanarak DisappearingScaleBar ve ScaleBar oluşturulabilir öğelerine erişim kazanırsınız. Bunlar, haritanın üst kısmında yer alan ve kullanıcılara yakınlaştırma düzeyine bağlı olarak değişen bir mesafe ölçüsü sağlayan kullanıcı arayüzü bileşenleridir.


 Box(contentAlignment = Alignment.Center) { GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState ) { // You can also use ScaleBar DisappearingScaleBar( modifier = Modifier .padding(top = 5.dp, end = 15.dp) .align(Alignment.TopStart), cameraPositionState = cameraPositionState ) Clustering(items = parkMarkers, onClusterClick = { // Handle when the cluster is clicked false }, onClusterItemClick = { marker -> // Handle when a marker in the cluster is clicked selectedMarker = marker false }) } } parkMarkers.forEach { Circle( center = it.position, radius = 120.0, fillColor = Color.Green, strokeColor = Color.Green ) }


Şekillendirilebilir öğeyi ekledikten sonra, haritanın üst kısmında yakınlaştırma düzeyine bağlı olarak değişen bir ScaleBar elde edersiniz.




Yardım ve Destek

Compose için Google Haritalar, Google Haritalar ile çalışmanın harika bir yoludur ve öğrenecek daha çok şey var. Yardıma ihtiyacınız olursa önerebileceğim birkaç yer var:

  • Compose Repo için Google Haritalar : Kitaplığın kaynak kodunu içeren depo. Kitaplığın nasıl kullanılacağına ve ayrıca hata raporlarınızı ve katkılarınızı nereye gönderebileceğinize ilişkin kod örnekleri içerir
  • Android için Google Haritalar Web Sitesi : Android için Google Haritalar'ın arkasındaki kavramları öğrenmek için gidilecek yer. Bunlar yüksek düzeydedir ve Compose kütüphanesini kullanmazlar, ancak yine de arka planda kullanıldıkları için bunları bilmek önemlidir.
  • Google Haritalar Platformu Discord Google Haritalar için resmi Discord sunucusu. Burada birden fazla platform için Google Haritalar'ı tartışan, yardım isteyen ve teklif eden ve kendi çalışmalarını sergileyen kişileri bulabilirsiniz.