เริ่มต้นใช้งาน Places SDK สำหรับ Android (Kotlin)

1. ก่อนที่คุณจะเริ่มต้น

โค้ดแล็บนี้จะสอนวิธีผสานรวม Places SDK สำหรับ Android กับแอป และวิธีใช้ฟีเจอร์แต่ละอย่างของ Places SDK

แอปเดโม Places

ข้อกำหนดเบื้องต้น

  • ความรู้พื้นฐานเกี่ยวกับการพัฒนา Kotlin และ Android

สิ่งที่คุณจะได้เรียนรู้

  • วิธีติดตั้ง Places SDK สำหรับ Android ด้วยส่วนขยาย Kotlin
  • วิธีโหลดรายละเอียดสถานที่สำหรับสถานที่ที่เฉพาะเจาะจง
  • วิธีเพิ่มวิดเจ็ตการเติมข้อความอัตโนมัติของสถานที่ลงในแอป
  • วิธีโหลดสถานที่ปัจจุบันตามตำแหน่งที่อุปกรณ์รายงานในปัจจุบัน

สิ่งที่คุณต้องมี

หากต้องการทำ Codelab นี้ให้เสร็จสมบูรณ์ คุณจะต้องมีบัญชี บริการ และเครื่องมือต่อไปนี้

2. ตั้งค่า

สำหรับขั้นตอนการเปิดใช้ด้านล่าง ให้เปิดใช้ Places API และ Maps SDK สำหรับ Android

ตั้งค่า Google Maps Platform

หากยังไม่มีบัญชี Google Cloud Platform และโปรเจ็กต์ที่เปิดใช้การเรียกเก็บเงิน โปรดดูคู่มือเริ่มต้นใช้งาน Google Maps Platform เพื่อสร้างบัญชีสำหรับการเรียกเก็บเงินและโปรเจ็กต์

  1. ใน Cloud Console ให้คลิกเมนูแบบเลื่อนลงของโปรเจ็กต์ แล้วเลือกโปรเจ็กต์ที่ต้องการใช้สำหรับ Codelab นี้

  1. เปิดใช้ Google Maps Platform APIs และ SDK ที่จำเป็นสำหรับ Codelab นี้ใน Google Cloud Marketplace โดยทำตามขั้นตอนในวิดีโอนี้หรือเอกสารประกอบนี้
  2. สร้างคีย์ API ในหน้าข้อมูลเข้าสู่ระบบของ Cloud Console คุณสามารถทำตามขั้นตอนในวิดีโอนี้หรือเอกสารประกอบนี้ คำขอทั้งหมดไปยัง Google Maps Platform ต้องใช้คีย์ API

3. การเริ่มใช้งานอย่างง่าย

หากต้องการให้คุณเริ่มต้นใช้งานได้โดยเร็วที่สุด ให้ดาวน์โหลดโค้ดเริ่มต้นเพื่อช่วยให้คุณทำตาม Codelab นี้ได้ คุณสามารถข้ามไปยังวิธีแก้ปัญหาได้ แต่หากต้องการทำตามขั้นตอนทั้งหมดเพื่อสร้างด้วยตนเอง โปรดอ่านต่อ

  1. โคลนที่เก็บหากคุณติดตั้ง git ไว้
git clone https://github.com/googlemaps/codelab-places-101-android-kotlin.git

หรือคลิกปุ่มนี้เพื่อดาวน์โหลดซอร์สโค้ด

  1. หลังจากดาวน์โหลดโค้ดแล้ว ให้เปิดโปรเจ็กต์ที่อยู่ในไดเรกทอรี /starter ใน Android Studio โปรเจ็กต์นี้มีโครงสร้างไฟล์พื้นฐานที่คุณจะต้องใช้เพื่อทำ Codelab ให้เสร็จสมบูรณ์ ทุกอย่างที่คุณต้องใช้ในการทำงานจะอยู่ในไดเรกทอรี /starter

หากต้องการดูโค้ดโซลูชันทั้งหมดที่ทำงานอยู่ คุณสามารถดูโค้ดที่เสร็จสมบูรณ์แล้วในไดเรกทอรี /solution

4. เพิ่มคีย์ API ลงในโปรเจ็กต์

ส่วนนี้อธิบายวิธีจัดเก็บคีย์ API เพื่อให้แอปอ้างอิงได้อย่างปลอดภัย คุณไม่ควรเช็คอินคีย์ API ในระบบควบคุมเวอร์ชัน ดังนั้นเราขอแนะนำให้จัดเก็บคีย์ในไฟล์ secrets.properties ซึ่งจะอยู่ในสำเนาในเครื่องของไดเรกทอรีรากของโปรเจ็กต์ ดูข้อมูลเพิ่มเติมเกี่ยวกับไฟล์ secrets.properties ได้ที่ไฟล์พร็อพเพอร์ตี้ Gradle

