Android nâng cao trong Kotlin 04.1: Android Google Maps

Lớp học lập trình này nằm trong khóa học Nâng cao về Android trong Kotlin. Bạn sẽ nhận được nhiều giá trị nhất từ khóa học này nếu bạn làm việc qua các lớp học lập trình theo trình tự, nhưng bạn không bắt buộc phải làm vậy. Tất cả các lớp học lập trình đều có trên trang đích của các lớp học lập trình Android nâng cao trong Kotlin.

Việc xây dựng các ứng dụng bằng Google Maps cho phép bạn thêm các tính năng vào ứng dụng, chẳng hạn như hình ảnh vệ tinh, các tùy chọn kiểm soát giao diện người dùng mạnh mẽ cho bản đồ, tính năng theo dõi vị trí và điểm đánh dấu vị trí. Bạn có thể thêm giá trị cho Google Maps chuẩn bằng cách hiển thị thông tin từ tập dữ liệu của riêng mình, chẳng hạn như vị trí của các khu vực câu cá hoặc leo núi nổi tiếng. Bạn cũng có thể tạo ra các trò chơi trong đó người chơi khám phá thế giới thực, chẳng hạn như trong trò chơi săn kho báu hoặc thậm chí là trò chơi thực tế tăng cường.

Trong bài học này, bạn tạo một ứng dụng Google Maps có tên là Wander. Ứng dụng này hiển thị bản đồ tùy chỉnh và hiển thị vị trí của người dùng.

Điều kiện tiên quyết

Hiểu được những điều sau:

  • Cách tạo một ứng dụng Android cơ bản rồi chạy ứng dụng đó bằng Android Studio.
  • Cách tạo và quản lý các tài nguyên, chẳng hạn như chuỗi.
  • Cách tái cấu trúc mã và đổi tên các biến bằng Android Studio.
  • Cách sử dụng Google Maps với tư cách là người dùng.
  • Cách đặt quyền trong thời gian chạy.

Kiến thức bạn sẽ học được

  • Cách lấy khóa API từ Google API Console và đăng ký khóa đó vào ứng dụng của bạn
  • Cách tích hợp Google Maps trong ứng dụng của bạn
  • Cách hiển thị các loại bản đồ khác nhau
  • Cách tạo kiểu cho Google Maps
  • Cách thêm điểm đánh dấu vào bản đồ của bạn
  • Cách cho phép người dùng đặt điểm đánh dấu về địa điểm yêu thích (CUE)
  • Cách bật tính năng theo dõi vị trí
  • Cách tạo ứng dụng Wander có ứng dụng Google Maps đã nhúng
  • Cách tạo các tính năng tùy chỉnh cho ứng dụng của bạn, chẳng hạn như điểm đánh dấu và kiểu
  • Cách bật tính năng theo dõi vị trí trong ứng dụng

Trong lớp học lập trình này, bạn tạo ứng dụng Wander để hiển thị bản đồ Google với kiểu tùy chỉnh. Ứng dụng Wander cho phép bạn thả điểm đánh dấu vào các vị trí, thêm lớp phủ và xem vị trí của bạn theo thời gian thực.

SDK Maps dành cho Android yêu cầu khóa API. Để có được khóa API, hãy đăng ký dự án của bạn trong trang API & Dịch vụ. Khóa API được liên kết với một chứng chỉ kỹ thuật số liên kết ứng dụng với tác giả của ứng dụng. Để biết thêm thông tin về cách sử dụng chứng chỉ kỹ thuật số và ký ứng dụng, hãy xem phần Ký ứng dụng của bạn.

Trong lớp học lập trình này, bạn sử dụng khóa API cho chứng chỉ gỡ lỗi. Thiết kế của chứng chỉ gỡ lỗi là không an toàn, như mô tả trong phần Ký bản dựng gỡ lỗi của bạn. Các ứng dụng Android được xuất bản có sử dụng SDK Maps dành cho Android cần có khóa API thứ hai: khóa cho chứng chỉ phát hành. Để biết thêm thông tin về cách lấy chứng chỉ phát hành, hãy xem phần Nhận khóa API.

Android Studio bao gồm mẫu Hoạt động trên Google Maps. Mã này tạo ra mã mẫu hữu ích. Mã mẫu bao gồm một tệp google_maps_api.xml chứa đường liên kết giúp đơn giản hóa việc nhận khóa API.

