Android için Yerler SDK'sını (Kotlin) kullanmaya başlama

1. Başlamadan Önce

Bu codelab'de, Android için Yerler SDK'sını uygulamanıza nasıl entegre edeceğiniz ve Yerler SDK'sının her bir özelliğini nasıl kullanacağınız açıklanmaktadır.

Places demo uygulaması

Ön koşullar

  • Kotlin ve Android geliştirme hakkında temel düzeyde bilgi sahibi olmak

Neler öğreneceksiniz?

  • Kotlin uzantılarıyla Android için Yerler SDK'sını yükleme
  • Belirli bir yer için yer ayrıntılarını yükleme
  • Uygulamanıza Yer Otomatik Tamamlama widget'ı ekleme
  • Cihazın mevcut konumuna göre Current Place nasıl yüklenir?

İhtiyacınız olanlar

Bu codelab'i tamamlamak için aşağıdaki hesaplara, hizmetlere ve araçlara ihtiyacınız vardır:

2. Hazırlanın

Aşağıdaki etkinleştirme adımında Places API ve Android için Haritalar SDK'sı'nı etkinleştirin.

Google Haritalar Platformu'nu ayarlama

Henüz bir Google Cloud Platform hesabınız ve faturalandırmanın etkinleştirildiği bir projeniz yoksa lütfen faturalandırma hesabı ve proje oluşturmak için Google Haritalar Platformu'nu Kullanmaya Başlama kılavuzuna bakın.

  1. Cloud Console'da proje açılır menüsünü tıklayın ve bu codelab için kullanmak istediğiniz projeyi seçin.

  1. Bu codelab için gereken Google Haritalar Platformu API'lerini ve SDK'larını Google Cloud Marketplace'te etkinleştirin. Bunun için bu videodaki veya bu dokümandaki adımları uygulayın.
  2. Cloud Console'un Kimlik Bilgileri sayfasında bir API anahtarı oluşturun. Bu videodaki veya bu dokümandaki adımları uygulayabilirsiniz. Google Haritalar Platformu'na yapılan tüm istekler için API anahtarı gerekir.

3. Hızlı başlangıç

Bu codelab'i takip etmenize yardımcı olması için başlangıç kodunu indirerek mümkün olduğunca hızlı bir şekilde başlayabilirsiniz. Çözüme geçebilirsiniz ancak kendiniz oluşturmak için tüm adımları takip etmek istiyorsanız okumaya devam edin.

  1. git yüklüyse depoyu klonlayın.
git clone https://github.com/googlemaps/codelab-places-101-android-kotlin.git

Alternatif olarak, kaynak kodunu indirmek için bu düğmeyi tıklayın.

  1. Kodu indirdikten sonra Android Studio'da /starter dizinindeki projeyi açın. Bu proje, codelab'i tamamlamak için ihtiyacınız olan temel dosya yapısını içerir. Çalışmak için ihtiyaç duyduğunuz her şey /starter dizininde bulunur.

Çalışan çözüm kodunun tamamını görmek isterseniz tamamlanmış kodu /solution dizininde görüntüleyebilirsiniz.

4. API anahtarınızı projeye ekleme

Bu bölümde, API anahtarınızı uygulamanız tarafından güvenli bir şekilde referans verilebilecek şekilde nasıl saklayacağınız açıklanmaktadır. API anahtarınızı sürüm kontrol sisteminize işlememeniz gerekir. Bu nedenle, projenizin kök dizininin yerel kopyasına yerleştirilecek olan secrets.properties dosyasında saklamanızı öneririz. secrets.properties dosyası hakkında daha fazla bilgi için Gradle özellik dosyaları konusuna bakın.

Bu görevi kolaylaştırmak için Android İçin Secrets Gradle Plugin'i kullanmanızı öneririz.

Google Haritalar projenize Android İçin Secrets Gradle Plugin'i yüklemek üzere:

  1. Android Studio'da üst düzey build.gradle.kts veya build.gradle dosyanızı açın ve buildscript altındaki dependencies öğesine aşağıdaki kodu ekleyin.

build.gradle.kts kullanıyorsanız şunları ekleyin:

buildscript {
    dependencies {
        classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1")
    }
}

build.gradle kullanıyorsanız şunları ekleyin:

buildscript {
    dependencies {
        classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1"
    }
}
  1. Modül düzeyindeki build.gradle.kts veya build.gradle dosyanızı açın ve aşağıdaki kodu plugins öğesine ekleyin.

build.gradle.kts kullanıyorsanız şunları ekleyin:

plugins {
    // ...
    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
}

build.gradle kullanıyorsanız şunları ekleyin:

plugins {
    // ...
    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
}
  1. Modül düzeyindeki build.gradle.kts veya build.gradle dosyanızda targetSdk ve compileSdk değerlerinin 34 olarak ayarlandığından emin olun.
  2. Dosyayı kaydedin ve projenizi Gradle ile senkronize edin.
  3. secrets.properties dosyasını en üst düzey dizininizde açın ve aşağıdaki kodu ekleyin. YOUR_API_KEY kısmını API anahtarınızla değiştirin. secrets.properties, sürüm kontrol sistemine kaydedilmekten hariç tutulduğu için anahtarınızı bu dosyada saklayın.