เราขอแนะนำให้ใช้ปลั๊กอินข้อมูลลับ Gradle สำหรับ Android เพื่อให้งานนี้มีประสิทธิภาพมากขึ้น

วิธีติดตั้งปลั๊กอินข้อมูลลับ Gradle สำหรับ Android ในโปรเจ็กต์ Google Maps

  1. ใน Android Studio ให้เปิดไฟล์ build.gradle.kts หรือ build.gradle ระดับบนสุด แล้วเพิ่มโค้ดต่อไปนี้ลงในองค์ประกอบ dependencies ภายใน buildscript

หากใช้ build.gradle.kts ให้เพิ่มข้อมูลต่อไปนี้

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

หากใช้ build.gradle ให้เพิ่มข้อมูลต่อไปนี้

buildscript {
    dependencies {
        classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1"
    }
}
  1. เปิดไฟล์ build.gradle.kts หรือ build.gradle ระดับโมดูล แล้วเพิ่มโค้ดต่อไปนี้ลงในองค์ประกอบ plugins

หากใช้ build.gradle.kts ให้เพิ่มข้อมูลต่อไปนี้

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

หากใช้ build.gradle ให้เพิ่มข้อมูลต่อไปนี้

plugins {
    // ...
    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
}
  1. ในไฟล์ build.gradle.kts หรือ build.gradle ระดับโมดูล ให้ตรวจสอบว่าได้ตั้งค่า targetSdk และ compileSdk เป็น 34
  2. บันทึกไฟล์และซิงค์โปรเจ็กต์กับ Gradle
  3. เปิดไฟล์ secrets.properties ในไดเรกทอรีระดับบนสุด แล้วเพิ่มโค้ดต่อไปนี้ แทนที่ YOUR_API_KEY ด้วยคีย์ API ของคุณ จัดเก็บคีย์ไว้ในไฟล์นี้เนื่องจากระบบจะไม่ตรวจสอบ secrets.properties ในระบบควบคุมเวอร์ชัน
PLACES_API_KEY=YOUR_API_KEY
  1. บันทึกไฟล์
  2. สร้างไฟล์ local.defaults.properties ในไดเรกทอรีระดับบนสุด ซึ่งเป็นโฟลเดอร์เดียวกับไฟล์ secrets.properties แล้วเพิ่มโค้ดต่อไปนี้
PLACES_API_KEY=DEFAULT_API_KEY

จุดประสงค์ของไฟล์นี้คือการระบุตำแหน่งสำรองสำหรับคีย์ API ในกรณีที่ไม่พบไฟล์ secrets.properties เพื่อให้การสร้างไม่ล้มเหลว ปัญหานี้อาจเกิดขึ้นหากคุณโคลนแอปจากระบบควบคุมเวอร์ชันที่ละเว้น secrets.properties และคุณยังไม่ได้สร้างไฟล์ secrets.properties ในเครื่องเพื่อระบุคีย์ API

  1. บันทึกไฟล์
  2. ใน Android Studio ให้เปิดไฟล์ build.gradle.kts หรือ build.gradle ระดับโมดูล แล้วแก้ไขพร็อพเพอร์ตี้ secrets หากไม่มีพร็อพเพอร์ตี้ secrets ให้เพิ่ม

แก้ไขพร็อพเพอร์ตี้ของปลั๊กอินเพื่อตั้งค่า propertiesFileName เป็น secrets.properties ตั้งค่า defaultPropertiesFileName เป็น local.defaults.properties และตั้งค่าพร็อพเพอร์ตี้อื่นๆ

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. ติดตั้ง Places SDK สำหรับ Android

ในส่วนนี้ คุณจะเพิ่ม Places SDK สำหรับ Android ลงในการขึ้นต่อกันของแอป

  1. ตอนนี้คุณเข้าถึงคีย์ API ภายในแอปได้แล้ว ให้เพิ่มการอ้างอิง Places SDK สำหรับ Android ลงในไฟล์ build.gradle ของแอป

แก้ไขไฟล์ build.gradle ระดับแอปเพื่อเพิ่มทรัพยากร Dependency สำหรับ Places SDK สำหรับ Android ดังนี้

build.gradle ระดับแอป

dependencies {
   // Dependency to include Places SDK for Android
   implementation 'com.google.android.libraries.places:places:3.4.0'
}
  1. เรียกใช้แอป

ตอนนี้คุณควรเห็นแอปที่มีหน้าจอว่างเปล่า ดำเนินการป้อนข้อมูลในหน้าจอนี้ด้วยการสาธิต 3 รายการต่อไป

6. ติดตั้ง Places Android KTX