Bước 1: Tạo dự án Wander bằng mẫu bản đồ

  1. Tạo dự án Android Studio mới.
  2. Chọn mẫu Hoạt động trên Google Maps.

  1. Đặt tên cho dự án là Wander.
  2. Đặt cấp độ API tối thiểu thành API 19. Đảm bảo ngôn ngữ là Kotlin.
  3. Nhấp vào Finish (Hoàn tất).
  4. Sau khi ứng dụng hoàn tất, hãy xem dự án của bạn và những tệp liên quan đến bản đồ sau đây mà Android Studio tạo cho bạn:

google_maps_api.xml – Bạn dùng tệp cấu hình này để giữ khóa API của mình. Mẫu tạo hai tệp google_maps_api.xml: một để gỡ lỗi và một để phát hành. Tệp cho khóa API cho chứng chỉ gỡ lỗi nằm trong src/debug/res/values. Tệp cho khóa API cho chứng chỉ phát hành nằm trong src/release/res/values. Trong lớp học lập trình này, bạn chỉ sử dụng chứng chỉ gỡ lỗi.

activity_maps.xml—Tệp bố cục này chứa một mảnh duy nhất lấp đầy toàn bộ màn hình. Lớp SupportMapFragment là một lớp con của lớp Fragment. SupportMapFragment là cách đơn giản nhất để đặt bản đồ vào ứng dụng. Đó là trình bao bọc xung quanh một chế độ xem bản đồ để tự động xử lý các nhu cầu cần thiết trong vòng đời.

Bạn có thể đưa SupportMapFragment vào tệp bố cục bằng thẻ <fragment> trong bất kỳ ViewGroup nào, với thuộc tính name bổ sung.

android:name="com.google.android.gms.maps.SupportMapFragment"

MapsActivity.java – Tệp MapsActivity.kt sẽ tạo thực thể cho SupportMapFragment trong phương thức onCreate(), đồng thời sử dụng lớp#39; getMapAsync() để tự động khởi tạo hệ thống bản đồ và chế độ xem. Hoạt động chứa SupportMapFragment phải triển khai giao diện OnMapReadyCallback và phương thức onMapReady() của giao diện đó. Phương thức onMapReady() được gọi khi bản đồ được tải.

Bước 2: Lấy khóa API

  1. Mở phiên bản gỡ lỗi của tệp google_maps_api.xml.
  2. Trong tệp, hãy tìm nhận xét có URL dài. Các thông số về URL bao gồm thông tin cụ thể về ứng dụng của bạn.
  3. Sao chép và dán URL vào một trình duyệt.
  4. Làm theo lời nhắc để tạo dự án trên trang API & Dịch vụ. Vì các thông số trong URL đã cung cấp nên trang biết tự động bật SDK Maps cho Android.
  5. Nhấp vào Tạo khóa API.
  6. Trên trang tiếp theo, hãy chuyển đến phần Khóa API rồi nhấp vào khóa bạn vừa tạo.
  7. Nhấp vào Hạn chế khóa và chọn SDK Maps dành cho Android để hạn chế việc sử dụng khóa cho các ứng dụng Android.
  8. Sao chép khóa API đã tạo. Bắt đầu bằng "AIza".
  9. Trong tệp google_maps_api.xml, hãy dán khóa này vào chuỗi google_maps_key có dòng YOUR_KEY_HERE.
  10. Chạy ứng dụng của bạn. Bạn sẽ thấy một bản đồ được nhúng trong hoạt động của mình với một điểm đánh dấu được đặt tại Sydney, Úc. (Điểm đánh dấu Sydney là một phần của mẫu và bạn thay đổi sau này.)

Bước 3: Đổi tên mMap

MapsActivity có một lateinit var riêng tư tên là mMap, thuộc loại GoogleMap. Để tuân thủ quy ước đặt tên của Kotlin, hãy đổi tên của mMap thành map.

  1. Trong MapsActivity, hãy nhấp chuột phải vào mMap rồi nhấp vào Tái cấu trúc > Đổi tên...

  1. Đổi tên biến thành map.

Xin lưu ý rằng tất cả các thông tin tham chiếu đến mMap trong hàm onMapReady() cũng thay đổi thành map.

Google Maps bao gồm một số loại bản đồ: bình thường, kết hợp, vệ tinh, địa hình và "none" (không sử dụng bản đồ).

Bản đồ thông thường

Bản đồ vệ tinh

Bản đồ kết hợp

Bản đồ địa hình