PLACES_API_KEY=YOUR_API_KEY
  1. Dosyayı kaydedin.
  2. local.defaults.properties dosyasını üst düzey dizininizde (secrets.properties dosyasıyla aynı klasörde) oluşturun ve aşağıdaki kodu ekleyin.
PLACES_API_KEY=DEFAULT_API_KEY

Bu dosyanın amacı, secrets.properties dosyası bulunamazsa API anahtarı için yedek bir konum sağlamaktır. Böylece derlemeler başarısız olmaz. Bu durum, uygulamayı secrets.properties öğesini atlayan bir sürüm kontrol sisteminden klonlarsanız ve API anahtarınızı sağlamak için henüz yerel olarak bir secrets.properties dosyası oluşturmadıysanız meydana gelebilir.

  1. Dosyayı kaydedin.
  2. Android Studio'da modül düzeyindeki build.gradle.kts veya build.gradle dosyanızı açın ve secrets özelliğini düzenleyin. secrets özelliği yoksa ekleyin.

Eklentinin özelliklerini düzenleyerek propertiesFileName değerini secrets.properties, defaultPropertiesFileName değerini local.defaults.properties ve diğer özellikleri ayarlayın.

secrets {
    // Optionally specify a different file name containing your secrets.
    // The plugin defaults to "local.properties"
    propertiesFileName = "secrets.properties"

    // A properties file containing default secret values. This file can be
    // checked in version control.
    defaultPropertiesFileName = "local.defaults.properties"
}

5. Android için Yerler SDK'sını yükleme

Bu bölümde, Android için Yerler SDK'sını uygulamanızın bağımlılıklarına eklersiniz.

  1. API anahtarınıza artık uygulama içinden erişilebildiğine göre, Android için Yerler SDK'sı bağımlılığını uygulamanızın build.gradle dosyasına ekleyin.

Uygulama düzeyindeki build.gradle dosyanızı değiştirerek Android için Yerler SDK'sı bağımlılığını ekleyin:

app-level build.gradle

dependencies {
   // Dependency to include Places SDK for Android
   implementation 'com.google.android.libraries.places:places:3.4.0'
}
  1. Uygulamayı çalıştırın.

Artık boş ekranlı bir uygulama görmelisiniz. Bu ekranı üç demo ile doldurmaya devam edin.

6. Places Android KTX'i yükleme

Bir veya daha fazla Google Haritalar Platformu Android SDK'sı kullanan Kotlin uygulamalarında, Kotlin uzantısı (KTX) kitaplıkları; eş yordamlar, uzantı özellikleri/işlevleri gibi Kotlin dil özelliklerinden yararlanmanızı sağlar. Her Google Haritalar SDK'sının, aşağıda gösterildiği gibi karşılık gelen bir KTX kitaplığı vardır:

Google Haritalar Platformu KTX Şeması

Bu görevde, uygulamanızda Kotlin'e özgü dil özelliklerini kullanmak için Places Android KTX kitaplığını kullanın.

Places Android KTX bağımlılığını ekleyin

Kotlin'e özgü özelliklerden yararlanmak için bu SDK'ya karşılık gelen KTX kitaplığını uygulama düzeyindeki build.gradle dosyanıza ekleyin.

build.gradle

dependencies {
    // ...

    // Places SDK for Android KTX Library
    implementation 'com.google.maps.android:places-ktx:3.1.1'
}

7. Places istemcisini başlatma

Uygulama kapsamı için Yerler SDK'sını başlatma

DemoApplication.kt dosyasında, app/src/main/java/com/google/codelabs/maps/placesdemo klasöründe Android için Yerler SDK'sını başlatın. Aşağıdaki satırları onCreate işlevinin sonuna yapıştırın:

        // Initialize the SDK with the Google Maps Platform API key
        Places.initialize(this, BuildConfig.PLACES_API_KEY)

Uygulamanızı oluşturduğunuzda Android İçin Secrets Gradle Plugin, secrets.properties dosyanızdaki API anahtarını BuildConfig.PLACES_API_KEY olarak kullanılabilir hale getirir.

Uygulama dosyasını manifeste ekleyin

Application uzantısını DemoApplication ile genişlettiğiniz için manifesti güncellemeniz gerekiyor. app/src/main konumundaki AndroidManifest.xml dosyasında application öğesine android:name özelliğini ekleyin:

    <application
        android:name=".DemoApplication"
        ...
    </application>

Bu kod, uygulama manifestini src/main/java/com/google/codelabs/maps/placesdemo/ klasöründeki DemoApplication sınıfına yönlendirir.

8. Yer Ayrıntılarını Getirme

Ayrıntılar ekranı oluşturma

app/src/main/res/layout/ klasöründe boş bir LinearLayout içeren activity_details.xml düzeni bulunur. <LinearLayout> parantezleri arasına aşağıdaki kodu ekleyerek doğrusal düzeni doldurun.

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/details_input"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/details_input_hint"
            android:text="@string/details_input_default" />

    </com.google.android.material.textfield.TextInputLayout>

    <Button
        android:id="@+id/details_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/button_details" />

    <TextView
        android:id="@+id/details_response_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="16dp"
        android:textIsSelectable="true" />

