Giới thiệu
Lấy thông tin quận/huyện/thành phố lân cận (sub-admin area) từ vị trí mạng. Sử dụng address.getSubAdminArea() từ Geocoder. Phù hợp cho ứng dụng thời tiết, tin tức địa phương, tìm kiếm khu vực.
Triển khai
Bước 1: Tạo dự án
Android Studio → New Project → Empty Activity.
Bước 2: Layout (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
android:gravity="center"
tools:context=".MainActivity">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22sp"
android:gravity="center"
android:lineSpacingExtra="4dp"
tools:text="Thông tin khu vực" />
</LinearLayout>
Bước 3: MainActivity.java
package com.example.myapplication;
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.TextView;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
TextView textView;
Location location;
List<Address> addresses;
Geocoder geocoder;
@RequiresApi(api = Build.VERSION_CODES.P)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text);
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 101);
}
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
geocoder = new Geocoder(this, Locale.getDefault());
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == 101 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
fetchAreaInfo();
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
protected void onResume() {
super.onResume();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
fetchAreaInfo();
}
private void fetchAreaInfo() {
if (location == null) {
textView.setText("Không có vị trí\nBật định vị và thử lại");
return;
}
try {
addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 3); // Lấy 3 kết quả
if (addresses != null && !addresses.isEmpty()) {
StringBuilder info = new StringBuilder();
info.append("Vị trí: ").append(String.format("%.4f, %.4f",
location.getLatitude(), location.getLongitude())).append("\n\n");
for (int i = 0; i < addresses.size(); i++) {
Address addr = addresses.get(i);
info.append("Kết quả ").append(i + 1).append(":\n");
info.append(" Đầy đủ: ").append(addr.getAddressLine(0)).append("\n");
info.append(" Quận/Huyện (SubAdminArea): ").append(addr.getSubAdminArea() != null ? addr.getSubAdminArea() : "N/A").append("\n");
info.append(" Tỉnh/TP (AdminArea): ").append(addr.getAdminArea() != null ? addr.getAdminArea() : "N/A").append("\n");
info.append(" Phường/Xã (SubLocality): ").append(addr.getSubLocality() != null ? addr.getSubLocality() : "N/A").append("\n");
info.append(" Thành phố (Locality): ").append(addr.getLocality() != null ? addr.getLocality() : "N/A").append("\n\n");
}
textView.setText(info.toString());
} else {
textView.setText("Không tìm thấy thông tin khu vực");
}
} catch (IOException e) {
e.printStackTrace();
textView.setText("Lỗi: " + e.getMessage());
}
}
}
Bước 4: Manifest
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" />
Cấu trúc địa chỉ hành chính Việt Nam trong Geocoder
| Cấp | Phương thức Geocoder | Ví dụ |
|---|---|---|
| Quốc gia | getCountryName() / getCountryCode() | Vietnam / VN |
| Tỉnh/Thành phố | getAdminArea() | Hà Nội, Hồ Chí Minh, Đà Nẵng |
| Quận/Huyện/Thị xã | getSubAdminArea() | Quận 1, Ba Vì, Sơn Trà |
| Phường/Xã/Thôn | getSubLocality() | Phường Bến Nghé, Xã Đông Xuân |
| Thành phố (cấp dưới) | getLocality() | Thường trùng AdminArea ở VN |
| Địa danh/Địa điểm | getFeatureName() | Bến Thành Market, West Lake |
Lưu ý quan trọng
- getSubAdminArea() ở Việt Nam thường trả về Quận/Huyện
- getAdminArea() trả về Tỉnh/Thành phố trực thuộc TW
- Kết quả phụ thuộc vào dữ liệu Google Maps, vùng vắng có thể thiếu
- Network Provider độ chính xác thấp → có thể trả về quận/huyện sai lân cận
- Nên dùng FusedLocationProviderClient + Geocoder cho độ chính xác cao hơn
Mở rộng: Tìm thành phố lân cận thực sự
Nếu cần tìm các thành phố gần vị trí hiện tại (không phải quận/huyện chứa vị trí), cần dùng Reverse Geocoding với radius hoặc Places API:
// Ý tưởng: dùng Places API Nearby Search // https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=LAT,LNG&radius=50000&type=locality&key=API_KEY