Giới thiệu
Bài viết hướng dẫn sử dụng Google Maps SDK và FusedLocationProviderClient (Location API hiện đại) để hiển thị bản đồ và theo dõi vị trí hiện tại của thiết bị Android.
⚠️ Cập nhật quan trọng
Code gốc dùng GoogleMap.OnMapReadyCallback với vị trí cứng (hardcoded). Hiện nay nên dùng FusedLocationProviderClient (Google Play Services Location) để lấy vị trí thực tế, tiết kiệm pin, xử lý quyền tự động.
Các bước thực hiện
Bước 1: Tạo dự án và thêm dependency
Android Studio → File → New Project → **Google Maps Activity** (template có sẵn).
Hoặc Empty Activity + thêm dependency:
dependencies {
implementation 'com.google.android.gms:play-services-maps:18.2.0'
implementation 'com.google.android.gms:play-services-location:21.0.1'
}
Bước 2: Layout (res/layout/activity_maps.xml)
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapsActivity" />
Bước 3: Logic hiện đại (MapsActivity.java)
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.widget.Toast;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnSuccessListener;
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001;
private GoogleMap mMap;
private FusedLocationProviderClient fusedLocationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
mMap = googleMap;
mMap.getUiSettings().setZoomControlsEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
// Kiểm tra và xin quyền vị trí
if (checkLocationPermission()) {
enableMyLocationAndGetCurrent();
} else {
requestLocationPermission();
}
}
private boolean checkLocationPermission() {
return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED;
}
private void requestLocationPermission() {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
enableMyLocationAndGetCurrent();
} else {
Toast.makeText(this, "Cần quyền vị trí để hiển thị vị trí hiện tại", Toast.LENGTH_LONG).show();
}
}
}
private void enableMyLocationAndGetCurrent() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
return;
}
mMap.setMyLocationEnabled(true); // Hiển thị nút "My Location" và chấm xanh
// Lấy vị trí hiện tại một lần (single shot)
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, location -> {
if (location != null) {
LatLng currentLatLng = new LatLng(location.getLatitude(), location.getLongitude());
mMap.addMarker(new MarkerOptions()
.position(currentLatLng)
.title("Vị trí hiện tại của bạn"));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15f));
} else {
Toast.makeText(this, "Không thể lấy vị trí, hãy bật GPS", Toast.LENGTH_SHORT).show();
// Fallback: vị trí mặc định (Hà Nội)
LatLng hanoi = new LatLng(21.0285, 105.8542);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(hanoi, 12f));
}
});
}
}
Bước 4: API Key (res/values/strings.xml)
<resources>
<string name="app_name">Map Demo</string>
<string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">YOUR_API_KEY_HERE</string>
</resources>
Lấy API Key tại Google Cloud Console → APIs & Services → Credentials → Create API Key → Restrict key: Android apps (package name + SHA-1). Bật **Maps SDK for Android**.
Bước 5: Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.com.sample">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Foreground service cho location updates liên tục (Android 10+) -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<activity
android:name=".MapsActivity"
android:label="@string/title_activity_maps">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Chạy ứng dụng
Kết nối thiết bị (cần Google Play Services), nhấn Run. Cấp quyền vị trí → Bản đồ hiển thị vị trí hiện tại.

Nâng cao: Theo dõi vị trí liên tục (Location Updates)
LocationRequest locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(5000) // 5 giây
.setFastestInterval(2000) // 2 giây
.setSmallestDisplacement(10); // 10 mét
LocationCallback locationCallback = new LocationCallback() {
@Override
public void onLocationResult(@NonNull LocationResult locationResult) {
Location location = locationResult.getLastLocation();
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f));
// Cập nhật marker...
}
};
// Bắt đầu
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());
// Dừng (trong onPause/onStop)
fusedLocationClient.removeLocationUpdates(locationCallback);
Best Practices
- Luôn kiểm tra quyền
ACCESS_FINE_LOCATIONtrước khi dùng - Dùng
getLastLocation()cho vị trí nhanh một lần,requestLocationUpdates()cho tracking liên tục - Xử lý trường hợp GPS tắt: chuyển hướng Settings
Settings.ACTION_LOCATION_SOURCE_SETTINGS - Android 10+: Cần
ACCESS_BACKGROUND_LOCATIONcho tracking background - Tiết kiệm pin: Dùng
PRIORITY_BALANCED_POWER_ACCURACYthay vì HIGH_ACCURACY khi không cần chính xác tuyệt đối