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

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

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

แอปเดโมของสถานที่ต่างๆ

สิ่งที่ต้องมีก่อน

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

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

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

สิ่งที่ต้องมี

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

2. ตั้งค่า

สําหรับขั้นตอนการเปิดใช้ด้านล่าง ให้เปิดใช้ Places API

ตั้งค่า Google Maps Platform

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

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

  1. เปิดใช้ Google Maps Platform API และ 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.git

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

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

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

4. ติดตั้ง Places SDK สําหรับ Android

ในส่วนนี้ คุณจะได้เพิ่ม Places SDK สําหรับ Android ลงในทรัพยากร Dependency ของแอป

เพิ่มคีย์ API

ระบุคีย์ API ที่สร้างไว้ก่อนหน้านี้ในแอปเพื่อให้ Places SDK สําหรับ Android เชื่อมโยงคีย์กับแอปได้

  1. เปิดไฟล์ชื่อ local.properties ในไดเรกทอรีรากของโปรเจ็กต์ (ระดับเดียวกับ gradle.properties และ settings.gradle)
  2. กําหนดคีย์ใหม่ GOOGLE_MAPS_API_KEY โดยตั้งค่าของคีย์เป็นคีย์ API ที่คุณสร้าง

local.properties

GOOGLE_MAPS_API_KEY=YOUR_KEY_HERE

โปรดทราบว่า local.properties จะแสดงอยู่ในไฟล์ .gitignore ในที่เก็บ Git เนื่องจากคีย์ API ของคุณถือเป็นข้อมูลที่ละเอียดอ่อนและไม่ควรเช็คอินการควบคุมแหล่งที่มาหากเป็นไปได้

  1. จากนั้นหากต้องการเปิดเผยคีย์ API เพื่อให้ใช้ในแอปได้ ให้ใส่ปลั๊กอิน Secrets Gradle Plugin for Android ในไฟล์ build.gradle ของแอปที่อยู่ในไดเรกทอรี app/ และเพิ่มบรรทัดต่อไปนี้ภายในบล็อก plugins

build.gradle ระดับแอป

plugins {
    // ...
    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
}
  1. แก้ไขไฟล์ build.gradle ระดับโปรเจ็กต์เพื่อรวมคลาสพาธต่อไปนี้

build.gradle ระดับโปรเจ็กต์

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

ปลั๊กอินนี้ช่วยให้คีย์ที่กําหนดไว้ภายในไฟล์ local.properties ใช้เป็นตัวแปรบิลด์ในไฟล์ Manifest ของ Android และเป็นตัวแปรในคลาส BuildConfig ที่ Gradle สร้างขึ้นในเวลาบิลด์ การใช้ปลั๊กอินนี้จะนําโค้ด Boilerplate ที่ต้องใช้ในการอ่านพร็อพเพอร์ตี้ออกจาก local.properties เพื่อให้เข้าถึงได้ทั่วทั้งแอป

เพิ่มทรัพยากร Dependency ของ Places สําหรับ Android

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

ในโปรเจ็กต์เริ่มต้นที่มาพร้อมกับ Codelab นี้ เราได้เพิ่มทรัพยากร Dependency นี้ไว้แล้ว

build.gradle ระดับแอป

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

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

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

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

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

ในงานนี้ ให้ใช้ไลบรารี Android KTX ของ Places เพื่อใช้ฟีเจอร์ภาษาที่ต้องการของ Kotlin ในแอปของคุณ

เพิ่มทรัพยากร Dependency สําหรับ Places ใน KTX

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

build.gradle

dependencies {
    // ...

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

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

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

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

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

เมื่อคุณสร้างแอป Secrets Gradle Plugin for Android จะทําให้คีย์ API ในไฟล์ local.properties พร้อมใช้งานใน BuildConfig.GOOGLE_MAPS_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/

7. เรียกดูรายละเอียดสถานที่

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

เลย์เอาต์ 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/ และเชื่อมโยงเข้ากับเลย์เอาต์ที่คุณเพิ่งสร้าง วางโค้ดนี้ลงในไฟล์:
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)

    }
}
  1. สร้างไคลเอ็นต์ Places เพื่อใช้กับกิจกรรมนี้ วางโค้ดนี้หลังจากเพิ่มออบเจ็กต์ข้อมูลพร็อพเพอร์ตี้ในฟังก์ชัน onCreate
        // Retrieve a PlacesClient (previously initialized - see DemoApplication)
        placesClient = Places.createClient(this)
  1. หลังจากตั้งค่าไคลเอ็นต์ของ Places แล้ว ให้แนบ Listener การคลิกกับปุ่ม วางรหัสนี้หลังจากที่สร้างไคลเอ็นต์ Places ในฟังก์ชัน onCreate
        // Upon button click, fetch and display the Place Details
        detailsButton.setOnClickListener {
            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
                }
            }
        }

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

  1. แปลง FetchPlaceResponse เป็นข้อความโดยกําหนดฟังก์ชันส่วนขยาย เราได้ให้ไฟล์ StringUtil.kt ไว้เพื่อให้การแปลงการตอบกลับ SDK สถานที่เป็นสตริงที่มนุษย์อ่านได้ง่ายขึ้น

ในตอนท้ายของไฟล์ DetailsActivity.kt ให้กําหนดฟังก์ชันในการแปลงออบเจ็กต์การตอบกลับสถานที่เป็นสตริง

fun FetchPlaceResponse.prettyPrint(): String {
    return StringUtil.stringify(this, false)
}