Bu kod, kullanıcının herhangi bir yer kimliği girebileceği veya sağlanan varsayılanı kullanabileceği bir metin girişi alanı, yer ayrıntıları isteğini başlatacak bir düğme ve yanıttaki bilgileri görüntüleyecek bir TextView ekler. İlişkili dizeler, src/main/res/values/strings.xml dosyasında sizin için tanımlanır.

Ayrıntılar etkinliği oluşturma

  1. DetailsActivity.kt klasöründe bir src/main/java/com/google/codelabs/maps/placesdemo/ dosyası oluşturun ve bu dosyayı yeni oluşturduğunuz düzenle ilişkilendirin. Bu kodu dosyaya yapıştırın:
@ExperimentalCoroutinesApi
class DetailsActivity : AppCompatActivity() {
    private lateinit var placesClient: PlacesClient
    private lateinit var detailsButton: Button
    private lateinit var detailsInput: TextInputEditText
    private lateinit var responseView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_details)

        // Set up view objects
        detailsInput = findViewById(R.id.details_input)
        detailsButton = findViewById(R.id.details_button)
        responseView = findViewById(R.id.details_response_content)

        val apiKey = BuildConfig.PLACES_API_KEY

        // Log an error if apiKey is not set.
        if (apiKey.isEmpty() || apiKey == "DEFAULT_API_KEY") {
            Log.e(TAG, "No api key")
            finish()
            return
        }
    }
}
  1. Bu etkinlikle kullanılmak üzere bir Places Client oluşturun. Bu kodu, onCreate işlevinde API anahtarını kontrol eden kodun sonrasına yapıştırın.
        // Retrieve a PlacesClient (previously initialized - see DemoApplication)
        placesClient = Places.createClient(this)
  1. Places Client kurulduktan sonra düğmeye bir tıklama işleyicisi ekleyin. Bu kodu, onCreate işlevinde Places Client oluşturulduktan sonra yapıştırın.
        // Upon button click, fetch and display the Place Details
        detailsButton.setOnClickListener { button ->
            button.isEnabled = false
            val placeId = detailsInput.text.toString()
            val placeFields = listOf(
                Place.Field.NAME,
                Place.Field.ID,
                Place.Field.LAT_LNG,
                Place.Field.ADDRESS
            )
            lifecycleScope.launch {
                try {
                    val response = placesClient.awaitFetchPlace(placeId, placeFields)
                    responseView.text = response.prettyPrint()
                } catch (e: Exception) {
                    e.printStackTrace()
                    responseView.text = e.message
                }
                button.isEnabled = true
            }
        }

Bu kod, giriş alanına girilen yer kimliğini alır, yer için hangi alanların isteneceği tanımlar, bir FetchPlaceRequest oluşturur, görevi başlatır ve başarı veya başarısızlık durumunu dinler. İstek başarılı olursa işlev, TextView'u istenen ayrıntılarla doldurur.

Manifeste Ayrıntılar etkinliğini ekleme

app/src/main konumundaki AndroidManifest.xml dosyasında <application> öğesinin alt öğesi olarak DetailsActivity için bir <activity> öğesi ekleyin:

        <activity android:name=".DetailsActivity" android:label="@string/details_demo_title" />

Ayrıntılar etkinliğini demo menüsüne ekleme

Ana ekranda mevcut demoları listelemek için boş bir Demo modülü sağlanır. Yer Ayrıntıları etkinliği oluşturduktan sonra, aşağıdaki kodu kullanarak Demo.kt klasöründeki src/main/java/com/google/codelabs/maps/placesdemo/ dosyasına ekleyin:

    DETAILS_FRAGMENT_DEMO(
        R.string.details_demo_title,
        R.string.details_demo_description,
        DetailsActivity::class.java
    ),

İlişkili dizeler, src/main/res/values/strings.xml dosyasında tanımlanır.

MainActivity.kt öğesini inceleyin ve Demo modülünün içeriğinde yineleme yapılarak doldurulan bir ListView oluşturduğunu gözlemleyin. Kullanıcı listedeki bir öğeye dokunduğunda tıklama işleyici, ilişkili etkinliği açar.

Uygulamayı çalıştırma

  1. Uygulamayı çalıştırın. Bu kez listede yer ayrıntıları demosunu sunan bir öğe görmelisiniz.
  2. Yer Ayrıntıları metnine dokunun. Giriş alanı ve düğmeyle birlikte oluşturduğunuz görünümü görürsünüz.
  3. "AYRINTILARI GÖSTER" düğmesine dokunun. Varsayılan yer kimliğini kullandıysanız Şekil 1'de gösterildiği gibi yer adı, adres ve harita koordinatları gösterilir.

Yanıt içeren yer ayrıntıları etkinliği

1.şekil Yanıtın gösterildiği yer ayrıntıları etkinliği.

9. Yer Adı Otomatik Tamamlama ekleme

Otomatik tamamlama ekranı oluşturma

app/src/main/res/layout/ klasöründe boş bir LinearLayout içeren activity_autocomplete.xml düzeni sağlanır. Bu kodu <LinearLayout> parantezleri arasına ekleyerek doğrusal düzeni doldurun.

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/autocomplete_fragment"
        android:background="@android:color/white"
        android:name="com.google.android.libraries.places.widget.AutocompleteSupportFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/autocomplete_response_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="16dp"
        android:textIsSelectable="true" />

