เกี่ยวกับ Codelab นี้
1 ก่อนที่คุณจะเริ่มต้น
Codelab นี้จะสอนวิธีผสานรวม Places SDK สําหรับ Android กับแอปของคุณ และใช้ฟีเจอร์ Places SDK แต่ละรายการ
สิ่งที่ต้องมีก่อน
- ความรู้เบื้องต้นเกี่ยวกับการพัฒนา Kotlin และ Android
สิ่งที่คุณจะได้เรียนรู้
- วิธีติดตั้ง Places SDK สําหรับ Android ด้วยส่วนขยาย Kotlin
- วิธีโหลดรายละเอียดสถานที่ของสถานที่ที่ต้องการ
- วิธีเพิ่มวิดเจ็ตการเติมข้อความอัตโนมัติลงในแอป
- วิธีโหลดสถานที่ปัจจุบันตามสถานที่ตั้งที่รายงานในปัจจุบันของอุปกรณ์
สิ่งที่ต้องมี
หากต้องการให้ Codelab นี้เสร็จสมบูรณ์ คุณจะต้องมีบัญชี บริการ และเครื่องมือต่อไปนี้
- บัญชี Google ที่เปิดใช้การเรียกเก็บเงิน
- Android Studio Bumblebee ขึ้นไป
- บริการ Google Play ที่ติดตั้งใน Android Studio
- อุปกรณ์ Android หรือโปรแกรมจําลอง Android ที่ใช้แพลตฟอร์ม Google APIs ที่ใช้ Android 8 ขึ้นไป (ดูขั้นตอนการติดตั้งเรียกใช้แอปในโปรแกรมจําลอง Android)
2 ตั้งค่า
สําหรับขั้นตอนการเปิดใช้ด้านล่าง ให้เปิดใช้ Places API
ตั้งค่า Google Maps Platform
หากยังไม่มีบัญชี Google Cloud Platform และโปรเจ็กต์ที่เปิดใช้การเรียกเก็บเงิน โปรดดูคู่มือการเริ่มต้นใช้งาน Google Maps Platform เพื่อสร้างบัญชีสําหรับการเรียกเก็บเงินและโปรเจ็กต์
- ใน Cloud Console ให้คลิกเมนูแบบเลื่อนลงของโปรเจ็กต์ แล้วเลือกโปรเจ็กต์ที่ต้องการใช้สําหรับ Codelab นี้
- เปิดใช้ Google Maps Platform API และ SDK ที่จําเป็นสําหรับ Codelab นี้ใน Google Cloud Marketplace โดยทําตามขั้นตอนในวิดีโอนี้หรือเอกสารนี้
- สร้างคีย์ API ในหน้าข้อมูลเข้าสู่ระบบของ Cloud Console คุณสามารถทําตามขั้นตอนในวิดีโอนี้หรือเอกสารนี้ คําขอทั้งหมดสําหรับ Google Maps Platform ต้องใช้คีย์ API
3 การเริ่มใช้งานอย่างง่าย
ดาวน์โหลดโค้ดเริ่มต้นเพื่อช่วยในการติดตาม Codelab นี้เพื่อช่วยให้คุณเริ่มต้นใช้งานได้อย่างรวดเร็วที่สุด คุณข้ามไปยังโซลูชันนี้ได้ แต่ถ้าต้องการปฏิบัติตามขั้นตอนทั้งหมดในการสร้างด้วยตัวเอง ให้อ่านต่อ
- โคลนที่เก็บหากคุณติดตั้ง
git
git clone https://github.com/googlemaps/codelab-places-101-android.git
หรือคลิกปุ่มนี้เพื่อดาวน์โหลดซอร์สโค้ด
- หลังจากดาวน์โหลดโค้ดแล้ว ให้เปิดโปรเจ็กต์ที่พบในไดเรกทอรี
/starter
ใน Android Studio โครงการนี้มีโครงสร้างไฟล์พื้นฐานที่จําเป็นให้เสร็จสิ้นใน Codelab ข้อมูลทั้งหมดที่คุณจําเป็นต้องใช้จะอยู่ในไดเรกทอรี/starter
หากต้องการดูโค้ดโซลูชันแบบเต็มที่เรียกใช้ คุณจะดูโค้ดที่สมบูรณ์ได้ในไดเรกทอรี /solution
4 ติดตั้ง Places SDK สําหรับ Android
ในส่วนนี้ คุณจะได้เพิ่ม Places SDK สําหรับ Android ลงในทรัพยากร Dependency ของแอป
เพิ่มคีย์ API
ระบุคีย์ API ที่สร้างไว้ก่อนหน้านี้ในแอปเพื่อให้ Places SDK สําหรับ Android เชื่อมโยงคีย์กับแอปได้
- เปิดไฟล์ชื่อ
local.properties
ในไดเรกทอรีรากของโปรเจ็กต์ (ระดับเดียวกับgradle.properties
และsettings.gradle
) - กําหนดคีย์ใหม่
GOOGLE_MAPS_API_KEY
โดยตั้งค่าของคีย์เป็นคีย์ API ที่คุณสร้าง
local.properties
GOOGLE_MAPS_API_KEY=YOUR_KEY_HERE
โปรดทราบว่า local.properties
จะแสดงอยู่ในไฟล์ .gitignore
ในที่เก็บ Git เนื่องจากคีย์ API ของคุณถือเป็นข้อมูลที่ละเอียดอ่อนและไม่ควรเช็คอินการควบคุมแหล่งที่มาหากเป็นไปได้
- จากนั้นหากต้องการเปิดเผยคีย์ API เพื่อให้ใช้ในแอปได้ ให้ใส่ปลั๊กอิน Secrets Gradle Plugin for Android ในไฟล์
build.gradle
ของแอปที่อยู่ในไดเรกทอรีapp/
และเพิ่มบรรทัดต่อไปนี้ภายในบล็อกplugins
build.gradle ระดับแอป
plugins {
// ...
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
}
- แก้ไขไฟล์
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
- ตอนนี้คุณเข้าถึงคีย์ 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'
}
- เรียกใช้แอป
คุณจะเห็นแอปที่มีหน้าจอว่างแล้ว เข้าสู่หน้าจอนี้โดยใช้การสาธิต 3 รายการต่อไป
5 ติดตั้ง Places Android KTX
สําหรับแอป Kotlin ที่ใช้ SDK สําหรับ Google Maps Platform บน Android อย่างน้อย 1 รายการ ไลบรารีส่วนขยาย Kotlin (KTX) ช่วยให้คุณใช้ประโยชน์จากฟีเจอร์ของภาษา Kotlin เช่น โครูทีน พร็อพเพอร์ตี้ส่วนขยาย/ฟังก์ชันของส่วนขยาย และอื่นๆ Google Maps SDK แต่ละรายการมีไลบรารี KTX ที่เกี่ยวข้องดังที่แสดงด้านล่าง
ในงานนี้ ให้ใช้ไลบรารี 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
สร้างกิจกรรมรายละเอียด
- สร้างไฟล์
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)
}
}
- สร้างไคลเอ็นต์ Places เพื่อใช้กับกิจกรรมนี้ วางโค้ดนี้หลังจากเพิ่มออบเจ็กต์ข้อมูลพร็อพเพอร์ตี้ในฟังก์ชัน
onCreate
// Retrieve a PlacesClient (previously initialized - see DemoApplication)
placesClient = Places.createClient(this)
- หลังจากตั้งค่าไคลเอ็นต์ของ 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
เริ่มงาน และฟังว่าสําเร็จหรือล้มเหลว หากคําขอประสบความสําเร็จ ฟังก์ชันจะเติมข้อความด้วยรายละเอียดที่ขอ
- แปลง
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 รายการในรายการที่แสดงการสาธิตรายละเอียดสถานที่
- แตะข้อความรายละเอียดสถานที่ คุณควรจะเห็นมุมมองที่คุณสร้างด้วยช่องป้อนข้อมูลและปุ่มป้อนข้อมูล
- แตะปุ่ม "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
สร้างกิจกรรมการเติมข้อความอัตโนมัติ
- สร้างไฟล์
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
ที่คุณกําหนดในไฟล์เลย์เอาต์
- จากนั้น ให้ระบุว่าจะเกิดอะไรขึ้นเมื่อผู้ใช้เลือกหนึ่งในการคาดคะเนที่แสดงโดยการเติมข้อความอัตโนมัติภายในสถานที่ เพิ่มโค้ดนี้ท้ายฟังก์ชัน
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
เรียกใช้แอป
- เรียกใช้แอป ครั้งนี้คุณจะเห็น 2 รายการในรายการหน้าจอหลัก
- แตะแถวการเติมข้อความอัตโนมัติของสถานที่ คุณควรเห็นป๊อปอัปอินพุตการเติมข้อความอัตโนมัติของสถานที่ดังที่แสดงในรูปที่ 2
- เริ่มพิมพ์ชื่อของสถานที่ โดยอาจเป็นชื่อสถานประกอบการ ที่อยู่ หรือภูมิภาคทางภูมิศาสตร์ก็ได้ การคาดคะเนควรแสดงขึ้นมาขณะที่คุณพิมพ์
- เลือกการคาดคะเนรายการใดรายการหนึ่ง การคาดคะเนควรหายไป และ TextView ควรแสดงรายละเอียดเกี่ยวกับสถานที่ที่เลือกดังที่แสดงในรูปที่ 3
รูปที่ 2 เติมข้อความอัตโนมัติหลังจากที่ผู้ใช้แตะช่องป้อนข้อมูล
รูปที่ 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" />
สร้างกิจกรรมของสถานที่ปัจจุบัน
- สร้างไฟล์
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
เมื่อมีการคลิกปุ่ม
- กําหนด
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
}
- เมื่อสาขา
else
ของฟังก์ชันcheckPermissionThenFindCurrentPlace
เรียกใช้requestPermissions
แอปจะแสดงกล่องโต้ตอบคําขอสิทธิ์แก่ผู้ใช้ หากผู้ใช้เรียกใช้อุปกรณ์ที่ใช้ระบบปฏิบัติการต่ํากว่า Android 12 ผู้ใช้จะให้สิทธิ์เข้าถึงตําแหน่งที่แน่นอน (ได้) เท่านั้น หากใช้อุปกรณ์ที่ใช้ Android 12 ขึ้นไป ผู้ใช้จะมีตัวเลือกในการระบุตําแหน่งโดยประมาณ (ระดับคร่าวๆ) แทนตําแหน่งที่แน่นอน (อย่างละเอียด) ดังที่แสดงในรูปที่ 4
รูปที่ 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()
}
- เมื่อได้รับสิทธิ์แล้ว ฟังก์ชัน
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 ด้วยรายละเอียดที่ขอ
- แปลง
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
เรียกใช้แอป
- เรียกใช้แอป ครั้งนี้คุณจะเห็นสามรายการในรายการหน้าจอหลัก
- แตะแถวสถานที่ปัจจุบัน คุณจะเห็นปุ่มบนหน้าจอ
- แตะที่ปุ่ม หากคุณไม่เคยให้สิทธิ์เข้าถึงตําแหน่งแก่แอปนี้มาก่อน คําขอสิทธิ์จะปรากฏขึ้น
- อนุญาตให้แอปเข้าถึงตําแหน่งของอุปกรณ์
- แตะที่ปุ่มอีกครั้ง ในขณะนี้ รายการสถานที่ใกล้เคียงสูงสุด 20 แห่งและความเป็นไปได้ควรปรากฏในรูปที่ 5
รูปที่ 5 นําเสนอสถานที่ปัจจุบันที่ตรงกันสําหรับสถานที่ที่รายงานของอุปกรณ์
10 ยินดีด้วย
คุณสร้างแอป Android ด้วย Places SDK สําหรับ Android เรียบร้อยแล้ว
สิ่งที่คุณได้เรียนรู้
- การติดตั้งและการกําหนดค่า Places SDK สําหรับ Android
- การติดตั้งส่วนขยาย Kotlin สําหรับ Places SDK สําหรับ Android
- กําลังโหลดรายละเอียดสถานที่
- กําลังเพิ่มเติมข้อความอัตโนมัติลงในสถานที่
- กําลังรับข้อมูลสถานที่ปัจจุบัน
มีอะไรอีกบ้าง
- สํารวจหรือแยกที่เก็บข้อมูล GitHub ของตัวอย่างและการสาธิตของ
android-places-demos
เพื่อเป็นแรงบันดาลใจเพิ่มเติม - เรียนรู้จาก Kotlin Codelabs เพิ่มเติมสําหรับการสร้างแอป Android ด้วย Google Maps Platform
- ช่วยเราสร้างเนื้อหาที่คุณคิดว่าเป็นประโยชน์ที่สุดโดยตอบคําถามต่อไปนี้
คุณต้องการเห็น Codelab อื่นใดบ้าง
Codelab ที่คุณต้องการไม่อยู่ในรายการใช่ไหม ส่งคําขอเกี่ยวกับปัญหาใหม่ที่นี่