Unified Network Location Provider (UnifiedNlp)

repository·master·Indexed 21 days ago

https://github.com/microg/unifiednlp

A plugin-based Network Location Provider for Android that acts as a privacy-respecting middleware between the Android system and various geolocation and geocoding backends such as Mozilla, Apple, and OpenBmap. It provides a set of client APIs, including LocationClient and GeocodeClient, to manage location requests, retrieve last known locations, and configure active backends.

Tokens
5.2K
Snippets
22
Records
25
Agent score
77%

What's inside UnifiedNlp

  1. How UnifiedNlp works with backends

    master

    UnifiedNlp acts as a middleware layer and does not provide geolocation features on its own. To enable location services, you must install one or more backends (plugins). Backends can typically be found and updated via F-Droid.

    Geolocation Backends

    • AppleWifiNlpBackend: Uses Apple's service for Wi-Fi resolution.
    • OpenBmapNlpBackend: Uses openBmap (freely licensed, supports offline use).
    • MozillaNlpBackend: Uses Mozilla Location Service.
    • LocalGSMBackend: Local provider for GSM cells (works offline).
    • LocalWifiNlpBackend: Local provider using on-phone generated Wi-Fi database.

    (Reverse) Geocoding Backends

    • NominatimGeocoderBackend: Address lookup backend.

    Activation

    After installing a backend, activate it in Android settings:

    • Android 4.4+: Go to Settings -> Location and select any mode except "device only".
    • Older Android: Go to Settings -> Location -> Wi-Fi & mobile network location.
  2. Install UnifiedNlp on Android 2.3 - 4.3.1 (Legacy)

    master

    Legacy Android versions require a rooted system and the LegacyNetworkLocation.apk build. Use the following steps via ADB:

    1. Mount /system as read-write.
    2. Push LegacyNetworkLocation.apk to /system/app/.
    3. Reboot the device.
    # Mount /system read-write
    adb root && adb remount
    
    # Copy to app
    adb push LegacyNetworkLocation.apk /system/app/LegacyNetworkLocation.apk
    
    # Reboot
    adb reboot
  3. Install UnifiedNlp on Android 4.4 - 7.1.1

    master

    For most modern ROMs without Google geolocation tools, you can install NetworkLocation.apk as a standard app (ensure "Unknown sources" is enabled in Settings -> Security).

    If your system requires a system-level installation (e.g., on certain non-AOSP ROMs), use the following steps with a rooted device:

    1. Mount /system as read-write using ADB.
    2. Push NetworkLocation.apk to /system/priv-app/.
    3. Reboot the device.

    Note for Android 7+: An additional patch is required to make it work, or you must install it in /system/priv-app as described above.

    # Mount /system read-write
    adb root && adb remount
    
    # Copy to priv-app
    adb push NetworkLocation.apk /system/priv-app/NetworkLocation.apk
    
    # Reboot
    adb reboot
  4. Install Unified Network Location Provider (UnifiedNlp)

    master

    UnifiedNlp is provided in three variants depending on your Android version and whether you have Google Apps (GApps) installed:

    • NetworkLocation.apk: For standard Android 4.4+ configurations without GApps.
    • LegacyNetworkLocation.apk: For legacy Android 2.3 - 4.3.1 configurations without GApps.
    • UnifiedNlp.apk: For Android systems that already include GApps.

    Note: The microG GmsCore project already includes the Unified Network Location Provider.

    # Download release builds from the release page
    # https://github.com/microg/android_packages_apps_UnifiedNlp/releases
  5. Use GeocodeClient for geocoding services

    master

    The GeocodeClient provides an interface to interact with geocoding and reverse geocoding services. It supports both synchronous calls and Kotlin coroutines (suspend functions). It requires an Android Context and a Lifecycle object for initialization.

    Available Methods

    Geocoding (Address to Coordinates)

    • requestGeocodeSync(request: GeocodeRequest, options: Bundle = defaultOptions): List<Address>: Synchronous call to retrieve addresses based on a geocode request.
    • suspend requestGeocode(request: GeocodeRequest, options: Bundle = defaultOptions): List<Address>: Asynchronous coroutine-based call to retrieve addresses.

    Reverse Geocoding (Coordinates to Address)

    • requestReverseGeocodeSync(request: ReverseGeocodeRequest, options: Bundle = defaultOptions): List<Address>: Synchronous call to retrieve addresses based on a reverse geocode request.
    • suspend requestReverseGeocode(request: ReverseGeocodeRequest, options: Bundle = defaultOptions): List<Address>: Asynchronous coroutine-based call to retrieve addresses.

    Backend Management

    • suspend getGeocodeBackends(options: Bundle = defaultOptions): List<String>: Retrieves a list of available geocode backends.
    • suspend setGeocodeBackends(backends: List<String>, options: Bundle = defaultOptions): Unit: Sets the active geocode backends.
    // Example usage of GeocodeClient
    val client = GeocodeClient(context, lifecycle)
    
    // Asynchronous geocoding
    val addresses = client.requestGeocode(geocodeRequest)
    
    // Asynchronous reverse geocoding
    val reverseAddresses = client.requestReverseGeocode(reverseGeocodeRequest)
    
    // Managing backends
    val backends = client.getGeocodeBackends()
    client.setGeocodeBackends(listOf("backend_name"))
  6. Manage location backends in UnifiedLocationClient

    master

    You can query and set the backends used for location and geocoding services:

    • getLocationBackends(): Returns an array of strings representing available location backends.
    • setLocationBackends(backends: Array<String>): Sets the active location backends.
    • getGeocoderBackends(): Returns an array of strings representing available geocoder backends.
    • setGeocoderBackends(backends: Array<String>): Sets the active geocoder backends.
    val backends = client.getLocationBackends()
    client.setLocationBackends(arrayOf("gps", "network"))
  7. Get last known location with UnifiedLocationClient

    master

    To retrieve the most recent cached location:

    • getLastLocation(): A suspend function that returns the last known Location or null.
    • getLastLocationSync(timeout): A synchronous version of the above.
    • getLastLocationForBackend(packageName, className, signatureDigest): Retrieves the last location specifically associated with a particular backend provider.
    val lastLocation = client.getLastLocation()
  8. Implement a GeocodeProvider for plugin development

    master

    To implement a custom geocoding provider within the UnifiedNLP framework, extend the GeocodeProvider class. You must override the following core methods to handle geocoding and reverse geocoding requests:

    • onGetFromLocation: Performs reverse geocoding (converting coordinates to an address) using latitude, longitude, maxResults, params (containing locale and clientPackage), and a mutable list of Address objects to populate.
    • onGetFromLocationName: Performs forward geocoding (converting a name to coordinates/address) using the locationName, a bounding box defined by lowerLeftLatitude/lowerLeftLongitude and upperRightLatitude/upperRightLongitude, maxResults, and params.

    Note that the implementation provided in this source uses a GeocodeClient to perform synchronous requests (requestReverseGeocodeSync and requestGeocodeSync) and populates the provided addrs list.

    class MyCustomGeocodeProvider(context: Context, lifecycle: Lifecycle) : GeocodeProvider() {
    
        override fun onGetFromLocation(
            latitude: Double, 
            longitude: Double, 
            maxResults: Int, 
            params: GeocoderParams, 
            addrs: MutableList<Address>
        ): String? {
            // Implementation logic
            return null
        }
    
        override fun onGetFromLocationName(
            locationName: String?, 
            lowerLeftLatitude: Double, 
            lowerLeftLongitude: Double, 
            upperRightLatitude: Double, 
            upperRightLongitude: Double, 
            maxResults: Int, 
            params: GeocoderParams, 
            addrs: MutableList<Address>
        ): String? {
            // Implementation logic
            return null
        }
    }
  9. Perform geocoding with UnifiedLocationClient

    master

    The deprecated UnifiedLocationClient provides geocoding capabilities (converting coordinates to addresses or names to coordinates):

    • getFromLocation(latitude, longitude, maxResults, locale, timeout): A suspend function to get addresses from coordinates.
    • getFromLocationSync(...): A synchronous version of the above.
    • getFromLocationName(locationName, maxResults, lowerLeftLat, lowerLeftLong, upperRightLat, upperRightLong, locale, timeout): A suspend function to get addresses from a location name within a bounding box.
    • getFromLocationNameSync(...): A synchronous version of the above.
    // Get addresses from coordinates
    val addresses = client.getFromLocation(
        latitude = 52.52, 
        longitude = 13.40, 
        maxResults = 1, 
        locale = "en"
    )
    
    // Get addresses from a name
    val addressesByName = client.getFromLocationName(
        locationName = "Berlin",
        maxResults = 5,
        lowerLeftLatitude = 52.0,
        lowerLeftLongitude = 13.0,
        upperRightLatitude = 53.0,
        upperRightLongitude = 14.0,
        locale = "en"
    )