Mỗi loại bản đồ cung cấp các loại thông tin khác nhau. Ví dụ: khi sử dụng bản đồ điều hướng trong ô tô, bạn nên xem tên đường phố để có thể sử dụng tùy chọn thông thường. Khi bạn đi bộ, bản đồ địa hình có thể giúp bạn quyết định bạn phải leo thêm bao nhiêu nữa để lên được đỉnh.

Trong nhiệm vụ này, bạn:

  1. Thêm thanh ứng dụng với trình đơn tùy chọn cho phép người dùng thay đổi loại bản đồ.
  2. Di chuyển bản đồ vị trí bắt đầu đến vị trí nhà riêng của bạn.
  3. Thêm tùy chọn hỗ trợ cho điểm đánh dấu, cho biết các vị trí riêng lẻ trên bản đồ và có thể bao gồm nhãn.

Thêm trình đơn cho các loại bản đồ

Trong bước này, bạn thêm một thanh ứng dụng có một trình đơn tùy chọn cho phép người dùng thay đổi loại bản đồ.

  1. Để tạo tệp XML mới cho trình đơn, hãy nhấp chuột phải vào thư mục res rồi chọn Mới > Tệp tài nguyên Android.
  2. Trong hộp thoại, hãy đặt tên tệp là map_options.
  3. Chọn Trình đơn cho loại tài nguyên.
  4. Nhấp vào OK.
  5. Trong thẻ , hãy thay mã trong tệp mới bằng mã sau để tạo tùy chọn trình đơn bản đồ. Loại "none" loại bản đồ bị bỏ qua vì "none" dẫn đến việc thiếu bất kỳ bản đồ nào. Bước này gây ra lỗi, nhưng bạn giải quyết lỗi trong bước tiếp theo.
<?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>
  1. Trong strings.xml, hãy thêm tài nguyên cho các thuộc tính title để khắc phục lỗi.
<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>
  1. Trong MapsActivity, hãy ghi đè phương thức onCreateOptionsMenu() và tăng cường trình đơn từ tệp tài nguyên map_options.
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
   val inflater = menuInflater
   inflater.inflate(R.menu.map_options, menu)
   return true
}
  1. Trong MapsActivity.kt, hãy ghi đè phương thức onOptionsItemSelected(). Thay đổi loại bản đồ bằng cách sử dụng hằng số loại bản đồ để phản ánh lựa chọn của người dùng.
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)
}
  1. Chạy ứng dụng.
  2. Nhấp vào để thay đổi loại bản đồ. Hãy chú ý tới sự thay đổi trong giao diện của bản đồ.

Theo mặc định, lệnh gọi lại onMapReady() bao gồm mã đặt điểm đánh dấu ở Sydney, Úc, nơi Google Maps được tạo. Lệnh gọi lại mặc định cũng tạo hiệu ứng bản đồ để xoay đến Sydney.

Trong nhiệm vụ này, bạn cần chuyển máy ảnh của bản đồ về nhà mình, thu phóng đến cấp độ bạn chỉ định và đặt điểm đánh dấu tại đó.

Bước 1: Thu phóng về nhà và thêm điểm đánh dấu

  1. Trong tệp MapsActivity.kt, hãy tìm phương thức onMapReady(). Xóa mã ở vị trí đó để đặt điểm đánh dấu ở Sydney và di chuyển máy ảnh. Đây là giao diện của phương thức.
override fun onMapReady(googleMap: GoogleMap) {
   map = googleMap

}
  1. Tìm vĩ độ và kinh độ trong nhà của bạn bằng cách làm theo các hướng dẫn này.
  2. Tạo một giá trị cho vĩ độ và một giá trị cho kinh độ, đồng thời nhập các giá trị số thực của chúng.
val latitude = 37.422160
val longitude = -122.084270
  1. Tạo đối tượng LatLng mới có tên là homeLatLng. Trong đối tượng homeLatLng, hãy chuyển các giá trị mà bạn vừa tạo.
val homeLatLng = LatLng(latitude, longitude)
  1. Tạo val cho mức độ phóng to mà bạn muốn hiển thị trên bản đồ. Sử dụng mức thu phóng 15f.
val zoomLevel = 15f