Bu kod, AutocompleteSupportFragment widget'ı ve yanıttaki bilgileri göstermek için bir TextView ekler. İlişkili dizeler, src/main/res/values/strings.xml dosyasında tanımlanır.

Otomatik Tamamlama etkinliği oluşturma

  1. src/main/java/com/google/codelabs/maps/placesdemo/ klasöründe bir AutocompleteActivity.kt dosyası oluşturun ve bu kodu kullanarak tanımlayın:
@ExperimentalCoroutinesApi
class AutocompleteActivity : AppCompatActivity() {
    private lateinit var responseView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_autocomplete)

        // Set up view objects
        responseView = findViewById(R.id.autocomplete_response_content)
        val autocompleteFragment =
            supportFragmentManager.findFragmentById(R.id.autocomplete_fragment)
                    as AutocompleteSupportFragment
    }
}

Bu kod, etkinliği düzen dosyasında tanımladığınız görünümler ve AutocompleteSupportFramgent ile ilişkilendirir.

  1. Ardından, kullanıcı Yer Otomatik Tamamlama tarafından sunulan tahminlerden birini seçtiğinde ne olacağını tanımlayın. Bu kodu onCreate işlevinin sonuna ekleyin:
        val placeFields: List<Place.Field> =
            listOf(Place.Field.NAME, Place.Field.ID, Place.Field.ADDRESS, Place.Field.LAT_LNG)
        autocompleteFragment.setPlaceFields(placeFields)

        // Listen to place selection events
        lifecycleScope.launchWhenCreated {
            autocompleteFragment.placeSelectionEvents().collect { event ->
                when (event) {
                    is PlaceSelectionSuccess -> {
                        val place = event.place
                        responseView.text = prettyPrintAutocompleteWidget(place, false)
                    }

                    is PlaceSelectionError -> Toast.makeText(
                        this@AutocompleteActivity,
                        "Failed to get place '${event.status.statusMessage}'",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
        }

Bu kod, yer için hangi alanların isteneceği tanımlar, yer seçimi etkinliğini ve başarı veya başarısızlığı dinler. İstek başarılı olursa işlev, TextView'u yer ayrıntılarıyla doldurur. Yer Otomatik Tamamlama'nın bir Yer nesnesi döndürdüğünü unutmayın. Yer Otomatik Tamamlama widget'ı kullanılırken ayrı bir Yer Ayrıntıları isteği göndermenize gerek yoktur.

Otomatik Tamamlama etkinliğini manifest dosyasına ekleme

app/src/main konumundaki AndroidManifest.xml dosyasında <application> öğesinin alt öğesi olarak AutocompleteActivity için bir <activity> öğesi ekleyin:

        <activity android:name=".AutocompleteActivity" android:label="@string/autocomplete_fragment_demo_title" />

Otomatik tamamlama etkinliğini demo menüsüne ekleme

Daha önce olduğu gibi, Demo modülündeki listeye ekleyerek Place Autocomplete demosunu ana ekrana ekleyin. Yer otomatik tamamlama etkinliği oluşturduktan sonra bu etkinliği src/main/java/com/google/codelabs/maps/placesdemo/ klasöründeki Demo.kt dosyasına ekleyin. Bu kodu DETAILS_FRAGMENT_DEMO öğesinin hemen sonrasına yapıştırın:

    AUTOCOMPLETE_FRAGMENT_DEMO(
        R.string.autocomplete_fragment_demo_title,
        R.string.autocomplete_fragment_demo_description,
        AutocompleteActivity::class.java
    ),

İlişkili dizeler, src/main/res/values/strings.xml dosyasında tanımlanır.

Uygulamayı çalıştırma

  1. Uygulamayı çalıştırın. Bu kez ana ekran listesinde iki öğe görmeniz gerekir.
  2. Yer otomatik tamamlama satırına dokunun. Şekil 2'de gösterildiği gibi bir yer otomatik tamamlama girişi pop-up'ı görmeniz gerekir.
  3. Bir yerin adını yazmaya başlayın. Bu, bir kuruluş adı, adres veya coğrafi bölge olabilir. Tahminler, siz yazarken gösterilmelidir.
  4. Tahminlerden birini seçin. Tahminler kaybolur ve TextView, seçilen yerle ilgili ayrıntıları Şekil 3'te gösterildiği gibi görüntüler.

Kullanıcı giriş alanına dokunduktan sonraki otomatik tamamlama etkinliği

Şekil 2. Kullanıcı giriş alanına dokunduktan sonraki otomatik tamamlama etkinliği.

Kullanıcı &quot;Niagara Şelalesi&quot; yazıp seçtikten sonraki otomatik tamamlama etkinliği

3.Şekil Kullanıcı "Niagara Şelalesi" yazıp seçtikten sonra yer ayrıntılarını gösteren otomatik tamamlama etkinliği.

10. Cihazın mevcut yerini alma

Mevcut Yer ekranı oluşturma

app/src/main/res/layout/ klasöründe boş bir LinearLayout içeren activity_current.xml düzeni sağlanmıştır. <LinearLayout> ayraçlarının arasına aşağıdaki kodu ekleyerek doğrusal düzeni doldurun.

    <Button
        android:id="@+id/current_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/current_button" />

    <TextView
        android:id="@+id/current_response_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="16dp"
        android:scrollbars = "vertical"
        android:textIsSelectable="true" />

Mevcut Yer etkinliği oluşturma

  1. src/main/java/com/google/codelabs/maps/placesdemo/ klasöründe bir CurrentPlaceActivity.kt dosyası oluşturun ve bu kodu kullanarak tanımlayın:
@ExperimentalCoroutinesApi
class CurrentPlaceActivity : AppCompatActivity(), OnMapReadyCallback {
    private lateinit var placesClient: PlacesClient
    private lateinit var currentButton: Button
    private lateinit var responseView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_current)

        // Retrieve a PlacesClient (previously initialized - see DemoApplication)
        placesClient = Places.createClient(this)

        // Set view objects
        currentButton = findViewById(R.id.current_button)
        responseView = findViewById(R.id.current_response_content)

        // Set listener for initiating Current Place
        currentButton.setOnClickListener {
            checkPermissionThenFindCurrentPlace()
        }
    }
}

Bu kod, etkinliği düzen dosyasında tanımladığınız görünümlerle ilişkilendirir. Ayrıca, düğme tıklandığında checkPermissionThenFindCurrentPlace işlevini çağırmak için düğmeye bir tıklama işleyici ekler.

  1. checkPermissionThenFindCurrentPlace() öğesini tanımlayarak ayrıntılı konum izninin olup olmadığını kontrol edin ve henüz verilmemişse bu izni isteyin. Bu kodu onCreate işlevinden sonra yapıştırın.
    /**
     * Checks that the user has granted permission for fine or coarse location.
     * If granted, finds current Place.
     * If not yet granted, launches the permission request.
     * See https://developer.android.com/training/permissions/requesting
     */
    private fun checkPermissionThenFindCurrentPlace() {
        when {
            (ContextCompat.checkSelfPermission(
                this,
                ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(
                this,
                ACCESS_COARSE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED) -> {
                // You can use the API that requires the permission.
                findCurrentPlace()
            }

            shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)
            -> {
                Log.d(TAG, "Showing permission rationale dialog")
                // TODO: In an educational UI, explain to the user why your app requires this
                // permission for a specific feature to behave as expected. In this UI,
                // include a "cancel" or "no thanks" button that allows the user to
                // continue using your app without granting the permission.
            }

            else -> {
                // Ask for both the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions.
                ActivityCompat.requestPermissions(
                    this,
                    arrayOf(
                        ACCESS_FINE_LOCATION,
                        ACCESS_COARSE_LOCATION
                    ),
                    PERMISSION_REQUEST_CODE
                )
            }
        }
    }

    companion object {
        private const val TAG = "CurrentPlaceActivity"
        private const val PERMISSION_REQUEST_CODE = 9
    }
  1. else işlevinin checkPermissionThenFindCurrentPlace dalı requestPermissions işlevini çağırdığında uygulama, kullanıcıya izin isteği iletişim kutusu gösterir. Kullanıcı, Android 12'den daha eski bir işletim sisteminin yüklü olduğu bir cihaz kullanıyorsa yalnızca tam konum izni verebilir. Android 12 veya sonraki sürümleri çalıştıran bir cihaz kullanan kullanıcılara, Şekil 4'te gösterildiği gibi tam konum yerine yaklaşık (kaba) konum sağlama seçeneği sunulur.

Android 12 veya sonraki bir sürümün yüklü olduğu cihazlarda kullanıcı izni isteme

Şekil 4. Android 12 veya sonraki sürümlerin yüklü olduğu bir cihazda kullanıcı izni istenirken tam veya yaklaşık konum izni verme seçeneği sunulur.

Kullanıcı, sistem izinleri iletişim kutusunu yanıtladıktan sonra sistem, onRequestPermissionsResult işlevinin uygulamanızdaki uygulamasını çağırır. Sistem, izin iletişim kutusuna verilen kullanıcı yanıtını ve tanımladığınız istek kodunu iletir. Aşağıdaki kodu onRequestPermissionResult altına yapıştırarak bu Anlık Yer etkinliğiyle ilgili konum izinlerinin istek kodunu işlemek için onRequestPermissionResult işlevini geçersiz kılın.checkPermissionThenFindCurrentPlace

    @SuppressLint("MissingPermission")
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>, grantResults: IntArray
    ) {
        if (requestCode != PERMISSION_REQUEST_CODE) {
            super.onRequestPermissionsResult(
                requestCode,
                permissions,
                grantResults
            )
            return
        } else if (
            permissions.toList().zip(grantResults.toList())
                .firstOrNull { (permission, grantResult) ->
                    grantResult == PackageManager.PERMISSION_GRANTED && (permission == ACCESS_FINE_LOCATION || permission == ACCESS_COARSE_LOCATION)
                } != null
        )
        // At least one location permission has been granted, so proceed with Find Current Place
        findCurrentPlace()
    }
  1. İzin verildikten sonra findCurrentPlace işlevi çalışır. İşlevi, onRequestPermissionsResult işlevinden sonra bu kodla tanımlayın.
    /**
     * Fetches a list of [PlaceLikelihood] instances that represent the Places the user is
     * most likely to be at currently.
     */
    @RequiresPermission(anyOf = [ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION])
    private fun findCurrentPlace() {
        // Use fields to define the data types to return.
        val placeFields: List<Place.Field> =
            listOf(Place.Field.NAME, Place.Field.ID, Place.Field.ADDRESS, Place.Field.LAT_LNG)

        // Call findCurrentPlace and handle the response (first check that the user has granted permission).
        if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) ==
            PackageManager.PERMISSION_GRANTED ||
            ContextCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) ==
            PackageManager.PERMISSION_GRANTED
        ) {
            // Retrieve likely places based on the device's current location
            currentButton.isEnabled = false
            lifecycleScope.launch {
                val response = placesClient.awaitFindCurrentPlace(placeFields)

                responseView.text = response.prettyPrint()

                // Enable scrolling on the long list of likely places
                val movementMethod = ScrollingMovementMethod()
                responseView.movementMethod = movementMethod
            }
        } else {
            Log.d(TAG, "LOCATION permission not granted")
            checkPermissionThenFindCurrentPlace()
        }
    }