สำหรับแอป Kotlin ที่ใช้ Google Maps Platform Android SDK อย่างน้อย 1 รายการ ไลบรารีส่วนขยาย Kotlin (KTX) จะช่วยให้คุณใช้ประโยชน์จากฟีเจอร์ภาษา Kotlin ได้ เช่น Coroutine, พร็อพเพอร์ตี้/ฟังก์ชันส่วนขยาย และอื่นๆ Google Maps SDK แต่ละรายการมีไลบรารี KTX ที่เกี่ยวข้องดังที่แสดงด้านล่าง

แผนภาพ KTX ของ Google Maps Platform

ในงานนี้ ให้ใช้ไลบรารี Places Android KTX เพื่อใช้ฟีเจอร์ภาษาเฉพาะของ Kotlin ในแอป

เพิ่มการอ้างอิง Places Android KTX

หากต้องการใช้ประโยชน์จากฟีเจอร์เฉพาะของ Kotlin ให้รวมไลบรารี KTX ที่เกี่ยวข้องสำหรับ SDK นี้ไว้ในไฟล์ build.gradle ระดับแอป

build.gradle

dependencies {
    // ...

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

7. เริ่มต้นไคลเอ็นต์ Places

เริ่มต้น Places SDK สำหรับขอบเขตแอปพลิเคชัน

ในไฟล์ DemoApplication.kt ของโฟลเดอร์ app/src/main/java/com/google/codelabs/maps/placesdemo ให้เริ่มต้นใช้งาน Places SDK สำหรับ Android วางบรรทัดด้านล่างที่ส่วนท้ายของฟังก์ชัน onCreate

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

เมื่อคุณสร้างแอป ปลั๊กอินข้อมูลลับ Gradle สำหรับ Android จะทำให้คีย์ API ในไฟล์ secrets.properties พร้อมใช้งานเป็น BuildConfig.PLACES_API_KEY

เพิ่มไฟล์แอปพลิเคชันลงในไฟล์ Manifest

เนื่องจากคุณได้ขยายเวลา Application ด้วย DemoApplication คุณจึงต้องอัปเดตไฟล์ Manifest เพิ่มพร็อพเพอร์ตี้ android:name ลงในองค์ประกอบ application ในไฟล์ AndroidManifest.xml ซึ่งอยู่ใน app/src/main

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

โค้ดนี้จะชี้ Manifest ของแอปพลิเคชันไปยังคลาส DemoApplication ในโฟลเดอร์ src/main/java/com/google/codelabs/maps/placesdemo/

8. ดึงข้อมูลรายละเอียดสถานที่

สร้างหน้าจอรายละเอียด

activity_details.xml ที่มี LinearLayout ว่างเปล่าจะอยู่ในโฟลเดอร์ app/src/main/res/layout/ ป้อนข้อมูลเลย์เอาต์เชิงเส้นโดยเพิ่มโค้ดต่อไปนี้ระหว่างเครื่องหมายวงเล็บ <LinearLayout>

    <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" />

โค้ดนี้จะเพิ่มช่องป้อนข้อความที่ผู้ใช้สามารถป้อนรหัสสถานที่หรือใช้ค่าเริ่มต้นที่ระบุ ปุ่มเพื่อเริ่มคำขอรายละเอียดสถานที่ และ TextView เพื่อแสดงข้อมูลจากการตอบกลับ ระบบจะกำหนดสตริงที่เชื่อมโยงให้คุณในไฟล์ src/main/res/values/strings.xml

สร้างกิจกรรมรายละเอียด

  1. สร้างDetailsActivity.ktในโฟลเดอร์ src/main/java/com/google/codelabs/maps/placesdemo/ แล้วเชื่อมโยงกับเลย์เอาต์ที่คุณเพิ่งสร้าง วางโค้ดนี้ลงในไฟล์
@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. สร้างไคลเอ็นต์ Places เพื่อใช้กับกิจกรรมนี้ วางโค้ดนี้หลังโค้ดเพื่อตรวจสอบคีย์ API ในฟังก์ชัน onCreate
        // Retrieve a PlacesClient (previously initialized - see DemoApplication)
        placesClient = Places.createClient(this)
  1. หลังจากตั้งค่าไคลเอ็นต์ Places แล้ว ให้แนบเครื่องมือฟังการคลิกกับปุ่ม วางโค้ดนี้หลังจากการสร้างไคลเอ็นต์ Places ในฟังก์ชัน onCreate
        // 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
            }
        }

โค้ดนี้จะดึงข้อมูลรหัสสถานที่ที่ป้อนในช่องป้อนข้อมูล กำหนดช่องที่จะขอสำหรับสถานที่ สร้าง FetchPlaceRequest เริ่มต้นงาน และรอฟังผลสำเร็จหรือล้มเหลว หากคำขอสำเร็จ ฟังก์ชันจะป้อนรายละเอียดที่ขอลงใน TextView

เพิ่มกิจกรรม Details ลงในไฟล์ Manifest