Mức thu phóng kiểm soát mức độ phóng to của bạn trên bản đồ. Danh sách sau đây giúp bạn biết được mức độ chi tiết của từng mức thu phóng:

  • 1: Thế giới
  • 5: Vùng đất/l lục địa
  • 10: Thành phố
  • 15: Đường phố
  • 20: Tòa nhà
  1. Di chuyển máy ảnh vào homeLatLng bằng cách gọi hàm moveCamera() trên đối tượng map và chuyển trong đối tượng CameraUpdate sử dụng CameraUpdateFactory.newLatLngZoom(). Chuyển vào đối tượng homeLatLngzoomLevel.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
  1. Thêm điểm đánh dấu vào bản đồ tại homeLatLng.
map.addMarker(MarkerOptions().position(homeLatLng))

Phương pháp cuối cùng của bạn sẽ có dạng như sau:

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))
}
  1. Chạy ứng dụng. Bản đồ sẽ xoay về nhà bạn, thu phóng đến mức mong muốn và đặt điểm đánh dấu trên nhà của bạn.

Bước 2: Cho phép người dùng thêm điểm đánh dấu bằng cách nhấp chuột dài

Trong bước này, bạn thêm một điểm đánh dấu khi người dùng chạm và giữ một vị trí trên bản đồ.

  1. Tạo một phương thức mã trong MapsActivity có tên là setMapLongClick(). Phương thức này sẽ lấy GoogleMap làm đối số.
  2. Đính kèm một trình xử lý setOnMapLongClickListener vào đối tượng bản đồ.
private fun setMapLongClick(map:GoogleMap) {
   map.setOnMapLongClickListener { }
}
  1. Trong setOnMapLongClickListener(), hãy gọi phương thức addMarker(). Chuyển đối tượng MarkerOptions mới vào vị trí được đặt thành LatLng đã chuyển.
private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       map.addMarker(
           MarkerOptions()
               .position(latLng)
       )
   }
}
  1. Ở cuối phương thức onMapReady(), hãy gọi setMapLongClick() bằng map.
override fun onMapReady(googleMap: GoogleMap) {
   ...
  
   setMapLongClick(map)
}
  1. Chạy ứng dụng của bạn.
  2. Chạm và giữ bản đồ để đặt điểm đánh dấu tại một vị trí.
  3. Hãy nhấn vào điểm đánh dấu đó để tâm điểm vào màn hình.

Bước 3: Thêm cửa sổ thông tin cho điểm đánh dấu

Trong bước này, bạn thêm một InfoWindow để hiển thị tọa độ của điểm đánh dấu khi điểm đánh dấu được nhấn vào.

  1. Trong setMapLongClick()setOnMapLongClickListener(), hãy tạo một val cho snippet. Đoạn trích là văn bản bổ sung được hiển thị sau tiêu đề. Đoạn mã của bạn hiển thị vĩ độ và kinh độ của một điểm đánh dấu.
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)
       )
   }
}
  1. Trong addMarker(), hãy đặt title của điểm đánh dấu thành Ghim đã thả bằng tài nguyên chuỗi R.string.dropped_pin.
  2. Đặt điểm đánh dấu snippet thành snippet.

Hàm hoàn chỉnh sẽ có dạng như sau:

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)
              
       )
   }
}
  1. Chạy ứng dụng của bạn.
  2. Chạm và giữ bản đồ để thả điểm đánh dấu vị trí.
  3. Nhấn vào điểm đánh dấu để hiển thị cửa sổ thông tin.

Bước 4: Thêm trình xử lý địa điểm yêu thích

Theo mặc định, các địa điểm yêu thích (CUE) xuất hiện trên bản đồ cùng với các biểu tượng tương ứng. Các điểm yêu thích có thể bao gồm công viên, trường học, tòa nhà chính phủ và các địa điểm khác. Khi loại bản đồ được đặt thành normal, điểm yêu thích của doanh nghiệp cũng xuất hiện trên bản đồ. Địa điểm yêu thích của doanh nghiệp đại diện cho các doanh nghiệp, chẳng hạn như cửa hàng, nhà hàng và khách sạn.

Trong bước này, bạn sẽ thêm một GoogleMap.OnPoiClickListener vào bản đồ. Trình nghe lượt nhấp này đặt một điểm đánh dấu trên bản đồ ngay khi người dùng nhấp vào một điểm yêu thích. Trình nghe lượt nhấp cũng hiển thị một cửa sổ thông tin chứa tên địa điểm yêu thích.

  1. Tạo một phương thức mã trong MapsActivity có tên là setPoiClick(). Phương thức này sẽ lấy GoogleMap làm đối số.
  2. Trong phương thức setPoiClick(), hãy đặt OnPoiClickListener trên GoogleMap đã chuyển.
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->

   }
}
  1. Trong setOnPoiClickListener(), hãy tạo một val poiMarker cho điểm đánh dấu .
  2. Đặt điểm đánh dấu thành điểm đánh dấu bằng cách sử dụng map.addMarker() với MarkerOptions, đặt title thành tên của điểm yêu thích.
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
   }
}
  1. Trong hàm setOnPoiClickListener(), hãy gọi showInfoWindow() trên poiMarker để hiển thị ngay cửa sổ thông tin.
