country_code_locator 1.1.0
country_code_locator: ^1.1.0 copied to clipboard
Offline WGS 84 coordinate to official ISO 3166-1 Alpha-2 or Alpha-3 country code lookup for Flutter.
country_code_locator #
Offline WGS 84 coordinate-to-country-code lookup for Flutter. The package loads a bundled, versioned boundary index once and then returns an officially assigned ISO 3166-1 Alpha-2 or Alpha-3 code synchronously—without network access, GPS, permissions, a platform geocoder, or a map-service SDK.
Features #
- Fully offline lookup after package installation.
- Synchronous queries after one asynchronous initialization.
- Pure Dart spatial grid, bounding-box, and point-in-polygon implementation.
- Polygon, MultiPolygon, holes, islands, and antimeridian support.
- Deterministic shared-boundary handling independent of source row order.
- Strict official ISO Alpha-2/Alpha-3 pairs; placeholders and
XKnever escape. - Validated binary data with format versioning, lengths, semantic checks, and CRC-32 integrity protection.
- Reproducible, checksum-pinned Natural Earth data pipeline.
Install #
flutter pub add country_code_locator
The boundary asset is declared by the package. Applications do not need to add
it to their own pubspec.yaml.
Use #
Load one locator during application startup and retain it for every query:
import 'package:country_code_locator/country_code_locator.dart';
final locator = await OfflineCountryCode.load();
final alpha2 = locator.lookup(
latitude: 35.6812,
longitude: 139.7671,
); // JP (default)
final alpha3 = locator.lookup(
latitude: 35.6812,
longitude: 139.7671,
format: CountryCodeFormat.alpha3,
); // JPN
lookup returns null for ocean, uncovered or uncoded land, and a point that
matches different codes on a shared boundary.
Select CountryCodeFormat.alpha2 or CountryCodeFormat.alpha3 per lookup. Both
formats share the same loaded geometry and boundary decisions; the default
remains Alpha-2.
Input validation #
Latitude must be finite and in [-90, 90]; longitude must be finite and in
[-180, 180]. Invalid values throw ArgumentError. Longitudes -180 and
180 are treated as the same meridian.
Custom asset loading #
Applications with their own loading layer can validate and initialize directly from bytes:
final locator = OfflineCountryCode.fromBytes(bytes);
fromBytes decodes all runtime structures immediately and does not retain or
mutate the supplied Uint8List. OfflineCountryCode.load(bundle: customBundle)
is also available for a custom Flutter AssetBundle.
Result policy #
| Situation | Result |
|---|---|
| Point inside one officially coded land polygon | That uppercase official Alpha-2 or Alpha-3 code, according to format |
| Multiple matching polygons with the same code | That code |
| Boundary shared by different codes | null |
| Ocean or data gap | null |
Uncoded or non-official source region, including Kosovo/XK |
null |
| Invalid coordinate | Throws ArgumentError |
This package identifies land polygons only. It does not identify territorial waters, exclusive economic zones, addresses, administrative subdivisions, or legal sovereignty.
Data and accuracy #
The bundled asset is generated from Natural Earth 5.1.1, 1:10m Admin 0 – Map Units. Natural Earth depicts boundaries according to its de facto policy; results do not express a legal position, sovereignty claim, or diplomatic recognition.
Coordinates are quantized to 1e-5 degree and no polygon simplification or
island-area threshold is applied. Accuracy remains limited by the source map's
scale and policy. See data provenance and regeneration and the
binary format.
Natural Earth data is Public Domain. The library source is MIT licensed.
Performance #
The 1.1.0 asset is 2,573,123 bytes (2.45 MiB). A profile-mode run on a physical Pixel 10 measured 52.019 ms cold load, 8.571 µs average warm Alpha-2 lookup, 8.573 µs average warm Alpha-3 lookup, and a 13.38 MiB process-wide peak-RSS delta. These are single-run measurements, not guaranteed thresholds or evidence of improvement over another release; see PERFORMANCE.md for the workload and caveats.
Runtime lookup consults a 2° spatial grid before polygon and ring bounds. It does not scan every global polygon, reparse the asset, or copy the geometry per query.
Example #
example/lib/main.dart contains a Material 3 application with editable latitude
and longitude fields. The package test suite also covers fixed real-world
coordinates, holes, MultiPolygon members, antimeridian wrapping, ambiguity,
invalid inputs, and corrupt assets.
Updating the data #
The generator uses only the Python standard library:
python3 tool/generate_boundaries.py
python3 tool/generate_boundaries.py --check
The first command downloads the source only when the local cache is absent, verifies its SHA-256, regenerates the asset and sidecar metadata, and reports changes from the previous asset. The second regenerates in memory and fails if committed output differs. Review DATA.md before changing a pin.