เพิ่มองค์ประกอบ <activity> สำหรับ DetailsActivity เป็นองค์ประกอบย่อยขององค์ประกอบ <application> ในไฟล์ AndroidManifest.xml ซึ่งอยู่ใน app/src/main

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

เพิ่มกิจกรรมรายละเอียดลงในเมนูการสาธิต

เรามีโมดูล Demo ที่ว่างเปล่าไว้แสดงรายการเดโมที่พร้อมใช้งานในหน้าจอหลัก ตอนนี้คุณได้สร้างกิจกรรมรายละเอียดสถานที่แล้ว ให้เพิ่มกิจกรรมลงในไฟล์ Demo.kt ในโฟลเดอร์ src/main/java/com/google/codelabs/maps/placesdemo/ ด้วยโค้ดนี้

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

โดยจะกำหนดสตริงที่เชื่อมโยงไว้ในไฟล์ src/main/res/values/strings.xml

ตรวจสอบ MainActivity.kt และสังเกตว่าโค้ดจะสร้าง ListView ที่เติมข้อมูลโดยการวนซ้ำเนื้อหาของโมดูล Demo หากผู้ใช้แตะรายการในลิสต์ Listener การคลิกจะเปิดกิจกรรมที่เกี่ยวข้อง

เรียกใช้แอป

  1. เรียกใช้แอป คราวนี้คุณควรเห็นรายการเดียวในรายการที่แสดงการสาธิตรายละเอียดสถานที่
  2. แตะข้อความรายละเอียดสถานที่ คุณควรเห็นมุมมองที่สร้างขึ้นพร้อมช่องป้อนข้อมูลและปุ่ม
  3. แตะปุ่ม "ดูรายละเอียด" หากใช้รหัสสถานที่เริ่มต้น คุณควรเห็นชื่อสถานที่ ที่อยู่ และพิกัดแผนที่ที่แสดง ดังที่แสดงในรูปที่ 1

กิจกรรมรายละเอียดสถานที่พร้อมการตอบกลับ

รูปที่ 1 กิจกรรมรายละเอียดสถานที่พร้อมคำตอบที่แสดง

9. เพิ่ม Place Autocomplete

สร้างหน้าจอเติมข้อความอัตโนมัติ

activity_autocomplete.xml เลย์เอาต์ที่มี LinearLayout ว่างเปล่าจะอยู่ในโฟลเดอร์ app/src/main/res/layout/ สร้างเลย์เอาต์เชิงเส้นโดยเพิ่มโค้ดนี้ระหว่างเครื่องหมายวงเล็บ <LinearLayout>

    <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" />

โค้ดนี้จะเพิ่มวิดเจ็ต AutocompleteSupportFragment และ TextView เพื่อแสดงข้อมูลจากการตอบกลับ โดยจะกำหนดสตริงที่เชื่อมโยงไว้ในไฟล์ src/main/res/values/strings.xml

สร้างกิจกรรมการเติมข้อความอัตโนมัติ

  1. สร้างไฟล์ AutocompleteActivity.kt ในโฟลเดอร์ src/main/java/com/google/codelabs/maps/placesdemo/ แล้วกำหนดด้วยโค้ดนี้
@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
    }
}

รหัสนี้จะเชื่อมโยงกิจกรรมกับมุมมองและ AutocompleteSupportFramgent ที่คุณกำหนดไว้ในไฟล์เลย์เอาต์

  1. จากนั้นกําหนดสิ่งที่จะเกิดขึ้นเมื่อผู้ใช้เลือกการคาดคะเนรายการใดรายการหนึ่งที่แสดงโดยการเติมข้อความอัตโนมัติของสถานที่ เพิ่มโค้ดนี้ที่ส่วนท้ายของฟังก์ชัน onCreate
        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()
                }
            }
        }

โค้ดนี้จะกำหนดช่องที่จะขอสำหรับสถานที่ ฟังเหตุการณ์การเลือกสถานที่ และฟังความสำเร็จหรือความล้มเหลว หากคำขอสำเร็จ ฟังก์ชันจะป้อนรายละเอียดสถานที่ลงใน TextView โปรดทราบว่าการเติมข้อความอัตโนมัติของสถานที่จะแสดงออบเจ็กต์ Place คุณจึงไม่จำเป็นต้องส่งคำขอรายละเอียดสถานที่แยกต่างหากเมื่อใช้เครื่องมือการเติมข้อความอัตโนมัติของสถานที่

เพิ่มกิจกรรมการเติมข้อความอัตโนมัติลงในไฟล์ Manifest

เพิ่มองค์ประกอบ <activity> สำหรับ AutocompleteActivity เป็นองค์ประกอบย่อยขององค์ประกอบ <application> ในไฟล์ AndroidManifest.xml ซึ่งอยู่ใน app/src/main

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

เพิ่มกิจกรรมการเติมข้อความอัตโนมัติลงในเมนูการสาธิต