poiMarker.showInfoWindow()

Mã cuối cùng của hàm setPoiClick() phải có dạng như sau.

private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
       poiMarker.showInfoWindow()
   }
}
  1. Vào cuối onMapReady(), hãy gọi setPoiClick() và chuyển vào map.
override fun onMapReady(googleMap: GoogleMap) {
   ...

   setPoiClick(map)
}
  1. Chạy ứng dụng của bạn và tìm địa điểm yêu thích, chẳng hạn như công viên hoặc quán cà phê.
  2. Nhấn vào điểm yêu thích để đặt điểm đánh dấu vào đó và hiển thị tên điểm yêu thích trong cửa sổ thông tin.

Bạn có thể tùy chỉnh Google Maps theo nhiều cách, mang đến cho bản đồ của bạn một giao diện độc đáo.

Bạn có thể tùy chỉnh một đối tượng MapFragment bằng cách sử dụng các thuộc tính XML có sẵn, giống như cách bạn tùy chỉnh mọi mảnh khác. Tuy nhiên, trong bước này, bạn tùy chỉnh giao diện nội dung của MapFragment bằng cách sử dụng các phương thức trên đối tượng GoogleMap.

Để tạo kiểu tùy chỉnh cho bản đồ của bạn, hãy tạo một tệp JSON chỉ định cách hiển thị các đối tượng trong bản đồ. Bạn không phải tạo tệp JSON này theo cách thủ công. Google cung cấp Trình hướng dẫn tạo kiểu cho Maps – trình tạo này tạo ra JSON cho bạn sau khi bạn tạo kiểu cho bản đồ của mình bằng hình ảnh. Trong nhiệm vụ này, bạn tạo kiểu cho bản đồ theo chủ đề hoài cổ, nghĩa là bản đồ sẽ sử dụng màu cổ điển và bạn thêm các đường màu.

Bước 1: Tạo kiểu cho bản đồ của bạn

  1. Truy cập vào https://mapstyle.withgoogle.com/ trong trình duyệt của bạn.
  2. Chọn Tạo kiểu.
  3. Chọn Retro.

  1. Nhấp vào Tùy chọn khác.

  1. Trong danh sách Loại tính năng, hãy chọn Đường > Điền.
  2. Thay đổi màu của đường thành bất kỳ màu nào bạn chọn (chẳng hạn như màu hồng).

  1. Nhấp vào Finish (Hoàn tất).

  1. Sao chép mã JSON từ hộp thoại hiện ra và nếu bạn muốn, hãy ẩn mã đó vào một ghi chú văn bản thuần túy để sử dụng trong bước tiếp theo.

Bước 2: Thêm kiểu vào bản đồ

  1. Trong Android Studio, trong thư mục res , hãy tạo một thư mục tài nguyên và đặt tên là raw. Bạn sử dụng tài nguyên thư mục raw như mã JSON.
  2. Tạo một tệp trong res/raw có tên là map_style.json.
  3. Dán mã JSON đã lưu trữ vào tệp tài nguyên mới.
  4. Trong MapsActivity, hãy tạo một biến lớp TAG phía trên phương thức onCreate(). Thuộc tính này dùng cho mục đích ghi nhật ký.
private val TAG = MapsActivity::class.java.simpleName
  1. Cũng trong MapsActivity, hãy tạo một hàm setMapStyle() nhận GoogleMap.
  2. Trong setMapStyle(), hãy thêm một khối try{}.
  3. Trong khối try{}, hãy tạo val success để tạo kiểu thành công. (Bạn thêm khối chặn sau.)
  4. Trong khối try{}, hãy đặt kiểu JSON thành bản đồ, hãy gọi setMapStyle() trên đối tượng GoogleMap. Chuyển vào đối tượng MapStyleOptions, sẽ tải tệp JSON.
  5. Chỉ định kết quả cho success. Phương thức setMapStyle() trả về boolean cho biết trạng thái thành công của việc phân tích cú pháp tệp định kiểu và đặt kiểu.
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
           )
       )
   }
}
  1. Thêm câu lệnh if cho success là false. Nếu kiểu đó không thành công, hãy in nhật ký mà việc phân tích cú pháp không thành công.
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
       if (!success) {
           Log.e(TAG, "Style parsing failed.")
       }
   }
}
  1. Thêm một khối catch{} để xử lý trường hợp thiếu tệp kiểu. Trong khối catch, nếu tệp không thể tải, hãy gửi Resources.NotFoundException.
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
   } catch (e: Resources.NotFoundException) {
       Log.e(TAG, "Can't find style. Error: ", e)
   }
}