Bu kod, olası yerler için hangi alanların isteneceği tanımlar, FindCurrentPlaceRequest oluşturur, görevi başlatır ve TextView'u istenen ayrıntılarla doldurur.

Mevcut Yer etkinliğini manifeste ekleyin

app/src/main konumundaki AndroidManifest.xml dosyasında <application> öğesinin alt öğesi olarak CurrentPlaceActivity için bir <activity> öğesi ekleyin:

        <activity android:name=".CurrentPlaceActivity" android:label="@string/current_demo_title" />

Mevcut Yer etkinliğini demo menüsüne ekleme

Tıpkı daha önce olduğu gibi, Demo modülündeki listeye ekleyerek Current Place demosunu ana ekrana ekleyin. Mevcut Yer etkinliği oluşturduktan sonra bu etkinliği src/main/java/com/google/codelabs/maps/placesdemo/ klasöründeki Demo.kt dosyasına ekleyin. Bu kodu AUTOCOMPLETE_FRAGMENT_DEMO öğesinin hemen sonrasına yapıştırın:

    CURRENT_FRAGMENT_DEMO(
        R.string.current_demo_title,
        R.string.current_demo_description,
        CurrentPlaceActivity::class.java
    ),

İlişkili dizeler, src/main/res/values/strings.xml dosyasında tanımlanır.