เช่นเดียวกับก่อนหน้านี้ ให้เพิ่มการสาธิตการเติมข้อความอัตโนมัติของสถานที่ลงในหน้าจอหลักโดยต่อท้ายรายการในโมดูล Demo ตอนนี้คุณได้สร้างกิจกรรมการเติมข้อความอัตโนมัติของสถานที่แล้ว ให้เพิ่มกิจกรรมดังกล่าวลงในไฟล์ Demo.kt ในโฟลเดอร์ src/main/java/com/google/codelabs/maps/placesdemo/ วางโค้ดนี้หลังรายการ DETAILS_FRAGMENT_DEMO ทันที

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

โดยจะกำหนดสตริงที่เชื่อมโยงไว้ในไฟล์ src/main/res/values/strings.xml

เรียกใช้แอป

  1. เรียกใช้แอป คราวนี้คุณควรเห็น 2 รายการในรายการหน้าจอหลัก
  2. แตะแถวการเติมข้อความอัตโนมัติของสถานที่ คุณควรเห็นอินพุตการเติมข้อความอัตโนมัติของสถานที่ปรากฏขึ้นตามที่แสดงในรูปที่ 2
  3. เริ่มพิมพ์ชื่อสถานที่ ซึ่งอาจเป็นชื่อสถานประกอบการ ที่อยู่ หรือภูมิภาคทางภูมิศาสตร์ การคาดคะเนควรแสดงขึ้นขณะที่คุณพิมพ์
  4. เลือกการคาดการณ์รายการใดรายการหนึ่ง การคาดคะเนควรหายไป และตอนนี้ TextView ควรแสดงรายละเอียดเกี่ยวกับสถานที่ที่เลือกตามที่แสดงในรูปที่ 3

กิจกรรมการเติมข้อความอัตโนมัติหลังจากที่ผู้ใช้แตะช่องป้อนข้อมูล

รูปที่ 2 กิจกรรมการเติมข้อความอัตโนมัติหลังจากที่ผู้ใช้แตะช่องป้อนข้อมูล

ป้อนข้อความอัตโนมัติหลังจากที่ผู้ใช้พิมพ์และเลือก &quot;น้ำตกไนแอการา&quot;

รูปที่ 3 กิจกรรมการเติมข้อความอัตโนมัติที่แสดงรายละเอียดสถานที่หลังจากที่ผู้ใช้พิมพ์และเลือก "น้ำตกไนแอการา"

10. รับสถานที่ปัจจุบันของอุปกรณ์

สร้างหน้าจอสถานที่ปัจจุบัน

activity_current.xml ที่มี LinearLayout ว่างเปล่าจะอยู่ในโฟลเดอร์ app/src/main/res/layout/ ป้อนข้อมูลเลย์เอาต์เชิงเส้นโดยเพิ่มโค้ดต่อไปนี้ระหว่างเครื่องหมายวงเล็บ <LinearLayout>

    <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" />

สร้างกิจกรรมสถานที่ปัจจุบัน

  1. สร้างไฟล์ CurrentPlaceActivity.kt ในโฟลเดอร์ src/main/java/com/google/codelabs/maps/placesdemo/ แล้วกำหนดด้วยโค้ดนี้
@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()
        }
    }
}