Phương thức hoàn thành sẽ có dạng như đoạn mã sau:

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)
   }
}
  1. Cuối cùng, hãy gọi phương thức setMapStyle() trong phương thức onMapReady() chuyển trong đối tượng GoogleMap.
override fun onMapReady(googleMap: GoogleMap) {
   ...
   setMapStyle(map)
}
  1. Chạy ứng dụng của bạn.
  2. Đặt bản đồ thành chế độ normal và kiểu mới sẽ hiển thị với giao diện cũ và đường của màu bạn đã chọn.

Bước 3: Tạo kiểu cho điểm đánh dấu của bạn

Bạn có thể cá nhân hóa bản đồ của mình hơn nữa bằng cách tạo kiểu cho điểm đánh dấu bản đồ. Trong bước này, bạn sẽ thay đổi những điểm đánh dấu màu đỏ mặc định thành nội dung hấp dẫn hơn.

  1. Trong phương thức onMapLongClick(), hãy thêm dòng mã sau vào MarkerOptions() của hàm dựng để sử dụng điểm đánh dấu mặc định, nhưng đổi màu thành màu xanh lam.
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))

Giờ đây, onMapLongClickListener() sẽ có dạng như sau:

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))
   )
}
  1. Chạy ứng dụng. Các điểm đánh dấu xuất hiện sau khi bạn nhấp và giữ hiện có màu xanh dương. Lưu ý rằng các điểm đánh dấu điểm yêu thích vẫn có màu đỏ vì bạn chưa thêm kiểu vào phương thức onPoiClick().

Bạn có thể tuỳ chỉnh bản đồ Google bằng cách vẽ lên trên bản đồ. Kỹ thuật này rất hữu ích nếu bạn muốn làm nổi bật một loại vị trí cụ thể, chẳng hạn như những điểm câu cá phổ biến.

  • Hình dạng: Bạn có thể thêm nhiều đường, đa giácvòng tròn vào bản đồ.
  • Đối tượng GroundOverlay: Lớp phủ mặt đất là một hình ảnh cố định cho một bản đồ. Không giống như điểm đánh dấu, lớp phủ mặt đất được hướng đến bề mặt Trái đất thay vì màn hình. Xoay, nghiêng hoặc thu phóng bản đồ sẽ thay đổi hướng của hình ảnh. Lớp phủ mặt đất rất hữu ích khi bạn muốn chỉnh sửa một hình ảnh ở một khu vực trên bản đồ.

Bước: Thêm lớp phủ mặt đất

Trong nhiệm vụ này, bạn thêm lớp phủ mặt đất có hình dạng Android vào vị trí nhà riêng.

  1. Hãy tải hình ảnh Android này xuống rồi lưu vào thư mục res/drawable của bạn. (Đảm bảo tên tệp là android.png.)

  1. Sau onMapReady(), sau khi cuộc gọi chuyển máy ảnh đến vị trí nhà riêng của bạn, hãy tạo một đối tượng GroundOverlayOptions.
  2. Chỉ định đối tượng này cho một biến có tên là androidOverlay.
val androidOverlay = GroundOverlayOptions()
  1. Sử dụng phương thức BitmapDescriptorFactory.fromResource() để tạo đối tượng BitmapDescriptor từ tài nguyên hình ảnh đã tải xuống.
  2. Chuyển đối tượng BitmapDescriptor kết quả vào phương thức image() của đối tượng GroundOverlayOptions.
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
  1. Tạo float overlaySize cho chiều rộng tính bằng mét của lớp phủ mong muốn. Trong ví dụ này, chiều rộng 100f sẽ hoạt động tốt.

Đặt thuộc tính position cho đối tượng GroundOverlayOptions bằng cách gọi phương thức position() và chuyển trong đối tượng homeLatLngoverlaySize.

