Codelab นี้เป็นส่วนหนึ่งของหลักสูตร Android ขั้นสูงใน Kotlin คุณจะได้รับประโยชน์สูงสุดจากหลักสูตรนี้หากทำตาม Codelab ตามลำดับ แต่ไม่จำเป็นต้องทำ Codelab ของหลักสูตรทั้งหมดแสดงอยู่ในหน้า Landing Page ของ Codelab Android ขั้นสูงใน Kotlin
การสร้างแอปด้วย Google Maps ช่วยให้คุณเพิ่มฟีเจอร์ต่างๆ ลงในแอปได้ เช่น ภาพถ่ายดาวเทียม การควบคุม UI ที่มีประสิทธิภาพสำหรับแผนที่ การติดตามตำแหน่ง และเครื่องหมายตำแหน่ง คุณเพิ่มคุณค่าให้กับ Google Maps มาตรฐานได้โดยการแสดงข้อมูลจากชุดข้อมูลของคุณเอง เช่น สถานที่ตั้งของพื้นที่ตกปลาหรือปีนเขาที่มีชื่อเสียง นอกจากนี้ คุณยังสร้างเกมที่ผู้เล่นสำรวจโลกจริงได้ด้วย เช่น เกมล่าขุมทรัพย์หรือแม้แต่เกมความเป็นจริงเสริม
ในบทเรียนนี้ คุณจะได้สร้างแอป Google Maps ชื่อ Wander ซึ่งจะแสดงแผนที่ที่ปรับแต่งแล้วและแสดงตำแหน่งของผู้ใช้
ข้อกำหนดเบื้องต้น
ความรู้เกี่ยวกับสิ่งต่อไปนี้
- วิธีสร้างแอป Android พื้นฐานและเรียกใช้โดยใช้ Android Studio
- วิธีสร้างและจัดการทรัพยากร เช่น สตริง
- วิธีปรับโครงสร้างโค้ดและเปลี่ยนชื่อตัวแปรโดยใช้ Android Studio
- วิธีใช้แผนที่ Google ในฐานะผู้ใช้
- วิธีตั้งค่าสิทธิ์รันไทม์
สิ่งที่คุณจะได้เรียนรู้
- วิธีรับคีย์ API จาก Google API Console และลงทะเบียนคีย์กับแอป
- วิธีผสานรวม Google Maps ในแอป
- วิธีแสดงแผนที่ประเภทต่างๆ
- วิธีจัดรูปแบบ Google Map
- วิธีเพิ่มเครื่องหมายลงในแผนที่
- วิธีเปิดใช้เพื่อให้ผู้ใช้ปักหมุดในจุดที่น่าสนใจ (POI)
- วิธีเปิดใช้การติดตามตำแหน่ง
- วิธีสร้างแอป
Wander
ซึ่งมี Google Maps แบบฝัง - วิธีสร้างฟีเจอร์ที่กำหนดเองสำหรับแอป เช่น เครื่องหมายและการจัดรูปแบบ
- วิธีเปิดใช้การติดตามตำแหน่งในแอป
ในโค้ดแล็บนี้ คุณจะสร้างแอป Wander
ซึ่งแสดงแผนที่ Google ที่มีการจัดรูปแบบที่กำหนดเอง แอป Wander ช่วยให้คุณวางเครื่องหมายบนสถานที่ เพิ่มภาพซ้อนทับ และดูตำแหน่งของคุณแบบเรียลไทม์ได้
Maps SDK สำหรับ Android ต้องใช้คีย์ API หากต้องการรับคีย์ API ให้ลงทะเบียนโปรเจ็กต์ในหน้า API และบริการ คีย์ API จะเชื่อมโยงกับใบรับรองดิจิทัลที่ลิงก์แอปกับผู้เขียน ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ใบรับรองดิจิทัลและการลงนามในแอปได้ที่ลงนามในแอป
ในโค้ดแล็บนี้ คุณจะใช้คีย์ API สำหรับใบรับรองการแก้ไขข้อบกพร่อง ใบรับรองการแก้ไขข้อบกพร่องไม่ปลอดภัยตามการออกแบบ ดังที่อธิบายไว้ในลงนามในบิลด์การแก้ไขข้อบกพร่อง แอป Android ที่เผยแพร่แล้วซึ่งใช้ Maps SDK สำหรับ Android จะต้องมีคีย์ API ที่ 2 ซึ่งเป็นคีย์สำหรับใบรับรองการเผยแพร่ ดูข้อมูลเพิ่มเติมเกี่ยวกับการขอรับใบรับรองรุ่นได้ที่รับคีย์ API
Android Studio มีเทมเพลตกิจกรรม Google Maps ซึ่งสร้างโค้ดเทมเพลตที่เป็นประโยชน์ โค้ดเทมเพลตมีไฟล์ google_maps_api.xml ซึ่งมีลิงก์ที่ช่วยให้รับคีย์ API ได้ง่ายขึ้น
ขั้นตอนที่ 1: สร้างโปรเจ็กต์ Wander ด้วยเทมเพลตแผนที่
- สร้างโปรเจ็กต์ Android Studio ใหม่
- เลือกเทมเพลตกิจกรรมใน Google Maps
- ตั้งชื่อโปรเจ็กต์
Wander
- ตั้งค่าระดับ API ขั้นต่ำเป็น API 19 ตรวจสอบว่าภาษาเป็น Kotlin
- คลิกเสร็จสิ้น
- เมื่อสร้างแอปเสร็จแล้ว ให้ดูโปรเจ็กต์และไฟล์ที่เกี่ยวข้องกับแผนที่ต่อไปนี้ที่ Android Studio สร้างให้คุณ
google_maps_api.xml - คุณใช้ไฟล์การกำหนดค่านี้เพื่อจัดเก็บคีย์ API เทมเพลตจะสร้างไฟล์ google_maps_api.xml 2 ไฟล์ ได้แก่ ไฟล์สําหรับการแก้ไขข้อบกพร่องและไฟล์สําหรับการเผยแพร่ ไฟล์สำหรับคีย์ API ของใบรับรองการแก้ไขข้อบกพร่องจะอยู่ใน src/debug/res/values ไฟล์สำหรับคีย์ API สำหรับใบรับรองการเผยแพร่อยู่ใน src/release/res/values ใน Codelab นี้ คุณจะใช้เฉพาะใบรับรองการแก้ไขข้อบกพร่อง
activity_maps.xml - ไฟล์เลย์เอาต์นี้มี Fragment เดียวที่ครอบคลุมทั้งหน้าจอ คลาส SupportMapFragment
เป็นคลาสย่อยของคลาส Fragment
SupportMapFragment
เป็นวิธีที่ง่ายที่สุดในการวางแผนที่ในแอป โดยเป็น Wrapper รอบมุมมองของแผนที่เพื่อจัดการความต้องการด้านวงจรของแอปที่จำเป็นโดยอัตโนมัติ
คุณใส่ SupportMapFragment
ในไฟล์เลย์เอาต์ได้โดยใช้แท็ก <fragment>
ใน ViewGroup
ใดก็ได้ พร้อมด้วยแอตทริบิวต์ name
เพิ่มเติม
android:name="com.google.android.gms.maps.SupportMapFragment"
MapsActivity.java - ไฟล์ MapsActivity.kt จะสร้างอินสแตนซ์ของ SupportMapFragment
ในเมธอด onCreate()
และใช้ getMapAsync
()
ของคลาสเพื่อเริ่มต้นระบบแผนที่และมุมมองโดยอัตโนมัติ กิจกรรมที่มี SupportMapFragment
ต้องใช้ OnMapReadyCallback
อินเทอร์เฟซและเมธอด onMapReady()
ของอินเทอร์เฟซนั้น ระบบจะเรียกใช้เมธอด onMapReady()
เมื่อโหลดแผนที่
ขั้นตอนที่ 2: รับคีย์ API
- เปิดไฟล์ google_maps_api.xml เวอร์ชันแก้ไขข้อบกพร่อง
- ในไฟล์ ให้มองหาความคิดเห็นที่มี URL ยาว พารามิเตอร์ของ URL มีข้อมูลเฉพาะเกี่ยวกับแอปของคุณ
- คัดลอกและวาง URL ลงในเบราว์เซอร์
- ทำตามข้อความแจ้งเพื่อสร้างโปรเจ็กต์ในหน้า API และบริการ เนื่องจากพารามิเตอร์ใน URL ที่ระบุ หน้าเว็บจึงทราบว่าต้องเปิดใช้ Maps SDK สำหรับ Android โดยอัตโนมัติ
- คลิกสร้างคีย์ API
- ในหน้าถัดไป ให้ไปที่ส่วนคีย์ API แล้วคลิกคีย์ที่คุณเพิ่งสร้าง
- คลิกจำกัดคีย์ แล้วเลือก Maps SDK สำหรับ Android เพื่อจำกัดการใช้คีย์ไว้เฉพาะแอป Android
- คัดลอกคีย์ API ที่สร้างขึ้น โดยจะขึ้นต้นด้วย "
AIza"
- ใน
google_maps_api.xml
ให้วางคีย์ลงในสตริงgoogle_maps_key
ที่มีข้อความYOUR_KEY_HERE
- เรียกใช้แอป คุณควรเห็นแผนที่ฝังในกิจกรรมโดยมีเครื่องหมายที่ตั้งอยู่ในซิดนีย์ ออสเตรเลีย (เครื่องหมายซิดนีย์เป็นส่วนหนึ่งของเทมเพลตและคุณจะเปลี่ยนได้ในภายหลัง)
ขั้นตอนที่ 3: เปลี่ยนชื่อ mMap
MapsActivity
มี lateinit
var
แบบส่วนตัวชื่อ mMap
ซึ่งมีประเภทเป็น GoogleMap
หากต้องการทำตามรูปแบบการตั้งชื่อของ Kotlin ให้เปลี่ยนชื่อ mMap
เป็น map
- ใน
MapsActivity
ให้คลิกขวาที่mMap
แล้วคลิกปรับโครงสร้าง> เปลี่ยนชื่อ...
- เปลี่ยนชื่อตัวแปรเป็น
map
โปรดสังเกตว่าการอ้างอิงทั้งหมดถึง mMap
ในฟังก์ชัน onMapReady()
จะเปลี่ยนเป็น map
ด้วย
Google Maps มีแผนที่หลายประเภท ได้แก่ ปกติ ไฮบริด ดาวเทียม ภูมิประเทศ และ "ไม่มี" (สำหรับไม่มีแผนที่เลย)
แผนที่ปกติ | แผนที่ดาวเทียม | แผนที่ไฮบริด | แผนที่ภูมิประเทศ |
แผนที่แต่ละประเภทจะให้ข้อมูลที่แตกต่างกัน เช่น เมื่อใช้ Maps เพื่อการนำทางในรถยนต์ การเห็นชื่อถนนจะเป็นประโยชน์ ดังนั้นคุณจึงอาจใช้ตัวเลือกปกติ เมื่อเดินป่า แผนที่ภูมิประเทศอาจช่วยให้คุณตัดสินใจได้ว่าต้องปีนขึ้นไปอีกเท่าใดจึงจะถึงยอดเขา
ในงานนี้ คุณจะต้องทำสิ่งต่อไปนี้
- เพิ่มแถบแอปที่มีเมนูตัวเลือกซึ่งช่วยให้ผู้ใช้เปลี่ยนประเภทแผนที่ได้
- ย้ายตำแหน่งเริ่มต้นของแผนที่ไปยังตำแหน่งบ้านของคุณ
- เพิ่มการรองรับเครื่องหมาย ซึ่งระบุตำแหน่งเดียวบนแผนที่และอาจมีป้ายกำกับ
เพิ่มเมนูสำหรับประเภทแผนที่
ในขั้นตอนนี้ คุณจะเพิ่มแถบแอปที่มีเมนูตัวเลือกซึ่งช่วยให้ผู้ใช้เปลี่ยนประเภทแผนที่ได้
- หากต้องการสร้างไฟล์ XML ของเมนูใหม่ ให้คลิกขวาที่ไดเรกทอรี res แล้วเลือกใหม่> ไฟล์ทรัพยากร Android
- ในกล่องโต้ตอบ ให้ตั้งชื่อไฟล์
map_options
- เลือก Menu สำหรับประเภททรัพยากร
- คลิกตกลง
- ในแท็บโค้ด ให้แทนที่โค้ดในไฟล์ใหม่ด้วยโค้ดต่อไปนี้เพื่อสร้างตัวเลือกเมนูแผนที่ ระบบละเว้นประเภทแผนที่ "ไม่มี" เนื่องจาก "ไม่มี" จะส่งผลให้ไม่มีแผนที่เลย ขั้นตอนนี้จะทำให้เกิดข้อผิดพลาด แต่คุณจะแก้ไขได้ในขั้นตอนถัดไป
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/normal_map"
android:title="@string/normal_map"
app:showAsAction="never" />
<item
android:id="@+id/hybrid_map"
android:title="@string/hybrid_map"
app:showAsAction="never" />
<item
android:id="@+id/satellite_map"
android:title="@string/satellite_map"
app:showAsAction="never" />
<item
android:id="@+id/terrain_map"
android:title="@string/terrain_map"
app:showAsAction="never" />
</menu>
- ใน
strings.xml
ให้เพิ่มแหล่งข้อมูลสำหรับแอตทริบิวต์title
เพื่อแก้ไขข้อผิดพลาด
<resources>
...
<string name="normal_map">Normal Map</string>
<string name="hybrid_map">Hybrid Map</string>
<string name="satellite_map">Satellite Map</string>
<string name="terrain_map">Terrain Map</string>
<string name="lat_long_snippet">Lat: %1$.5f, Long: %2$.5f</string>
<string name="dropped_pin">Dropped Pin</string>
<string name="poi">poi</string>
</resources>
- ใน
MapsActivity
ให้ลบล้างเมธอดonCreateOptionsMenu()
และขยายเมนูจากไฟล์ทรัพยากรmap_options
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.map_options, menu)
return true
}
- ใน
MapsActivity.kt
ให้ลบล้างวิธีการonOptionsItemSelected()
เปลี่ยนประเภทแผนที่โดยใช้ค่าคงที่ของประเภทแผนที่เพื่อให้สอดคล้องกับการเลือกของผู้ใช้
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
// Change the map type based on the user's selection.
R.id.normal_map -> {
map.mapType = GoogleMap.MAP_TYPE_NORMAL
true
}
R.id.hybrid_map -> {
map.mapType = GoogleMap.MAP_TYPE_HYBRID
true
}
R.id.satellite_map -> {
map.mapType = GoogleMap.MAP_TYPE_SATELLITE
true
}
R.id.terrain_map -> {
map.mapType = GoogleMap.MAP_TYPE_TERRAIN
true
}
else -> super.onOptionsItemSelected(item)
}
- เรียกใช้แอป
- คลิก
เพื่อเปลี่ยนประเภทแผนที่ สังเกตว่าลักษณะที่ปรากฏของแผนที่เปลี่ยนแปลงไปอย่างไรในโหมดต่างๆ
โดยค่าเริ่มต้น onMapReady()
การเรียกกลับจะมีโค้ดที่วางเครื่องหมายในซิดนีย์ ออสเตรเลีย ซึ่งเป็นที่ที่สร้าง Google Maps การเรียกกลับเริ่มต้นจะทำให้แผนที่เคลื่อนไหวเพื่อเลื่อนไปยังซิดนีย์ด้วย
ในงานนี้ คุณจะทำให้กล้องของแผนที่เคลื่อนไปยังบ้าน ซูมไปยังระดับที่คุณระบุ และวางเครื่องหมายไว้ที่นั่น
ขั้นตอนที่ 1: ซูมไปที่บ้านและเพิ่มเครื่องหมาย
- ในไฟล์
MapsActivity.kt
ให้ค้นหาวิธีonMapReady()
นำโค้ดที่วางเครื่องหมายในซิดนีย์และย้ายกล้องออก ตอนนี้เมธอดของคุณควรมีลักษณะดังนี้
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
}
- ค้นหาละติจูดและลองจิจูดของบ้านโดยทำตามวิธีการเหล่านี้
- สร้างค่าสำหรับละติจูดและค่าสำหรับลองจิจูด แล้วป้อนค่าลอยตัวของค่าเหล่านั้น
val latitude = 37.422160
val longitude = -122.084270
- สร้างออบเจ็กต์
LatLng
ใหม่ชื่อhomeLatLng
ในhomeLatLng
ออบเจ็กต์ ให้ส่งค่าที่คุณเพิ่งสร้าง
val homeLatLng = LatLng(latitude, longitude)
- สร้าง
val
สำหรับระดับการซูมที่คุณต้องการในแผนที่ ใช้ระดับการซูม 15f
val zoomLevel = 15f
ระดับการซูมจะควบคุมระดับการซูมเข้าบนแผนที่ รายการต่อไปนี้จะช่วยให้คุณทราบถึงระดับรายละเอียดที่แต่ละระดับการซูมแสดง
1
: โลก5
: ผืนดินขนาดใหญ่/ทวีป10
: เมือง15
: ถนน20
: อาคาร
- ย้ายกล้องไปที่
homeLatLng
โดยเรียกใช้ฟังก์ชันmoveCamera()
ในออบเจ็กต์map
และส่งออบเจ็กต์CameraUpdate
โดยใช้CameraUpdateFactory.newLatLngZoom()
ส่งออบเจ็กต์homeLatLng
และzoomLevel
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
- เพิ่มเครื่องหมายลงในแผนที่ที่
homeLatLng
map.addMarker(MarkerOptions().position(homeLatLng))
วิธีสุดท้ายควรมีลักษณะดังนี้
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
//These coordinates represent the latitude and longitude of the Googleplex.
val latitude = 37.422160
val longitude = -122.084270
val zoomLevel = 15f
val homeLatLng = LatLng(latitude, longitude)
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
map.addMarker(MarkerOptions().position(homeLatLng))
}
- เรียกใช้แอป แผนที่ควรเลื่อนไปยังบ้าน ซูมไปยังระดับที่ต้องการ และวางเครื่องหมายบนบ้าน
ขั้นตอนที่ 2: อนุญาตให้ผู้ใช้เพิ่มเครื่องหมายโดยใช้การคลิกแบบยาว
ในขั้นตอนนี้ คุณจะเพิ่มเครื่องหมายเมื่อผู้ใช้แตะตำแหน่งบนแผนที่ค้างไว้
- สร้าง Stub ของเมธอดใน
MapsActivity
ชื่อsetMapLongClick()
ซึ่งรับGoogleMap
เป็นอาร์กิวเมนต์ - แนบ Listener
setOnMapLongClickListener
กับออบเจ็กต์แผนที่
private fun setMapLongClick(map:GoogleMap) {
map.setOnMapLongClickListener { }
}
- ใน
setOnMapLongClickListener()
ให้เรียกใช้เมธอดaddMarker()
ส่งออบเจ็กต์MarkerOptions
ใหม่โดยตั้งค่าตำแหน่งเป็นLatLng
ที่ส่งเข้ามา
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
map.addMarker(
MarkerOptions()
.position(latLng)
)
}
}
- เมื่อสิ้นสุด
onMapReady()
ให้โทรหาsetMapLongClick()
ด้วยmap
override fun onMapReady(googleMap: GoogleMap) {
...
setMapLongClick(map)
}
- เรียกใช้แอป
- แตะแผนที่ค้างไว้เพื่อวางเครื่องหมายที่ตำแหน่ง
- แตะเครื่องหมายเพื่อจัดกึ่งกลางบนหน้าจอ
ขั้นตอนที่ 3: เพิ่มหน้าต่างข้อมูลสำหรับเครื่องหมาย
ในขั้นตอนนี้ คุณจะเพิ่ม InfoWindow
ที่แสดงพิกัดของเครื่องหมายเมื่อมีการแตะเครื่องหมาย
- ใน
setMapLongClick()setOnMapLongClickListener()
ให้สร้างval
สำหรับsnippet
ข้อมูลโค้ดคือข้อความเพิ่มเติมที่แสดงหลังชื่อ ข้อมูลโค้ดจะแสดงละติจูดและลองจิจูดของเครื่องหมาย
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
// A snippet is additional text that's displayed after the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
)
}
}
- ใน
addMarker()
ให้ตั้งค่าtitle
ของเครื่องหมายเป็นหมุดที่วางโดยใช้แหล่งข้อมูลสตริงR.string.
dropped_pin
- ตั้งค่า
snippet
ของเครื่องหมายเป็นsnippet
ฟังก์ชันที่เสร็จสมบูรณ์แล้วจะมีลักษณะดังนี้
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
// A Snippet is Additional text that's displayed below the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
.title(getString(R.string.dropped_pin))
.snippet(snippet)
)
}
}
- เรียกใช้แอป
- แตะแผนที่ค้างไว้เพื่อวางเครื่องหมายระบุตำแหน่ง
- แตะเครื่องหมายเพื่อแสดงหน้าต่างข้อมูล
ขั้นตอนที่ 4: เพิ่มเครื่องมือฟัง POI
โดยค่าเริ่มต้น จุดที่น่าสนใจ (POI) จะปรากฏบนแผนที่พร้อมกับไอคอนที่เกี่ยวข้อง POI ได้แก่ สวนสาธารณะ โรงเรียน อาคารรัฐบาล และอื่นๆ เมื่อตั้งค่าประเภทแผนที่เป็น normal
จุดที่น่าสนใจของธุรกิจจะปรากฏบนแผนที่ด้วย POI ของธุรกิจแสดงถึงธุรกิจต่างๆ เช่น ร้านค้า ร้านอาหาร และโรงแรม
ในขั้นตอนนี้ คุณจะเพิ่ม GoogleMap.OnPoiClickListener
ลงในแผนที่ เครื่องมือฟังการคลิกนี้จะวางเครื่องหมายบนแผนที่ทันทีเมื่อผู้ใช้คลิกจุดที่น่าสนใจ ตัวตรวจจับการคลิกยังแสดงหน้าต่างข้อมูลที่มีชื่อจุดที่น่าสนใจด้วย
- สร้าง Stub ของเมธอดใน
MapsActivity
ชื่อsetPoiClick()
ซึ่งรับGoogleMap
เป็นอาร์กิวเมนต์ - ในเมธอด
setPoiClick()
ให้ตั้งค่าOnPoiClickListener
ในGoogleMap
ที่ส่งเข้ามา
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
}
}
- ใน
setOnPoiClickListener()
ให้สร้างval poiMarker
สำหรับเครื่องหมาย - ตั้งค่าเป็นเครื่องหมายโดยใช้
map.addMarker()
พร้อมการตั้งค่าMarkerOptions
โดยตั้งค่าtitle
เป็นชื่อของจุดที่น่าสนใจ
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
val poiMarker = map.addMarker(
MarkerOptions()
.position(poi.latLng)
.title(poi.name)
)
}
}
- ในฟังก์ชัน
setOnPoiClickListener()
ให้เรียกใช้showInfoWindow()
ในpoiMarker
เพื่อแสดงหน้าต่างข้อมูลทันที
poiMarker.showInfoWindow()
โค้ดสุดท้ายสำหรับฟังก์ชัน setPoiClick()
ควรมีลักษณะดังนี้
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
val poiMarker = map.addMarker(
MarkerOptions()
.position(poi.latLng)
.title(poi.name)
)
poiMarker.showInfoWindow()
}
}
- เมื่อสิ้นสุด
onMapReady()
ให้โทรหาsetPoiClick()
แล้วส่งmap
override fun onMapReady(googleMap: GoogleMap) {
...
setPoiClick(map)
}
- เรียกใช้แอปและค้นหาสถานที่น่าสนใจ เช่น สวนสาธารณะหรือร้านกาแฟ
- แตะจุดที่น่าสนใจเพื่อวางเครื่องหมายและแสดงชื่อของจุดที่น่าสนใจในหน้าต่างข้อมูล
คุณปรับแต่ง Google Maps ได้หลายวิธีเพื่อให้แผนที่มีรูปลักษณ์และให้ความรู้สึกที่ไม่ซ้ำใคร
คุณปรับแต่งออบเจ็กต์ MapFragment
ได้โดยใช้แอตทริบิวต์ XML ที่มีอยู่ เช่นเดียวกับการปรับแต่ง Fragment อื่นๆ อย่างไรก็ตาม ในขั้นตอนนี้ คุณจะปรับแต่งรูปลักษณ์ของเนื้อหาของ MapFragment
โดยใช้วิธีการในออบเจ็กต์ GoogleMap
หากต้องการสร้างสไตล์ที่กำหนดเองสำหรับแผนที่ ให้สร้างไฟล์ JSON ที่ระบุวิธีแสดงฟีเจอร์ในแผนที่ คุณไม่จำเป็นต้องสร้างไฟล์ JSON นี้ด้วยตนเอง Google มีวิซาร์ดการจัดรูปแบบ Maps Platform ซึ่งจะสร้าง JSON ให้คุณหลังจากจัดรูปแบบแผนที่ด้วยภาพ ในงานนี้ คุณจะจัดรูปแบบแผนที่ด้วยธีมย้อนยุค ซึ่งหมายความว่าแผนที่จะใช้สีแบบวินเทจและคุณจะเพิ่มถนนที่มีสี
ขั้นตอนที่ 1: สร้างสไตล์สำหรับแผนที่
- ไปที่ https://mapstyle.withgoogle.com/ ในเบราว์เซอร์
- เลือกสร้างสไตล์
- เลือกย้อนยุค
- คลิกตัวเลือกเพิ่มเติม
- ในรายการประเภทฟีเจอร์ ให้เลือกถนน> เติม
- เปลี่ยนสีถนนเป็นสีใดก็ได้ที่คุณเลือก (เช่น สีชมพู)
- คลิกเสร็จสิ้น
- คัดลอกโค้ด JSON จากกล่องโต้ตอบที่ได้ และหากต้องการ ให้เก็บโค้ดไว้ในโน้ตข้อความธรรมดาเพื่อใช้ในขั้นตอนถัดไป
ขั้นตอนที่ 2: เพิ่มสไตล์ลงในแผนที่
- ใน Android Studio ให้สร้างไดเรกทอรีทรัพยากรในไดเรกทอรี
res
แล้วตั้งชื่อว่าraw
คุณใช้ทรัพยากรไดเรกทอรีraw
เช่น โค้ด JSON - สร้างไฟล์ใน
res/raw
ชื่อmap_style.json
- วางโค้ด JSON ที่ซ่อนไว้ลงในไฟล์ทรัพยากรใหม่
- ใน
MapsActivity
ให้สร้างTAG
ตัวแปรคลาสเหนือเมธอดonCreate()
ซึ่งใช้เพื่อวัตถุประสงค์ในการบันทึก
private val TAG = MapsActivity::class.java.simpleName
- นอกจากนี้ ใน
MapsActivity
ให้สร้างฟังก์ชันsetMapStyle()
ที่รับGoogleMap
- ใน
setMapStyle()
ให้เพิ่มบล็อกtry{}
- ใน
try{}
ให้สร้างval success
เพื่อให้การจัดรูปแบบสำเร็จ (คุณเพิ่มบล็อก catch ต่อไปนี้) - ใน
try{}
ให้ตั้งค่าสไตล์ JSON เป็นแผนที่ เรียกใช้setMapStyle()
ในออบเจ็กต์GoogleMap
ส่งออบเจ็กต์MapStyleOptions
ซึ่งจะโหลดไฟล์ JSON - กำหนดผลลัพธ์ให้กับ
success
เมธอดsetMapStyle()
จะแสดงผลบูลีนที่ระบุสถานะความสำเร็จของการแยกวิเคราะห์ไฟล์การจัดรูปแบบและการตั้งค่ารูปแบบ
private fun setMapStyle(map: GoogleMap) {
try {
// Customize the styling of the base map using a JSON object defined
// in a raw resource file.
val success = map.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this,
R.raw.map_style
)
)
}
}
- เพิ่มคำสั่ง if สำหรับ
success
เป็นเท็จ หากจัดรูปแบบไม่สำเร็จ ให้พิมพ์บันทึกว่าการแยกวิเคราะห์ล้มเหลว
private fun setMapStyle(map: GoogleMap) {
try {
...
if (!success) {
Log.e(TAG, "Style parsing failed.")
}
}
}
- เพิ่มบล็อก
catch{}
เพื่อจัดการกรณีที่ไม่มีไฟล์สไตล์ ในcatch
บล็อก หากโหลดไฟล์ไม่ได้ ให้ส่งResources.NotFoundException
private fun setMapStyle(map: GoogleMap) {
try {
...
} catch (e: Resources.NotFoundException) {
Log.e(TAG, "Can't find style. Error: ", e)
}
}
เมธอดที่เสร็จสมบูรณ์แล้วควรมีลักษณะเหมือนข้อมูลโค้ดต่อไปนี้
private fun setMapStyle(map: GoogleMap) {
try {
// Customize the styling of the base map using a JSON object defined
// in a raw resource file.
val success = map.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this,
R.raw.map_style
)
)
if (!success) {
Log.e(TAG, "Style parsing failed.")
}
} catch (e: Resources.NotFoundException) {
Log.e(TAG, "Can't find style. Error: ", e)
}
}
- สุดท้าย ให้เรียกใช้เมธอด
setMapStyle()
ในเมธอดonMapReady()
โดยส่งออบเจ็กต์GoogleMap
override fun onMapReady(googleMap: GoogleMap) {
...
setMapStyle(map)
}
- เรียกใช้แอป
- ตั้งค่าแผนที่เป็นโหมด
normal
แล้วการจัดรูปแบบใหม่จะปรากฏขึ้นพร้อมกับธีมย้อนยุคและถนนในสีที่คุณเลือก
ขั้นตอนที่ 3: จัดรูปแบบเครื่องหมาย
คุณปรับแต่งแผนที่เพิ่มเติมได้โดยการจัดรูปแบบเครื่องหมายแผนที่ ในขั้นตอนนี้ คุณจะเปลี่ยนเครื่องหมายสีแดงเริ่มต้นให้เป็นเครื่องหมายที่ดูดีขึ้น
- ในเมธอด
onMapLongClick()
ให้เพิ่มบรรทัดโค้ดต่อไปนี้ลงในMarkerOptions()
ของตัวสร้างเพื่อใช้เครื่องหมายเริ่มต้น แต่เปลี่ยนสีเป็นสีน้ำเงิน
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
ตอนนี้ onMapLongClickListener()
มีลักษณะดังนี้
map.setOnMapLongClickListener { latLng ->
// A snippet is additional text that's displayed after the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
.title(getString(R.string.dropped_pin))
.snippet(snippet)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
)
}
- เรียกใช้แอป ตอนนี้เครื่องหมายที่ปรากฏหลังจากที่คุณคลิกค้างไว้จะเป็นสีน้ำเงิน โปรดทราบว่าเครื่องหมายจุดที่น่าสนใจยังคงเป็นสีแดงเนื่องจากคุณไม่ได้เพิ่มรูปแบบให้กับเมธอด
onPoiClick()
วิธีหนึ่งในการปรับแต่งแผนที่ Google คือการวาดทับแผนที่ เทคนิคนี้มีประโยชน์หากคุณต้องการไฮไลต์สถานที่ประเภทใดประเภทหนึ่ง เช่น จุดตกปลายอดนิยม
- รูปร่าง: คุณสามารถเพิ่มเส้นหลายเส้น รูปหลายเหลี่ยม และวงกลมลงในแผนที่ได้
GroundOverlay
ออบเจ็กต์: การวางซ้อนพื้นคือรูปภาพที่ตรึงไว้กับแผนที่ การวางซ้อนพื้นดินจะวางแนวให้สอดคล้องกับพื้นผิวโลก ไม่ใช่หน้าจอ ซึ่งแตกต่างจากเครื่องหมาย การหมุน เอียง หรือซูมแผนที่จะเปลี่ยนการวางแนวของรูปภาพ การวางซ้อนพื้นมีประโยชน์เมื่อคุณต้องการแก้ไขรูปภาพเดียวในพื้นที่หนึ่งบนแผนที่
ขั้นตอน: เพิ่มภาพซ้อนทับพื้น
ในงานนี้ คุณจะได้เพิ่มภาพซ้อนทับพื้นในรูปของหุ่นยนต์ Android ลงในตำแหน่งบ้าน
- ดาวน์โหลด รูปภาพ Android นี้และบันทึกลงในโฟลเดอร์
res/drawable
(ตรวจสอบว่าชื่อไฟล์คือandroid.png
)
- ใน
onMapReady()
หลังจากเรียกให้กล้องย้ายไปยังตำแหน่งของบ้านแล้ว ให้สร้างออบเจ็กต์GroundOverlayOptions
- กำหนดออบเจ็กต์ให้กับตัวแปรที่ชื่อ
androidOverlay
val androidOverlay = GroundOverlayOptions()
- ใช้วิธี
BitmapDescriptorFactory.fromResource()
เพื่อสร้างออบเจ็กต์BitmapDescriptor
จากแหล่งข้อมูลรูปภาพที่ดาวน์โหลด - ส่งออบเจ็กต์
BitmapDescriptor
ที่ได้ไปยังเมธอดimage()
ของออบเจ็กต์GroundOverlayOptions
val androidOverlay = GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.android))
- สร้าง
float overlaySize
สำหรับความกว้างเป็นเมตรของภาพซ้อนทับที่ต้องการ ในตัวอย่างนี้ ความกว้าง100f
จะใช้งานได้ดี
ตั้งค่าพร็อพเพอร์ตี้ position
สำหรับออบเจ็กต์ GroundOverlayOptions
โดยเรียกใช้เมธอด position()
และส่งผ่านออบเจ็กต์ homeLatLng
และ overlaySize
val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.android))
.position(homeLatLng, overlaySize)
- เรียกใช้
addGroundOverlay()
ในออบเจ็กต์GoogleMap
แล้วส่งออบเจ็กต์GroundOverlayOptions
map.addGroundOverlay(androidOverlay)
- เรียกใช้แอป
- เปลี่ยนค่าของ
zoomLevel
เป็น 18f เพื่อดูรูปภาพ Android เป็นภาพซ้อนทับ
ผู้ใช้มักใช้ Google Maps เพื่อดูตำแหน่งปัจจุบันของตน หากต้องการแสดงตำแหน่งอุปกรณ์บนแผนที่ คุณสามารถใช้เลเยอร์ข้อมูลตำแหน่งได้
เลเยอร์ข้อมูลตำแหน่งจะเพิ่มตำแหน่งของฉันลงในแผนที่ เมื่อผู้ใช้แตะปุ่ม แผนที่จะอยู่ตรงกลางตำแหน่งของอุปกรณ์ ตำแหน่งจะแสดงเป็นจุดสีน้ำเงินหากอุปกรณ์อยู่กับที่ และเป็นเครื่องหมายก้ามปูสีน้ำเงินหากอุปกรณ์เคลื่อนที่
ในงานนี้ คุณจะเปิดใช้เลเยอร์ข้อมูลตำแหน่ง
ขั้นตอน: ขอสิทธิ์เข้าถึงตำแหน่ง
การเปิดใช้การติดตามตำแหน่งใน Google Maps ต้องใช้โค้ดเพียงบรรทัดเดียว อย่างไรก็ตาม คุณต้องตรวจสอบว่าผู้ใช้ได้ให้สิทธิ์เข้าถึงตำแหน่งแล้ว (โดยใช้รูปแบบสิทธิ์รันไทม์)
ในขั้นตอนนี้ คุณจะขอสิทธิ์เข้าถึงตำแหน่งและเปิดใช้การติดตามตำแหน่ง
- ในไฟล์
AndroidManifest.xml
ให้ตรวจสอบว่ามีสิทธิ์FINE_LOCATION
อยู่แล้ว Android Studio จะแทรกสิทธิ์นี้เมื่อคุณเลือกเทมเพลต Google Maps
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- ใน
MapsActivity
ให้สร้างตัวแปรคลาสREQUEST_LOCATION_PERMISSION
private val REQUEST_LOCATION_PERMISSION = 1
- หากต้องการตรวจสอบว่าได้รับสิทธิ์หรือไม่ ให้สร้างเมธอดใน
MapsActivity
ที่ชื่อisPermissionGranted()
ในวิธีนี้ ให้ตรวจสอบว่าผู้ใช้ได้ให้สิทธิ์หรือไม่
private fun isPermissionGranted() : Boolean {
return ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
- หากต้องการเปิดใช้การติดตามตำแหน่งในแอป ให้สร้างเมธอดใน
MapsActivity
ที่ชื่อenableMyLocation()
ซึ่งไม่ต้องใช้อาร์กิวเมนต์และไม่แสดงผลใดๆ ภายใน ให้ตรวจสอบACCESS_FINE_LOCATION
หากได้รับสิทธิ์ ให้เปิดใช้เลเยอร์ตำแหน่ง หรือขอสิทธิ์
private fun enableMyLocation() {
if (isPermissionGranted()) {
map.isMyLocationEnabled = true
}
else {
ActivityCompat.requestPermissions(
this,
arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION
)
}
}
- เรียกใช้
enableMyLocation()
จากการเรียกกลับonMapReady()
เพื่อเปิดใช้เลเยอร์ตำแหน่ง
override fun onMapReady(googleMap: GoogleMap) {
...
enableMyLocation()
}
- แทนที่เมธอด
onRequestPermissionsResult()
หากrequestCode
เท่ากับREQUEST_LOCATION_PERMISSION
จะได้รับสิทธิ์ และหากอาร์เรย์grantResults
ไม่ว่างโดยมีPackageManager.PERMISSION_GRANTED
ในช่องแรก ให้เรียกใช้enableMyLocation()
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray) {
if (requestCode == REQUEST_LOCATION_PERMISSION) {
if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
enableMyLocation()
}
}
}
- เรียกใช้แอป ควรมีกล่องโต้ตอบที่ขอสิทธิ์เข้าถึงตำแหน่งของอุปกรณ์ โปรดอนุญาตสิทธิ์
ตอนนี้แผนที่จะแสดงตำแหน่งปัจจุบันของอุปกรณ์โดยใช้จุดสีน้ำเงิน สังเกตว่ามีปุ่มตำแหน่ง หากเลื่อนแผนที่ออกจากตำแหน่งของคุณแล้วคลิกปุ่มนี้ ระบบจะจัดให้แผนที่อยู่ตรงกลางตำแหน่งของอุปกรณ์อีกครั้ง
ดาวน์โหลดโค้ดสำหรับ Codelab ที่เสร็จสมบูรณ์แล้ว
$ git clone https://github.com/googlecodelabs/android-kotlin-geo-maps
หรือจะดาวน์โหลดที่เก็บเป็นไฟล์ ZIP แล้วแตกไฟล์และเปิดใน Android Studio ก็ได้
- หากต้องการใช้ Maps API คุณต้องมีคีย์ API จากคอนโซล Google API
- ใน Android Studio การใช้เทมเพลตกิจกรรม Google Maps จะสร้าง
Activity
ที่มีSupportMapFragment
รายการเดียวในเลย์เอาต์ของแอป เทมเพลตยังเพิ่มACCESS_FINE_PERMISSION
ลงในไฟล์ Manifest ของแอป รวมถึงใช้OnMapReadyCallback
ในกิจกรรม และลบล้างเมธอดonMapReady()
ที่จำเป็น
หากต้องการเปลี่ยนประเภทแผนที่ของ GoogleMap
ในขณะรันไทม์ ให้ใช้วิธีการ GoogleMap.setMapType()
Google Maps อาจเป็นแผนที่ประเภทใดประเภทหนึ่งต่อไปนี้
- ปกติ: แผนที่ถนนทั่วไป แสดงถนน สิ่งก่อสร้างบางอย่างที่มนุษย์สร้างขึ้น และลักษณะทางธรรมชาติที่สำคัญ เช่น แม่น้ำ ป้ายกำกับถนนและฟีเจอร์ก็มองเห็นได้เช่นกัน
- ไฮบริด: ข้อมูลภาพถ่ายจากดาวเทียมที่มีการเพิ่มแผนที่ถนน ป้ายกำกับถนนและฟีเจอร์ก็มองเห็นได้เช่นกัน
- ดาวเทียม: ข้อมูลภาพถ่าย ป้ายกำกับถนนและฟีเจอร์จะไม่ปรากฏ
- ภูมิประเทศ: ข้อมูลภูมิประเทศ แผนที่ประกอบด้วยสี เส้นชั้นความสูงและป้ายกำกับ รวมถึงการแรเงาตามมุมมอง นอกจากนี้ คุณยังเห็นถนนและป้ายกำกับบางรายการด้วย
- ไม่มี: ไม่มีไทล์แผนที่ฐาน
เกี่ยวกับ Google Maps
- เครื่องหมายคือตัวบ่งชี้สำหรับสถานที่ตั้งทางภูมิศาสตร์ที่เฉพาะเจาะจง
- เมื่อแตะแล้ว ลักษณะการทำงานเริ่มต้นของเครื่องหมายคือการแสดงหน้าต่างข้อมูลที่มีข้อมูลเกี่ยวกับสถานที่
- โดยค่าเริ่มต้น จุดที่น่าสนใจ (POI) จะปรากฏบนแผนที่ฐานพร้อมกับไอคอนที่เกี่ยวข้อง POI ได้แก่ สวนสาธารณะ โรงเรียน อาคารรัฐบาล และอื่นๆ
- นอกจากนี้ จุดที่น่าสนใจสำหรับธุรกิจ (ร้านค้า ร้านอาหาร โรงแรม และอื่นๆ) จะปรากฏบนแผนที่โดยค่าเริ่มต้นเมื่อประเภทแผนที่เป็น
normal
- คุณบันทึกการคลิกจุดที่น่าสนใจได้โดยใช้
OnPoiClickListener
- คุณเปลี่ยนลักษณะที่ปรากฏขององค์ประกอบเกือบทั้งหมดของ Google Maps ได้โดยใช้วิซาร์ดการจัดรูปแบบ ตัวช่วยจัดรูปแบบจะสร้างไฟล์ JSON ที่คุณส่งไปยัง Google Maps โดยใช้เมธอด
setMapStyle()
- คุณปรับแต่งเครื่องหมายได้โดยเปลี่ยนสีเริ่มต้น หรือแทนที่ไอคอนเครื่องหมายเริ่มต้นด้วยรูปภาพที่กำหนดเอง
ข้อมูลอื่นๆ ที่สำคัญมีดังนี้
- ใช้ภาพซ้อนทับพื้นเพื่อยึดรูปภาพไว้กับสถานที่ตั้งทางภูมิศาสตร์
- ใช้ออบเจ็กต์
GroundOverlayOptions
เพื่อระบุรูปภาพ ขนาดของรูปภาพเป็นเมตร และตำแหน่งของรูปภาพ ส่งออบเจ็กต์นี้ไปยังเมธอดGoogleMap.addGroundOverlay()
เพื่อตั้งค่าการวางซ้อนในแผนที่ - หากแอปมี
ACCESS_FINE_LOCATION
คุณจะเปิดใช้การติดตามตำแหน่งได้โดยการตั้งค่าmap.isMyLocationEnabled = true
- ซึ่งไม่ได้กล่าวถึงในโค้ดแล็บนี้ แต่คุณสามารถให้ข้อมูลเพิ่มเติมเกี่ยวกับสถานที่ได้โดยใช้ Google Street View ซึ่งเป็นรูปภาพพาโนรามาที่นำทางได้ของสถานที่ที่กำหนด
เอกสารประกอบสำหรับนักพัฒนาแอป Android
- เริ่มต้นใช้งาน
- การเพิ่มแผนที่พร้อมเครื่องหมาย
- ออบเจ็กต์แผนที่
- การเพิ่มแผนที่ที่มีการจัดรูปแบบ
- Street View
- การวางซ้อนพื้น
เอกสารอ้างอิง:
ดูลิงก์ไปยัง Codelab อื่นๆ ในหลักสูตรนี้ได้ที่หน้า Landing Page ของ Codelab Android ขั้นสูงใน Kotlin