โค้ดนี้จะเชื่อมโยงกิจกรรมกับมุมมองที่คุณกำหนดไว้ในไฟล์เลย์เอาต์ นอกจากนี้ ยังเพิ่ม Listener การคลิกไปยังปุ่มเพื่อเรียกฟังก์ชัน checkPermissionThenFindCurrentPlace เมื่อมีการคลิกปุ่ม

  1. กำหนด checkPermissionThenFindCurrentPlace() เพื่อตรวจสอบสิทธิ์เข้าถึงตำแหน่งแบบละเอียดและขอสิทธิ์หากยังไม่ได้รับ วางโค้ดนี้หลังฟังก์ชัน onCreate
    /**
     * 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 ของฟังก์ชัน checkPermissionThenFindCurrentPlace เรียกใช้ requestPermissions แอปจะแสดงกล่องโต้ตอบคำขอสิทธิ์ต่อผู้ใช้ หากผู้ใช้ใช้อุปกรณ์ที่ใช้ระบบปฏิบัติการต่ำกว่า Android 12 ผู้ใช้จะให้สิทธิ์เข้าถึงตำแหน่งที่แน่นอน (ละเอียด) ได้เท่านั้น หากผู้ใช้ใช้อุปกรณ์ที่ใช้ Android 12 ขึ้นไป ผู้ใช้จะมีตัวเลือกในการระบุตำแหน่งโดยประมาณ (หยาบ) แทนตำแหน่งที่แน่นอน (ละเอียด) ดังที่แสดงในรูปที่ 4

การขอสิทธิ์จากผู้ใช้ในอุปกรณ์ที่ใช้ Android 12 ขึ้นไป

รูปที่ 4 การขอสิทธิ์จากผู้ใช้ในอุปกรณ์ที่ใช้ Android 12 ขึ้นไปจะแสดงตัวเลือกในการให้สิทธิ์เข้าถึงตำแหน่งที่แน่นอนหรือตำแหน่งโดยประมาณ

หลังจากผู้ใช้ตอบกลับกล่องโต้ตอบสิทธิ์ของระบบแล้ว ระบบจะเรียกใช้การติดตั้งใช้งาน onRequestPermissionsResult ของแอป ระบบจะส่งคำตอบของผู้ใช้ไปยังกล่องโต้ตอบการให้สิทธิ์ รวมถึงรหัสคำขอที่คุณกำหนด แทนที่ onRequestPermissionResult เพื่อจัดการรหัสคำขอสำหรับสิทธิ์เข้าถึงตำแหน่งที่เกี่ยวข้องกับกิจกรรมสถานที่ปัจจุบันนี้โดยวางโค้ดต่อไปนี้ใต้ 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. เมื่อได้รับสิทธิ์แล้ว ฟังก์ชัน findCurrentPlace จะทํางาน กำหนดฟังก์ชันด้วยโค้ดนี้หลังจากฟังก์ชัน onRequestPermissionsResult
    /**
     * 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()
        }
    }

โค้ดนี้จะกำหนดช่องที่จะขอสำหรับสถานที่ที่มีแนวโน้มว่าจะใช่ สร้าง FindCurrentPlaceRequest เริ่มงาน และป้อนข้อมูล TextView ด้วยรายละเอียดที่ขอ

เพิ่มกิจกรรมสถานที่ปัจจุบันลงในไฟล์ Manifest

เพิ่มองค์ประกอบ <activity> สำหรับ CurrentPlaceActivity เป็นองค์ประกอบย่อยขององค์ประกอบ <application> ในไฟล์ AndroidManifest.xml ซึ่งอยู่ใน app/src/main

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

เพิ่มกิจกรรมสถานที่ปัจจุบันลงในเมนูการสาธิต

เช่นเดียวกับก่อนหน้านี้ ให้เพิ่มเดโมสถานที่ปัจจุบันลงในหน้าจอหลักโดยต่อท้ายรายการในโมดูล Demo ตอนนี้คุณได้สร้างกิจกรรมสถานที่ปัจจุบันแล้ว ให้เพิ่มกิจกรรมดังกล่าวลงในไฟล์ Demo.kt ในโฟลเดอร์ src/main/java/com/google/codelabs/maps/placesdemo/ วางโค้ดนี้หลังรายการ AUTOCOMPLETE_FRAGMENT_DEMO ทันที

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

โดยจะกำหนดสตริงที่เชื่อมโยงไว้ในไฟล์ src/main/res/values/strings.xml

เรียกใช้แอป

  1. เรียกใช้แอป คราวนี้คุณควรเห็น 3 รายการในรายการหน้าจอหลัก
  2. แตะแถวสถานที่ปัจจุบัน คุณควรเห็นปุ่มบนหน้าจอ
  3. แตะปุ่ม หากคุณไม่เคยให้สิทธิ์เข้าถึงตำแหน่งแก่แอปนี้มาก่อน คำขอสิทธิ์ควรปรากฏขึ้น
  4. ให้สิทธิ์แอปในการเข้าถึงตำแหน่งของอุปกรณ์
  5. แตะปุ่มอีกครั้ง คราวนี้ รายการสถานที่ใกล้เคียงสูงสุด 20 แห่งและความน่าจะเป็นของแต่ละแห่งควรปรากฏขึ้น ดังที่แสดงในรูปที่ 5

แสดงสถานที่ปัจจุบันที่น่าจะเป็นไปได้สำหรับตำแหน่งที่อุปกรณ์รายงาน

รูปที่ 5 แสดงสถานที่ปัจจุบันที่น่าจะเป็นไปได้สำหรับตำแหน่งที่รายงานของอุปกรณ์

11. แสดงสถานที่ปัจจุบันบนแผนที่

เพิ่มการอ้างอิง Maps

ในไฟล์ build.gradle ระดับโมดูล ให้เพิ่มทรัพยากร Dependency ของบริการ Google Play สำหรับ Maps SDK สำหรับ Android

app/build.gradle

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

อัปเดตไฟล์ Manifest ของ Android เพื่อรองรับแผนที่

เพิ่มองค์ประกอบ meta-data ต่อไปนี้ภายในองค์ประกอบ application

ซึ่งจะฝังเวอร์ชันของบริการ Google Play ที่ใช้คอมไพล์แอปและระบุคีย์ API ของคุณ

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 ลงใน secrets.properties

เปิดไฟล์ secrets.properties ในไดเรกทอรีระดับบนสุด แล้วเพิ่มโค้ดต่อไปนี้ แทนที่ YOUR_API_KEY ด้วยคีย์ API ของคุณ

MAPS_API_KEY=YOUR_API_KEY

เปิดไฟล์ local.defaults.properties ในไดเรกทอรีระดับบนสุด ซึ่งเป็นโฟลเดอร์เดียวกับไฟล์ secrets.properties แล้วเพิ่มโค้ดต่อไปนี้

MAPS_API_KEY=DEFAULT_API_KEY

ตรวจสอบคีย์ API

ใน onCreate() แอปจะตรวจสอบคีย์ API ของ Maps และเริ่มต้น Fragment การรองรับแผนที่ getMapAsync() ใช้เพื่อลงทะเบียนการโทรกลับของแผนที่

เพิ่มโค้ดต่อไปนี้เพื่อดำเนินการนี้

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)

        // ...
    }

สร้างเลย์เอาต์แผนที่

  1. ในโฟลเดอร์ app/src/main/res/layout/ ให้สร้างไฟล์เลย์เอาต์ fragment_map.xml แล้วป้อนโค้ดต่อไปนี้ลงในเลย์เอาต์

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" />

ซึ่งจะกำหนดให้ SupportMapFragment ทำหน้าที่เป็นคอนเทนเนอร์สำหรับแผนที่และให้สิทธิ์เข้าถึงออบเจ็กต์ GoogleMap

  1. ในเลย์เอาต์ activity_current.xml ที่อยู่ในโฟลเดอร์ app/src/main/res/layout/ ให้เพิ่มโค้ดต่อไปนี้ที่ด้านล่างของเลย์เอาต์เชิงเส้น

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"/>

TextView ที่เพิ่มเข้ามาอ้างอิงถึงทรัพยากรสตริงใหม่ที่ต้องสร้าง

  1. ใน app/src/main/res/values/strings.xml ให้เพิ่มทรัพยากรสตริงต่อไปนี้

res/values/strings.xml

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

เนื่องจากมีการเพิ่มมุมมองเพิ่มเติมสำหรับแผนที่ TextView ที่แสดงรายการสถานที่จึงต้องตั้งค่าความสูงเพื่อให้มุมมองเหล่านี้ยังคงมองเห็นได้

  1. เพิ่มแอตทริบิวต์ maxHeight ลงใน TextView ที่มีรหัส current_response_content

res/layout/activity_current.xml

android:maxHeight="200dp"

ใช้ OnMapReadyCallback

ใช้OnMapReadyCallbackอินเทอร์เฟซโดยเพิ่มลงในการประกาศคลาส และแทนที่เมธอด onMapReady() เพื่อตั้งค่าแผนที่เมื่อมีออบเจ็กต์ GoogleMap

CurrentPlaceActivity.kt

class CurrentPlaceActivity : AppCompatActivity(), OnMapReadyCallback {

ที่ส่วนท้ายของคลาส ให้เพิ่มโค้ดต่อไปนี้

CurrentPlaceActivity.kt

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

Callback ต้องใช้ตัวแปรคลาสบางรายการจึงจะทำงานได้อย่างถูกต้อง เพิ่มข้อมูลต่อไปนี้ทันทีหลังจากส่วนหัวของคลาส

CurrentPlaceActivity.kt

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

เพิ่มโค้ดต่อไปนี้ลงในออบเจ็กต์คู่ของคลาส

CurrentPlaceActivity.kt

private const val DEFAULT_ZOOM = 15f

เรียกใช้แอป

  1. เรียกใช้แอป
  2. แตะแถวสถานที่ปัจจุบัน คุณควรเห็นปุ่มบนหน้าจอ
  3. แตะปุ่ม หากคุณไม่เคยให้สิทธิ์เข้าถึงตำแหน่งแก่แอปนี้มาก่อน คำขอสิทธิ์ควรปรากฏขึ้น
  4. ให้สิทธิ์แอปในการเข้าถึงตำแหน่งของอุปกรณ์
  5. แตะปุ่มอีกครั้ง แผนที่จะแสดงขึ้น

กิจกรรมสถานที่ปัจจุบันที่แสดงแผนที่

รูปที่ 6 กิจกรรมสถานที่ปัจจุบันที่แสดงแผนที่

อัปเดตแผนที่ด้วยสถานที่

ที่ส่วนท้ายของคลาส ให้เพิ่มโค้ดต่อไปนี้

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
    }
}

ซึ่งใช้เพื่อจัดเก็บและจัดรูปแบบข้อมูลของสถานที่

ที่จุดเริ่มต้นของคลาส ให้เพิ่มโค้ดต่อไปนี้เพื่อสร้างตัวแปรที่ใช้จัดเก็บข้อมูลของสถานที่ที่ส่งคืน

CurrentPlaceActivity.kt

private val likelyPlaces = mutableListOf<LikelyPlace>()

ในขั้นตอนนี้ ระบบจะเปลี่ยนโค้ดเพื่อให้ผู้ใช้เห็นรายการสถานที่และเลือกสถานที่ที่จะแสดงบนแผนที่ ข้อมูลสถานที่ทั้งหมดจะแสดงในรายการบนหน้าจอ

ในฟังก์ชัน findCurrentPlace ในบล็อก lifecycleScope.launch ก่อนบรรทัดโค้ดนี้

CurrentPlaceActivity.kt

responseView.text = response.prettyPrint()

เพิ่มโค้ดต่อไปนี้

CurrentPlaceActivity.kt

                likelyPlaces.clear()

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

                openPlacesDialog()

โค้ดนี้ต้องใช้ค่าคงที่สำหรับจำนวนสถานที่สูงสุดที่จะแสดง

เพิ่มโค้ดสำหรับค่าคงที่นั้นในออบเจ็กต์คู่

CurrentPlaceActivity.kt

private const val M_MAX_ENTRIES = 5

เพิ่มโค้ดต่อไปนี้ซึ่งจะสร้างกล่องโต้ตอบที่อนุญาตให้ผู้ใช้เลือกสถานที่

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 กล่องโต้ตอบจะอ้างอิงทรัพยากรสตริงซึ่งต้องเพิ่มลงในstrings.xmlไฟล์ทรัพยากรที่อยู่ในโฟลเดอร์ app/src/main/res/values/

เพิ่มรายการต่อไปนี้ไปยัง strings.xml

res/values/strings.xml

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

จากนั้นฟังก์ชันเหล่านี้จะเรียกใช้ฟังก์ชัน setPlaceOnMap ซึ่งจะย้ายกล้องและวางเครื่องหมายไว้ที่ตำแหน่งที่เลือก

เพิ่มโค้ดต่อไปนี้

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)
        )
    }

นอกจากนี้ เราขอแนะนำให้บันทึกและกู้คืนสถานะของแผนที่ด้วย

หากต้องการบันทึกสถานะ ให้ลบล้างฟังก์ชัน onSaveInstanceState แล้วเพิ่มโค้ดต่อไปนี้

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)
    }

หากต้องการกู้คืนสถานะ ให้onCreateเพิ่มโค้ดต่อไปนี้หลังการเรียกใช้ setContentView

CurrentPlaceActivity.kt

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

การบันทึกและกู้คืนต้องใช้คีย์ ซึ่งเป็นค่าคงที่จากออบเจ็กต์เสริม

ในบล็อกออบเจ็กต์เสริม ให้เพิ่มข้อมูลต่อไปนี้

CurrentPlaceActivity.kt

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

เรียกใช้แอป

  1. เรียกใช้แอป
  2. แตะแถวสถานที่ปัจจุบัน คุณควรเห็นปุ่มบนหน้าจอ
  3. แตะปุ่ม หากคุณไม่เคยให้สิทธิ์เข้าถึงตำแหน่งแก่แอปนี้มาก่อน คำขอสิทธิ์ควรปรากฏขึ้น
  4. ให้สิทธิ์แอปในการเข้าถึงตำแหน่งของอุปกรณ์
  5. แตะปุ่มอีกครั้ง
  6. เลือกสถานที่โดยแตะสถานที่นั้น ระบบจะซูมแผนที่และจัดกึ่งกลางโดยมีเครื่องหมายวางอยู่ที่ตำแหน่งที่เลือก

แผนที่ที่มีเครื่องหมายระบุตำแหน่งที่เลือก

รูปที่ 7 แผนที่ที่มีเครื่องหมายที่ตำแหน่งที่เลือก

12. ขอแสดงความยินดี

คุณสร้างแอป Android ด้วย Places SDK สำหรับ Android ได้สำเร็จแล้ว

สิ่งที่คุณได้เรียนรู้

ขั้นตอนถัดไปคือ

  • สำรวจหรือ Fork ที่เก็บ GitHub ของตัวอย่างและเดโม android-places-demos เพื่อหาแรงบันดาลใจเพิ่มเติม
  • ดูKotlin Codelab เพิ่มเติมสำหรับการสร้างแอป Android ด้วย Google Maps Platform
  • ช่วยเราสร้างเนื้อหาที่เป็นประโยชน์ต่อคุณมากที่สุดโดยตอบคำถามต่อไปนี้

คุณอยากเห็น Codelab อื่นๆ แบบไหน

การแสดงข้อมูลเป็นภาพบนแผนที่ ข้อมูลเพิ่มเติมเกี่ยวกับการปรับแต่งรูปแบบของแผนที่ การสร้างการโต้ตอบ 3 มิติในแผนที่

หากไม่พบ Codelab ที่ต้องการ ขอได้โดยแจ้งปัญหาใหม่ที่นี่