val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
   .position(homeLatLng, overlaySize)
  1. Gọi addGroundOverlay() trên đối tượng GoogleMap và chuyển vào đối tượng GroundOverlayOptions.
map.addGroundOverlay(androidOverlay)
  1. Chạy ứng dụng.
  2. Hãy thay đổi giá trị của zoomLevel thành 18f để xem hình ảnh Android dưới dạng một lớp phủ.

Người dùng thường sử dụng Google Maps để xem vị trí hiện tại của họ. Để hiển thị vị trí của thiết bị trên bản đồ của bạn, bạn có thể sử dụng lớp dữ liệu vị trí.

Lớp dữ liệu vị trí sẽ thêm Vị trí của tôi vào bản đồ. Khi người dùng nhấn vào nút, bản đồ sẽ căn giữa vị trí của thiết bị. Vị trí được hiển thị dưới dạng chấm màu xanh dương nếu thiết bị đứng yên và dưới dạng sọc màu xanh dương nếu thiết bị đang di chuyển.

Trong tác vụ này, bạn sẽ bật lớp dữ liệu vị trí.

Bước: Yêu cầu quyền truy cập thông tin vị trí

Để bật tính năng theo dõi vị trí trong Google Maps, bạn phải có một dòng mã duy nhất. Tuy nhiên, bạn phải đảm bảo rằng người dùng đã cấp quyền truy cập thông tin vị trí (bằng cách sử dụng mô hình quyền truy cập thời gian chạy).

Trong bước này, bạn yêu cầu quyền truy cập thông tin vị trí và bật tính năng theo dõi vị trí.

  1. Trong tệp AndroidManifest.xml, hãy xác minh rằng bạn có quyền FINE_LOCATION. Android Studio đã chèn quyền này khi bạn chọn mẫu Google Maps.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  1. Trong MapsActivity, hãy tạo một biến lớp REQUEST_LOCATION_PERMISSION.
private val REQUEST_LOCATION_PERMISSION = 1
  1. Để kiểm tra xem có được cấp quyền hay không, hãy tạo một phương thức trong MapsActivity có tên là isPermissionGranted(). Trong phương thức này, hãy kiểm tra xem người dùng đã cấp quyền hay chưa.
