Google Maps trong Android
Bài này hướng dẫn bạn tích hợp Google Maps vào ứng dụng Android với Jetpack Compose, từ setup cơ bản đến các tính năng nâng cao.
1. Tại sao dùng Google Maps?
Google Maps cho phép bạn:
- Hiển thị bản đồ trong app
- Đánh dấu vị trí (markers)
- Hiển thị vị trí hiện tại của user
- Vẽ đường đi, polylines
- Tích hợp với Places API để tìm kiếm địa điểm
2. Setup Google Maps SDK
Bước 1: Tạo API Key
- Truy cập Google Cloud Console
- Tạo project mới hoặc chọn project có sẵn
- Vào APIs & Services > Library
- Enable Maps SDK for Android
- Vào APIs & Services > Credentials
- Click Create Credentials > API Key
- Copy API key
Bước 2: Thêm Dependencies
// build.gradle.kts (Module: app)
dependencies {
// Google Maps Compose
implementation("com.google.maps.android:maps-compose:4.3.0")
// Google Maps Services (optional, for places)
implementation("com.google.android.gms:play-services-maps:18.2.0")
implementation("com.google.android.gms:play-services-location:21.1.0")
}Bước 3: Cấu hình API Key
<!-- AndroidManifest.xml -->
<application ...>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${MAPS_API_KEY}" />
</application>// local.properties (KHÔNG commit lên Git!)
MAPS_API_KEY=AIzaSyB...your_api_key_here// build.gradle.kts
android {
defaultConfig {
manifestPlaceholders["MAPS_API_KEY"] =
project.findProperty("MAPS_API_KEY") as String? ?: ""
}
}Tại sao làm như vậy?
- API key là thông tin nhạy cảm
- Không nên commit trực tiếp vào code
local.propertiesđã được ignore bởi.gitignore
3. Hiển thị bản đồ cơ bản
@Composable
fun BasicMapScreen() {
// Vị trí mặc định: Hà Nội
val hanoi = LatLng(21.0285, 105.8542)
// Camera state - điều khiển góc nhìn của bản đồ
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(hanoi, 12f)
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
)
}Giải thích:
LatLng(21.0285, 105.8542): Tọa độ (vĩ độ, kinh độ) của Hà Nộizoom = 12f: Mức zoom (1 = thế giới, 20 = tòa nhà)cameraPositionState: Quản lý vị trí camera (có thể animate)
4. Thêm Markers (Đánh dấu vị trí)
@Composable
fun MapWithMarkers() {
val hanoi = LatLng(21.0285, 105.8542)
val hoGuom = LatLng(21.0288, 105.8525)
val hoTay = LatLng(21.0542, 105.8231)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(hanoi, 13f)
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
// Marker cơ bản
Marker(
state = MarkerState(position = hoGuom),
title = "Hồ Gươm",
snippet = "Trung tâm Hà Nội"
)
// Marker với icon tùy chỉnh
Marker(
state = MarkerState(position = hoTay),
title = "Hồ Tây",
icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)
)
}
}Giải thích:
Marker: Đánh dấu một vị trí trên bản đồtitle: Tiêu đề hiển thị khi tap vào markersnippet: Mô tả ngắn bên dưới titleicon: Có thể dùng màu khác hoặc icon tùy chỉnh
5. Lấy vị trí hiện tại của User
Bước 1: Thêm Permissions
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />Bước 2: Request Permission và lấy vị trí
@Composable
fun MapWithCurrentLocation() {
val context = LocalContext.current
var currentLocation by remember { mutableStateOf<LatLng?>(null) }
// Request location permission
val permissionState = rememberPermissionState(Manifest.permission.ACCESS_FINE_LOCATION)
LaunchedEffect(permissionState.status.isGranted) {
if (permissionState.status.isGranted) {
// Lấy vị trí hiện tại
val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
location?.let {
currentLocation = LatLng(it.latitude, it.longitude)
}
}
}
}
// UI
Column {
if (!permissionState.status.isGranted) {
Button(onClick = { permissionState.launchPermissionRequest() }) {
Text("Cho phép truy cập vị trí")
}
}
currentLocation?.let { location ->
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(location, 15f)
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState,
properties = MapProperties(isMyLocationEnabled = true)
) {
Marker(
state = MarkerState(position = location),
title = "Vị trí của bạn"
)
}
}
}
}Giải thích từng bước:
- Kiểm tra permission đã được cấp chưa
- Nếu chưa → hiển thị button để request
- Nếu có → dùng
FusedLocationProviderClientđể lấy vị trí isMyLocationEnabled = truehiển thị chấm xanh vị trí hiện tại
6. Xử lý khi User tap vào bản đồ
@Composable
fun MapWithTapHandler() {
var selectedLocation by remember { mutableStateOf<LatLng?>(null) }
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(LatLng(21.0285, 105.8542), 12f)
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState,
onMapClick = { latLng ->
// User tap vào vị trí này
selectedLocation = latLng
}
) {
selectedLocation?.let { location ->
Marker(
state = MarkerState(position = location),
title = "Vị trí đã chọn",
snippet = "Lat: ${location.latitude}, Lng: ${location.longitude}"
)
}
}
}7. Vẽ đường (Polyline)
@Composable
fun MapWithRoute() {
// Các điểm tạo thành đường đi
val routePoints = listOf(
LatLng(21.0285, 105.8542), // Điểm A
LatLng(21.0300, 105.8500), // Điểm B
LatLng(21.0350, 105.8450), // Điểm C
LatLng(21.0400, 105.8400), // Điểm D
)
GoogleMap(...) {
// Vẽ đường nối các điểm
Polyline(
points = routePoints,
color = Color.Blue,
width = 10f
)
// Đánh dấu điểm đầu và cuối
Marker(state = MarkerState(position = routePoints.first()), title = "Điểm đi")
Marker(state = MarkerState(position = routePoints.last()), title = "Điểm đến")
}
}8. Các loại Map (Map Types)
GoogleMap(
properties = MapProperties(
mapType = MapType.NORMAL // Bản đồ thường
// mapType = MapType.SATELLITE // Ảnh vệ tinh
// mapType = MapType.TERRAIN // Địa hình
// mapType = MapType.HYBRID // Kết hợp
)
)9. Map Controls (Zoom, Compass, etc.)
GoogleMap(
uiSettings = MapUiSettings(
zoomControlsEnabled = true, // Nút +/-
compassEnabled = true, // La bàn
myLocationButtonEnabled = true, // Nút về vị trí hiện tại
mapToolbarEnabled = false // Toolbar Google Maps
)
)📝 Tóm tắt cho người mới
| Bước | Làm gì |
|---|---|
| 1 | Tạo API key trên Google Cloud Console |
| 2 | Thêm dependency maps-compose |
| 3 | Cấu hình API key trong Manifest |
| 4 | Dùng GoogleMap composable |
| 5 | Thêm Marker để đánh dấu vị trí |
| 6 | Request permission để lấy vị trí user |
Lưu ý bảo mật
- Không commit API key lên GitHub
- Sử dụng
local.propertieshoặc environment variables - Có thể restrict API key trong Google Cloud Console
Last updated on