Reverse Geocoding with Baidu Maps API in Android When Geocoder Fails on Android 8.0+

Applications may encounter issues where the native Geocoder class fails to resolve latitude and longitude coordinates into address information on Android 8.0 and later versions. When this occurs, a viable alternative is to leverage the Baidu Maps Web Service API for reverse geocoding.

To use the Baidu Maps API, you first need a developer account to obtain an API Key (AK). The process for obtaining an AK is straightforward and can be done through the Baidu Developer Platform.

The URL for the reverse geocoding request is as follows:

String baiduApiUrl = String.format(
        "http://api.map.baidu.com/geocoder/v2/?ak=%s&location=%s,%s&output=json&pois=1&coordtype=wgs84ll&mcode=%s",
        baiduApiKey,
        latitude,
        longitude,
        securitySignature
);

In this URL:

  • ak: Your unique Baidu API Key.
  • location: A string containing the latitude and longitude, separated by a comma.
  • output: Specifies the desired response format, typically json.
  • pois: A flag to indicate whether to include Point of Interest (POI) data. 1 enables POI retrieval, 0 disables it.
  • coordtype: Defines the coordinate system of the provided latitude and longitude. wgs84ll is used for standard GPS coordinates.
  • mcode: The security signature associated with your application, essential for secure API access.

Detailed information regarding request parameters and their meanings can be found in the official Baidu Maps API documentation. Key parameters include:

  • location: (Required) The latitude and longitude for the reverse geocoding query.
  • coordtype: (Optional) Specifies the coordinate system (e.g., bd09ll, gcj02ll, wgs84ll). Defaults to Baidu's internal coordinate system.
  • pois: (Optional) Controls the inclusion of nearby POI data. 1 for inclusion, 0 for exclusion.
  • radius: (Optional) The search radius in meters for POIs, ranging from 0 to 1000.
  • ak: (Required) Your Baidu API Key.
  • sn: (Required if SN verification is enabled for your AK) The security signature for the request.
  • output: (Optional) The format of the response (json or xml). Defaults to xml.
  • extensions_road: (Optional) Set to true to retrieve nearby road information.
  • extensions_town: (Optional) Set to true to include township-level administrative data.
  • language: (Optional) Specifies the language for administrative division names.

Up on a successful request, the API returns a JSON object containing detailed address components, location information, business districts, and nearby POIs. The status field indicates the succes or failure of the request (0 for success).

When dealing with different coordinate systems, such as converting between WGS84 (GPS), GCJ-02 (China's national standard), and BD-09 (Baidu's standard), a coordinate transformation utility class can be implemanted.

public class CoordinateConverter {

    private static final double PI = Math.PI;
    private static final double EARTH_A = 6378245.0;
    private static final double EARTH_EE = 0.00669342162296594323;
    private static final double X_PI = PI * 3000.0 / 180.0;

    /**
     * Converts WGS-84 coordinates to Baidu coordinates.
     * @param latitude The WGS-84 latitude.
     * @param longitude The WGS-84 longitude.
     * @return An array containing Baidu latitude and longitude.
     */
    public static double[] wgs84ToBaidu(double latitude, double longitude) {
        double[] gcjCoords = wgs84ToGcj02(latitude, longitude);
        return gcj02ToBaidu(gcjCoords[0], gcjCoords[1]);
    }

    /**
     * Converts GCJ-02 coordinates to Baidu coordinates.
     * @param lat GCJ-02 latitude.
     * @param lon GCJ-02 longitude.
     * @return An array containing Baidu latitude and longitude.
     */
    public static double[] gcj02ToBaidu(double lat, double lon) {
        double x = lon, y = lat;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * X_PI);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * X_PI);
        double bdLon = z * Math.cos(theta) + 0.0065;
        double bdLat = z * Math.sin(theta) + 0.006;
        return new double[] { bdLat, bdLon };
    }

    /**
     * Converts Baidu coordinates to GCJ-02 coordinates.
     * @param lat Baidu latitude.
     * @param lon Baidu longitude.
     * @return An array containing GCJ-02 latitude and longitude.
     */
    public static double[] baiduToGcj02(double lat, double lon) {
        double x = lon - 0.0065, y = lat - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
        double gcjLon = z * Math.cos(theta);
        double gcjLat = z * Math.sin(theta);
        return new double[] { gcjLat, gcjLon };
    }

    /**
     * Converts WGS-84 coordinates to GCJ-02 coordinates.
     * @param lat WGS-84 latitude.
     * @param lon WGS-84 longitude.
     * @return An array containing GCJ-02 latitude and longitude.
     */
    public static double[] wgs84ToGcj02(double lat, double lon) {
        double dLat = transformLat(lon - 105.0, lat - 35.0);
        double dLon = transformLon(lon - 105.0, lat - 35.0);
        double radLat = lat * PI / 180.0;
        double magic = Math.sin(radLat);
        magic = 1 - EARTH_EE * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((EARTH_A * (1 - EARTH_EE)) / (magic * sqrtMagic) * PI);
        dLon = (dLon * 180.0) / (EARTH_A / sqrtMagic * Math.cos(radLat) * PI);
        double mgLat = lat + dLat;
        double mgLon = lon + dLon;
        return new double[] { mgLat, mgLon };
    }

    private static double transformLat(double x, double y) {
        double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
        return ret;
    }

    private static double transformLon(double x, double y) {
        double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0;
        return ret;
    }
}

Tags: Android GPS Geocoder Baidu Maps API Reverse Geocoding

Posted on Thu, 03 Sep 2026 16:25:04 +0000 by nemethpeter