private fun isPermissionGranted() : Boolean {
  return ContextCompat.checkSelfPermission(
       this,
      Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
  1. Để bật tính năng theo dõi vị trí trong ứng dụng, hãy tạo một phương thức trong MapsActivity có tên là enableMyLocation(). Phương thức này không nhận đối số nào và không trả về bất kỳ giá trị nào. Bên trong, hãy kiểm tra quyền ACCESS_FINE_LOCATION. Nếu quyền đó được cấp, hãy bật lớp vị trí. Nếu không, hãy yêu cầu quyền.
private fun enableMyLocation() {
   if (isPermissionGranted()) {
       map.isMyLocationEnabled = true 
   }
   else {
       ActivityCompat.requestPermissions(
           this,
           arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
           REQUEST_LOCATION_PERMISSION
       )
   }
}
  1. Gọi enableMyLocation() từ lệnh gọi lại onMapReady() để bật lớp vị trí.
override fun onMapReady(googleMap: GoogleMap) {
   ...
   enableMyLocation()
}
  1. Ghi đè phương thức onRequestPermissionsResult(). Nếu quyền requestCode bằng REQUEST_LOCATION_PERMISSION được cấp và nếu mảng grantResults không trống với PackageManager.PERMISSION_GRANTED ở vị trí đầu tiên, hãy gọi enableMyLocation().
override fun onRequestPermissionsResult(
   requestCode: Int,
   permissions: Array<String>,
   grantResults: IntArray) {
   if (requestCode == REQUEST_LOCATION_PERMISSION) {
       if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
           enableMyLocation()
       }
   }
}
  1. Chạy ứng dụng của bạn. Bạn sẽ thấy một hộp thoại yêu cầu quyền truy cập vào thông tin vị trí của thiết bị. Hãy tiếp tục và cho phép.

Bản đồ hiện hiển thị vị trí hiện tại của thiết bị bằng chấm màu xanh dương. Xin lưu ý rằng có một nút vị trí. Nếu bạn di chuyển bản đồ ra khỏi vị trí của bạn và nhấp vào nút này, nó sẽ căn giữa bản đồ về vị trí của thiết bị.

Tải mã xuống cho lớp học lập trình đã hoàn thành.

$  git clone https://github.com/googlecodelabs/android-kotlin-geo-maps


Hoặc bạn có thể tải tệp lưu trữ xuống dưới dạng tệp zip, giải nén và mở tệp đó trong Android Studio.

Tải tệp zip xuống

  • Để sử dụng API Maps, bạn cần có khóa API từ Google API Console.
  • Trong Android Studio, việc sử dụng mẫu Hoạt động trên Google Maps tạo một Activity chỉ với một SupportMapFragment trong bố cục của ứng dụng. Mẫu cũng thêm ACCESS_FINE_PERMISSION vào tệp kê khai ứng dụng và triển khai OnMapReadyCallback trong hoạt động của bạn và ghi đè phương thức onMapReady() bắt buộc.

Để thay đổi loại bản đồ của GoogleMap vào thời gian chạy, hãy dùng phương thức GoogleMap.setMapType(). Bản đồ của Google có thể là một trong các loại bản đồ sau:

  • Thông thường: Bản đồ đường thông thường. Hiển thị đường, một số tính năng do con người tạo ra và các đặc điểm tự nhiên quan trọng như sông. Ngoài ra, nhãn đường và tính năng cũng hiển thị.
  • Kết hợp: Dữ liệu ảnh vệ tinh và bản đồ đường được thêm vào. Ngoài ra, nhãn đường và tính năng cũng hiển thị.
  • Vệ tinh: Dữ liệu ảnh. Các nhãn đường và tính năng không hiển thị.
  • Địa hình: Dữ liệu địa hình. Bản đồ bao gồm màu, đường kẻ và nhãn, cũng như tính năng tô bóng phối cảnh. Một số đường và nhãn cũng hiển thị.
  • Không có: Không có ô bản đồ cơ sở nào.

Giới thiệu về Google Maps:

  • Điểm đánh dấu là chỉ báo cho một vị trí địa lý cụ thể.
  • Khi được nhấn, hoạt động mặc định của điểm đánh dấu là hiển thị cửa sổ thông tin chứa thông tin về vị trí đó.
  • Theo mặc định, các địa điểm yêu thích (CUE) xuất hiện trên bản đồ cơ sở cùng với các biểu tượng tương ứng. Các điểm yêu thích có thể bao gồm công viên, trường học, tòa nhà chính phủ và các địa điểm khác.
  • Ngoài ra, điểm yêu thích dành cho doanh nghiệp (cửa hàng, nhà hàng, khách sạn và các địa điểm khác) sẽ xuất hiện theo mặc định trên bản đồ khi loại bản đồ là normal.
  • Bạn có thể nắm bắt lượt nhấp vào điểm yêu thích bằng cách sử dụng OnPoiClickListener.
  • Bạn có thể thay đổi giao diện hình ảnh của hầu hết mọi thành phần trong Google Maps bằng Trình hướng dẫn tạo kiểu. Trình hướng dẫn tạo kiểu tạo tệp JSON mà bạn chuyển vào Google Maps bằng phương thức setMapStyle().
  • Bạn có thể tùy chỉnh các điểm đánh dấu bằng cách thay đổi màu mặc định hoặc thay thế biểu tượng điểm đánh dấu mặc định bằng một hình ảnh tùy chỉnh.

Các thông tin quan trọng khác:

  • Sử dụng lớp phủ mặt đất để cố định hình ảnh cho một vị trí địa lý.
  • Sử dụng đối tượng GroundOverlayOptions để chỉ định hình ảnh, kích thước của hình ảnh tính bằng mét và vị trí của hình ảnh. Chuyển đối tượng này vào phương thức GoogleMap.addGroundOverlay() để đặt lớp phủ lên bản đồ.
  • Miễn là ứng dụng của bạn có quyền ACCESS_FINE_LOCATION, bạn có thể bật theo dõi vị trí bằng cách đặt map.isMyLocationEnabled = true.
  • Lớp học này không được bao gồm trong lớp học lập trình này, nhưng bạn có thể cung cấp thêm thông tin về một vị trí bằng cách sử dụng Chế độ xem phố của Google. Đây là ảnh toàn cảnh có thể di chuyển đến một vị trí nhất định.

Tài liệu dành cho nhà phát triển Android:

Tài liệu tham khảo:

Để biết đường liên kết đến các lớp học lập trình khác trong khóa học này, hãy xem trang đích của Lớp học nâng cao cho Android trong Kotlin.