Uygulamayı çalıştırma

  1. Uygulamayı çalıştırın. Bu kez ana ekran listesinde üç öğe görmeniz gerekir.
  2. Geçerli Yer satırına dokunun. Ekranda bir düğme görmelisiniz.
  3. Düğmeye dokunun. Bu uygulamaya daha önce konum izni vermediyseniz izin isteği açılır.
  4. Uygulamaya cihazın konumuna erişim izni verin.
  5. Düğmeye tekrar dokunun. Bu kez, Şekil 5'te gösterildiği gibi, yakındaki 20'ye kadar yerin listesi ve olasılıkları görünür.

Cihazın bildirilen konumu için olası Geçerli Yer eşleşmelerini gösterme

5.şekil Cihazın bildirilen konumu için olası mevcut yer eşleşmelerini gösterir.

11. Mevcut Yeri haritada gösterme

Harita bağımlılığını ekleyin

Modül düzeyindeki build.gradle dosyanıza Android için Haritalar SDK'sı Google Play Hizmetleri bağımlılığını ekleyin.

app/build.gradle

dependencies {
    // ...
    implementation 'com.google.android.gms:play-services-maps:18.2.0'
}

Haritaları hesaba katmak için Android manifestini güncelleyin

meta-data öğesinin içine aşağıdaki application öğelerini ekleyin.

Bunlar, uygulamanın derlendiği Google Play Hizmetleri sürümünü yerleştirir ve API anahtarınızı belirtir.

AndroidManifest.xml

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="${MAPS_API_KEY}" />

API anahtarını secrets.properties adlı cihaza ekleyin

secrets.properties dosyasını en üst düzey dizininizde açın ve aşağıdaki kodu ekleyin. YOUR_API_KEY kısmını API anahtarınızla değiştirin.

MAPS_API_KEY=YOUR_API_KEY

local.defaults.properties dosyasını üst düzey dizininizde (secrets.properties dosyasıyla aynı klasör) açın ve aşağıdaki kodu ekleyin.

MAPS_API_KEY=DEFAULT_API_KEY

API anahtarını kontrol edin

onCreate() içinde uygulama, Haritalar API anahtarını kontrol eder ve Haritalar destek parçasını başlatır. getMapAsync(), harita geri arama özelliğine kaydolmak için kullanılır.

Bunu yapmak için aşağıdaki kodu ekleyin.

CurrentPlaceActivity.kt

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_current)

        val apiKey = BuildConfig.MAPS_API_KEY

        // Log an error if apiKey is not set.
        if (apiKey.isEmpty() || apiKey == "DEFAULT_API_KEY") {
            Log.e("Places test", "No api key")
            finish()
            return
        }

        // Retrieve a PlacesClient (previously initialized - see DemoApplication)
        placesClient = Places.createClient(this)
        (supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment?)?.getMapAsync(this)

        // ...
    }

