在 Android 應用中嵌入 Google 地圖,包含標記點、資訊視窗、縮放控制等基本功能。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application>
<meta-data android:name="com.google.android.geo.API_KEY" android:value="YOUR_API_KEY" />
<uses-library android:name="org.apache.http.legacy" android:required="false" />
</application>
implementation 'com.google.android.gms:play-services-maps:18.2.0'
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map_fragment);
mapFragment.getMapAsync(this);
}
@Override public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// 1. 設定初始位置與縮放
LatLng taipei = new LatLng(25.0330, 121.5654);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(taipei, 12));
// 2. 添加標記
mMap.addMarker(new MarkerOptions()
.position(taipei)
.title("台北 101")
.snippet("台灣最高建築")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
// 3. 啟用定位圖層 (需權限)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
}
// 4. 設定資訊視窗點擊
mMap.setOnInfoWindowClickListener(marker -> {
Toast.makeText(this, "點擊: " + marker.getTitle(), Toast.LENGTH_SHORT).show();
});
}
}
<fragment xmlns:android="https://schemas.android.com/apk/res/android"
android:id="@+id/map_fragment"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
// 僅供參考:MapView 需手動管理生命週期
public class OldMapActivity extends AppCompatActivity {
private MapView mapView;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mapView = new MapView(this);
mapView.onCreate(savedInstanceState);
setContentView(mapView);
mapView.getMapAsync(this::onMapReady);
}
@Override protected void onResume() { super.onResume(); mapView.onResume(); }
@Override protected void onPause() { super.onPause(); mapView.onPause(); }
@Override protected void onDestroy() { super.onDestroy(); mapView.onDestroy(); }
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); }
@Override public void onLowMemory() { super.onLowMemory(); mapView.onLowMemory(); }
}
// 自定義標記圖示
BitmapDescriptor customIcon = BitmapDescriptorFactory.fromResource(R.drawable.custom_marker);
// 圓形範圍
mMap.addCircle(new CircleOptions()
.center(taipei)
.radius(1000) // 公尺
.strokeColor(Color.BLUE)
.fillColor(Color.argb(50, 0, 0, 255)));
// 多邊形
mMap.addPolygon(new PolygonOptions()
.add(new LatLng(25.0, 121.5), new LatLng(25.1, 121.5), new LatLng(25.1, 121.6))
.strokeColor(Color.RED)
.fillColor(Color.argb(100, 255, 0, 0)));
// 地圖類型切換
mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE); // NORMAL, HYBRID, TERRAIN
| 現象 | 原因 | 解決 |
|---|---|---|
| 地圖空白/灰格 | API Key 錯誤、SHA1 不匹配、未啟用 SDK | 檢查 Console、logcat 找 "API_KEY" 錯誤訊息 |
| 定位不顯示 | 缺 ACCESS_FINE_LOCATION 權限 | 動態申請權限後 setMyLocationEnabled(true) |
| Crash: ClassNotFoundException | 缺 play-services-maps 依賴 | Gradle 加入 implementation |