Skip to Content

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

  1. Truy cập Google Cloud Console 
  2. Tạo project mới hoặc chọn project có sẵn
  3. Vào APIs & Services > Library
  4. Enable Maps SDK for Android
  5. Vào APIs & Services > Credentials
  6. Click Create Credentials > API Key
  7. 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ội
  • zoom = 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 marker
  • snippet: Mô tả ngắn bên dưới title
  • icon: 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:

  1. Kiểm tra permission đã được cấp chưa
  2. Nếu chưa → hiển thị button để request
  3. Nếu có → dùng FusedLocationProviderClient để lấy vị trí
  4. isMyLocationEnabled = true hiể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ướcLàm gì
1Tạo API key trên Google Cloud Console
2Thêm dependency maps-compose
3Cấu hình API key trong Manifest
4Dùng GoogleMap composable
5Thêm Marker để đánh dấu vị trí
6Request permission để lấy vị trí user

Lưu ý bảo mật

  • Không commit API key lên GitHub
  • Sử dụng local.properties hoặc environment variables
  • Có thể restrict API key trong Google Cloud Console
Last updated on