Harita düzenini oluşturma

  1. app/src/main/res/layout/ klasöründe fragment_map.xml adlı bir düzen dosyası oluşturun ve düzeni aşağıdaki kodla doldurun.

res/layout/fragment_map.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.google.codelabs.maps.placesdemo.CurrentPlaceActivity" />

Bu, harita için kapsayıcı görevi görecek ve GoogleMap nesnesine erişim sağlayacak bir SupportMapFragment tanımlar.

  1. activity_current.xml düzeninde, app/src/main/res/layout/ klasöründe bulunan doğrusal düzenin en altına aşağıdaki kodu ekleyin.

res/layout/activity_current.xml

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="16dp"
        android:paddingBottom="16dp"
        android:text="@string/showing_most_likely_place"
        style="@style/TextAppearance.AppCompat.Title"/>

    <include layout="@layout/fragment_map"/>

Eklenen TextView, oluşturulması gereken yeni bir dize kaynağına referans veriyor.

  1. app/src/main/res/values/strings.xml içinde aşağıdaki dize kaynağını ekleyin.

res/values/strings.xml

<string name="showing_most_likely_place">Showing most likely place</string>

Haritaya ek görünümler eklendiğinden, yer listesini gösteren TextView öğesinin yüksekliği, bu görünümlerin görünür kalması için ayarlanmalıdır.

  1. Kimliği current_response_content olan TextView öğesine maxHeight özelliğini ekleyin.

res/layout/activity_current.xml

android:maxHeight="200dp"

OnMapReadyCallback işaretlemesini uygulayın

Sınıf bildirimine ekleyerek OnMapReadyCallback arayüzünü uygulayın ve GoogleMap nesnesi kullanılabilir olduğunda haritayı ayarlamak için onMapReady() yöntemini geçersiz kılın:

CurrentPlaceActivity.kt

class CurrentPlaceActivity : AppCompatActivity(), OnMapReadyCallback {

Sınıfın sonuna aşağıdaki kodu ekleyin:

CurrentPlaceActivity.kt

    override fun onMapReady(map: GoogleMap) {
        this.map = map
        lastKnownLocation?.let { location ->
            map.moveCamera(
                CameraUpdateFactory.newLatLngZoom(
                    location,
                    DEFAULT_ZOOM
                )
            )
        }
    }

Geri çağırmanın düzgün çalışması için bazı sınıf değişkenleri gerekir. Sınıf başlığının hemen ardından şunları ekleyin:

CurrentPlaceActivity.kt

private var map: GoogleMap? = null
private var lastKnownLocation: LatLng? = null

Aşağıdaki kodu sınıf arkadaşı nesnesine ekleyin:

CurrentPlaceActivity.kt

private const val DEFAULT_ZOOM = 15f

Uygulamayı çalıştırma

  1. Uygulamayı çalıştırın.
  2. Geçerli Yer satırına dokunun. Ekranda bir düğme görmelisiniz.
  3. Düğmeye dokunun. Bu uygulamaya daha önce konum izni vermediyseniz izin isteği açılır.
  4. Uygulamaya cihazın konumuna erişim izni verin.
  5. Düğmeye tekrar dokunun. Harita gösterilir.

Haritayı gösteren Geçerli Yer etkinliği

6.şekil Haritayı gösteren Geçerli Yer etkinliği.

Haritayı bir yerle güncelleme

Sınıfın sonuna aşağıdaki kodu ekleyin:

CurrentPlaceActivity.kt

private data class LikelyPlace(
    val name: String,
    val address: String,
    val attribution: List<String>,
    val latLng: LatLng
)

private fun PlaceLikelihood.toLikelyPlace(): LikelyPlace? {
    val name = this.place.name
    val address = this.place.address
    val latLng = this.place.latLng
    val attributions = this.place.attributions ?: emptyList()

    return if (name != null && address != null && latLng != null) {
        LikelyPlace(name, address, attributions, latLng)
    } else {
        null
    }
}

Bunlar, yerin verilerini depolamak ve biçimlendirmek için kullanılır.

Sınıfın başında, döndürülen yerin verilerini depolamak için kullanılan bir değişken oluşturmak üzere aşağıdaki kodu ekleyin.

CurrentPlaceActivity.kt

private val likelyPlaces = mutableListOf<LikelyPlace>()

Bu adımda kod , kullanıcıya bir Yerler listesi sunulacak ve kullanıcı haritada gösterilecek bir yer seçecek şekilde değiştirilir. Tüm Yerler verileri ekranda bir listede gösterilir.

findCurrentPlace işlevinde, bu kod satırından önceki lifecycleScope.launch bloğunda

CurrentPlaceActivity.kt

responseView.text = response.prettyPrint()

Aşağıdaki kodu ekleyin:

CurrentPlaceActivity.kt

                likelyPlaces.clear()

                likelyPlaces.addAll(
                    response.placeLikelihoods.take(M_MAX_ENTRIES).mapNotNull { placeLikelihood ->
                        placeLikelihood.toLikelyPlace()
                    }
                )

