Integrating Real-Time User Location and Custom Markers with Baidu Maps on Android
Android Manifest Configuration
To enible mapping and location serviecs, you must declare the necessary permissions in your AndroidManifest.xml. These allow the application to access network states, GPS data, and storage.
<!-- Essential Permissions for Baidu Maps -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- Screen Compatibility -->
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:resizeable="true"
android:anyDensity="true"/>
Layout Implementation
Add the MapView component to your XML layout file. This component acts as the container for the map interface.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.baidu.mapapi.MapView
android:id="@+id/main_bmapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" />
</LinearLayout>
MapActivity and Location Logic
The following implementation extends MapActivity to handle the map engine initialization, user location tracking, and the rendering of custom map markers.
package com.tech.map.demo;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.baidu.mapapi.BMapManager;
import com.baidu.mapapi.GeoPoint;
import com.baidu.mapapi.ItemizedOverlay;
import com.baidu.mapapi.LocationListener;
import com.baidu.mapapi.MKGeneralListener;
import com.baidu.mapapi.MapActivity;
import com.baidu.mapapi.MapController;
import com.baidu.mapapi.MapView;
import com.baidu.mapapi.MyLocationOverlay;
import com.baidu.mapapi.OverlayItem;
import java.util.ArrayList;
import java.util.List;
public class LocationTrackingActivity extends MapActivity {
private MapView mBaiduMapView;
private BMapManager mBMapManager;
private MapController mController;
private LocationListener mLocListener;
private MyLocationOverlay mUserLocationOverlay;
private final String API_KEY = "YOUR_BAIDU_MAP_API_KEY";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_main);
mBaiduMapView = findViewById(R.id.main_bmapView);
mBMapManager = new BMapManager(this);
mBMapManager.init(API_KEY, new MKGeneralListener() {
@Override
public void onGetPermissionState(int status) {
if (status == 300) {
Toast.makeText(LocationTrackingActivity.this, "Invalid API Key!", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onGetNetworkState(int error) {
Log.e("MapError", "Network error state: " + error);
}
});
initMapActivity(mBMapManager);
mBaiduMapView.setBuiltInZoomControls(true);
mController = mBaiduMapView.getController();
mController.setZoom(14);
// Initialize user location tracking layer
mUserLocationOverlay = new MyLocationOverlay(this, mBaiduMapView);
mBaiduMapView.getOverlays().add(mUserLocationOverlay);
mLocListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
if (location != null) {
GeoPoint point = new GeoPoint((int) (location.getLatitude() * 1e6),
(int) (location.getLongitude() * 1e6));
mController.animateTo(point);
}
}
};
}
public void triggerGpsSearch(View view) {
mBMapManager.getLocationManager().requestLocationUpdates(mLocListener);
mUserLocationOverlay.enableMyLocation();
mController.zoomIn();
}
public void renderCustomPoints(View view) {
Drawable markerIcon = getResources().getDrawable(R.drawable.custom_pin_icon);
CustomMarkerOverlay customOverlay = new CustomMarkerOverlay(markerIcon);
mBaiduMapView.getOverlays().add(customOverlay);
mController.zoomIn();
}
// Inner class for managing multiple map markers
public class CustomMarkerOverlay extends ItemizedOverlay<OverlayItem> {
private List<OverlayItem> mItems = new ArrayList<>();
public CustomMarkerOverlay(Drawable marker) {
super(marker);
// Sample coordinates
double[][] coordinates = {
{31.15443, 121.57428}, {31.23443, 121.657428},
{31.22777, 121.59000}, {31.22477, 121.63000}
};
for (int i = 0; i < coordinates.length; i++) {
GeoPoint gp = new GeoPoint((int) (coordinates[i][0] * 1e6), (int) (coordinates[i][1] * 1e6));
mItems.add(new OverlayItem(gp, "Location " + (i + 1), "Details for point " + (i + 1)));
}
populate();
}
@Override
protected OverlayItem createItem(int index) {
return mItems.get(index);
}
@Override
public int size() {
return mItems.size();
}
@Override
public boolean onTap(int index) {
Toast.makeText(LocationTrackingActivity.this, mItems.get(index).getSnippet(), Toast.LENGTH_SHORT).show();
return true;
}
}
@Override
protected void onResume() {
super.onResume();
if (mBMapManager != null) {
mBMapManager.getLocationManager().requestLocationUpdates(mLocListener);
mUserLocationOverlay.enableMyLocation();
mUserLocationOverlay.enableCompass();
mBMapManager.start();
}
}
@Override
protected void onPause() {
super.onPause();
if (mBMapManager != null) {
mBMapManager.getLocationManager().removeUpdates(mLocListener);
mUserLocationOverlay.disableMyLocation();
mUserLocationOverlay.disableCompass();
mBMapManager.stop();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mBMapManager != null) {
mBMapManager.destroy();
mBMapManager = null;
}
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
}
Resource Management
It is critical to manage the BMapManager lifecycle correctly. Failure to call stop() and removeUpdates() in onPause, or destroy() in onDestroy, can lead to memory leaks and unnnecessary battery consumption by keeping GPS services active in the background.