เพิ่มกิจกรรมรายละเอียดลงในไฟล์ Manifest

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

        <activity android:name=".DetailsActivity" />

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

มีโมดูล 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 แล้วสังเกตว่ามีการสร้างรายการViewView ที่สร้างขึ้นโดยทําซ้ําผ่านเนื้อหาของโมดูล Demo หากผู้ใช้แตะรายการที่ต้องการในรายการ Listener การคลิกจะเปิดกิจกรรมที่เกี่ยวข้อง

เรียกใช้แอป

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

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

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

8. เพิ่มการเติมข้อความอัตโนมัติของสถานที่

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

เลย์เอาต์ 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/ และกําหนดด้วยโค้ดนี้
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:
        // Specify the types of place data to return.
        autocompleteFragment.setPlaceFields(listOf(Place.Field.NAME, Place.Field.ID, Place.Field.LAT_LNG, Place.Field.ADDRESS))

        // Listen to place selection events
        lifecycleScope.launchWhenCreated {
            autocompleteFragment.placeSelectionEvents().collect { event ->
                when (event) {
                    is PlaceSelectionSuccess -> {
                        val place = event.place
                        responseView.text = StringUtil.stringifyAutocompleteWidget(place, false)
                    }
                    is PlaceSelectionError -> Toast.makeText(
                        this@AutocompleteActivity,
                        "Failed to get place '${event.status.statusMessage}'",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }

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

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

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

        <activity android:name=".AutocompleteActivity" />

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

ให้เพิ่มการสาธิตการเติมข้อความอัตโนมัติเกี่ยวกับสถานที่ลงในหน้าจอหลักเช่นเดียวกับการเพิ่มลงในรายการในโมดูล 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 เติมข้อความอัตโนมัติหลังจากที่ผู้ใช้แตะช่องป้อนข้อมูล

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

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

9. รับตําแหน่งปัจจุบันของอุปกรณ์

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

เลย์เอาต์ 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. สร้างไฟล์ CurrentActivity.kt ในโฟลเดอร์ src/main/java/com/google/codelabs/maps/placesdemo/ และกําหนดด้วยโค้ดนี้
class CurrentPlaceActivity : AppCompatActivity() {
    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(
                        Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.ACCESS_COARSE_LOCATION
                    ),
                    PERMISSION_REQUEST_CODE
                )
            }
        }
    }

    companion object {
        private 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)

        // Use the builder to create a FindCurrentPlaceRequest.
        val request: FindCurrentPlaceRequest = FindCurrentPlaceRequest.newInstance(placeFields)

        // 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
            lifecycleScope.launch {
                try {
                    val response = placesClient.awaitFindCurrentPlace(placeFields)
                    responseView.text = response.prettyPrint()

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

        }
    }

โค้ดนี้จะกําหนดช่องที่ขอสถานที่ที่เป็นไปได้ สร้าง FindCurrentPlaceRequest เริ่มงาน และเติมข้อมูล TextView ด้วยรายละเอียดที่ขอ

  1. แปลง FindCurrentPlaceResponse เป็นข้อความโดยกําหนดฟังก์ชันส่วนขยาย เราได้ให้ไฟล์ StringUtil.kt ไว้เพื่อให้การแปลงการตอบกลับ SDK สถานที่เป็นสตริงที่มนุษย์อ่านได้ง่ายขึ้น

ในตอนท้ายของไฟล์ CurrentPlaceActivity.kt ให้กําหนดฟังก์ชันในการแปลงออบเจ็กต์การตอบกลับสถานที่ปัจจุบันเป็นสตริง

fun FindCurrentPlaceResponse.prettyPrint(): String {
    return StringUtil.stringify(this, false)
}

เพิ่มกิจกรรม Place ปัจจุบันลงในไฟล์ Manifest

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

        <activity android:name=".CurrentPlaceActivity" />

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

ให้เพิ่มการสาธิตสถานที่ปัจจุบันลงในหน้าจอหลักเช่นเดิมโดยต่อท้ายรายการในโมดูล 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. เรียกใช้แอป ครั้งนี้คุณจะเห็นสามรายการในรายการหน้าจอหลัก
  2. แตะแถวสถานที่ปัจจุบัน คุณจะเห็นปุ่มบนหน้าจอ
  3. แตะที่ปุ่ม หากคุณไม่เคยให้สิทธิ์เข้าถึงตําแหน่งแก่แอปนี้มาก่อน คําขอสิทธิ์จะปรากฏขึ้น
  4. อนุญาตให้แอปเข้าถึงตําแหน่งของอุปกรณ์
  5. แตะที่ปุ่มอีกครั้ง ในขณะนี้ รายการสถานที่ใกล้เคียงสูงสุด 20 แห่งและความเป็นไปได้ควรปรากฏในรูปที่ 5

แสดงสถานที่ตั้งปัจจุบันที่ตรงกันสําหรับสถานที่ที่รายงานของอุปกรณ์

รูปที่ 5 นําเสนอสถานที่ปัจจุบันที่ตรงกันสําหรับสถานที่ที่รายงานของอุปกรณ์

10. ยินดีด้วย

คุณสร้างแอป Android ด้วย Places SDK สําหรับ Android เรียบร้อยแล้ว

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

มีอะไรอีกบ้าง

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

คุณต้องการเห็น Codelab อื่นใดบ้าง

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

Codelab ที่คุณต้องการไม่อยู่ในรายการใช่ไหม ส่งคําขอเกี่ยวกับปัญหาใหม่ที่นี่