                openPlacesDialog()

Bu kod, gösterilecek maksimum yer sayısı için bir sabit gerektirir.

Yardımcı nesneye bu sabitin kodunu ekleyin.

CurrentPlaceActivity.kt

private const val M_MAX_ENTRIES = 5

Kullanıcının yer seçmesine olanak tanıyan iletişim kutusunu oluşturan aşağıdaki kodu ekleyin.

CurrentPlaceActivity.kt

    /**
     * Displays a form allowing the user to select a place from a list of likely places.
     */
    private fun openPlacesDialog() {
        // Ask the user to choose the place where they are now.
        val listener =
            DialogInterface.OnClickListener { _, which -> // The "which" argument contains the position of the selected item.
                val likelyPlace = likelyPlaces[which]
                lastKnownLocation = likelyPlace.latLng

                val snippet = buildString {
                    append(likelyPlace.address)
                    if (likelyPlace.attribution.isNotEmpty()) {
                        append("\n")
                        append(likelyPlace.attribution.joinToString(", "))
                    }
                }

                val place = Place.builder().apply {
                    name = likelyPlace.name
                    latLng = likelyPlace.latLng
                }.build()

                map?.clear()

                setPlaceOnMap(place, snippet)
            }

        // Display the dialog.
        AlertDialog.Builder(this)
            .setTitle(R.string.pick_place)
            .setItems(likelyPlaces.map { it.name }.toTypedArray(), listener)
            .setOnDismissListener {
                currentButton.isEnabled = true
            }
            .show()
    }

Android'deki en iyi uygulamalara uygun olarak iletişim kutusu, app/src/main/res/values/ klasöründeki strings.xml kaynak dosyasına eklenmesi gereken bir dize kaynağına referans veriyor.

strings.xml alanına aşağıdakileri ekleyin:

res/values/strings.xml

    <string name="pick_place">Choose a place</string>

Bu işlevler daha sonra kamerayı hareket ettiren ve seçilen konuma işaretçi yerleştiren setPlaceOnMap işlevini çağırır.

Aşağıdaki kodu ekleyin:

CurrentPlaceActivity.kt

    private fun setPlaceOnMap(place: Place?, markerSnippet: String?) {
        val latLng = place?.latLng ?: defaultLocation
        map?.moveCamera(
            CameraUpdateFactory.newLatLngZoom(
                latLng,
                DEFAULT_ZOOM
            )
        )
        map?.addMarker(
            MarkerOptions()
                .position(latLng)
                .title(place?.name)
                .snippet(markerSnippet)
        )
    }

Haritaların durumunu kaydetmeniz ve geri yüklemeniz de önerilir.

Durumunu kaydetmek için onSaveInstanceState işlevini geçersiz kılın ve aşağıdaki kodu ekleyin:

CurrentPlaceActivity.kt

    /**
     * Saves the state of the map when the activity is paused.
     */
    override fun onSaveInstanceState(outState: Bundle) {
        outState.putParcelable(KEY_LOCATION, lastKnownLocation)
        super.onSaveInstanceState(outState)
    }

Durumunu geri yüklemek için onCreate bölümünde setContentView çağrısından sonra aşağıdaki kodu ekleyin:

CurrentPlaceActivity.kt

        if (savedInstanceState != null) {
            lastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION)
        }

Kaydetme ve geri yükleme için anahtar gerekir. Bu, yardımcı nesneden gelen sabit bir değerdir.

Eşlik eden nesne bloğuna aşağıdakileri ekleyin:

CurrentPlaceActivity.kt

        // Key for storing activity state.
        private const val KEY_LOCATION = "location"

Uygulamayı çalıştırma

  1. Uygulamayı çalıştırın.
  2. Geçerli Yer satırına dokunun. Ekranda bir düğme görmelisiniz.
  3. Düğmeye dokunun. Bu uygulamaya daha önce konum izni vermediyseniz izin isteği açılır.
  4. Uygulamaya cihazın konumuna erişim izni verin.
  5. Düğmeye tekrar dokunun.
  6. Dokunarak bir yer seçin. Harita yakınlaştırılır ve seçilen konuma yerleştirilen bir işaretçiyle ortalanır.

Seçilen konumda işaretçi bulunan harita

Şekil 7. Seçilen konumda işaretçi bulunan harita.

12. Tebrikler

Android için Yerler SDK'sını kullanarak Android uygulamasını başarıyla oluşturdunuz.

Öğrendikleriniz

Sırada ne var?

  • Daha fazla ilham almak için örnek ve demoların android-places-demos GitHub deposunu inceleyin veya çatallayın.
  • Google Haritalar Platformu ile Android uygulamaları oluşturmak için diğer Kotlin codelab'lerinden bilgi edinin.
  • Aşağıdaki soruyu yanıtlayarak en yararlı bulacağınız içerikleri oluşturmamıza yardımcı olun:

Başka hangi codelab'leri görmek istersiniz?

Haritalarda veri görselleştirme Haritalarımın stilini özelleştirme hakkında daha fazla bilgi Haritalarda 3D etkileşimler için geliştirme

İstediğiniz codelab listelenmiyor mu? Buradan yeni bir sorunla ilgili istekte bulunun.