Skip to content

Feature/improved search and results #273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions geocoding/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 4.1.0

* Added the ability to refine address search by geographic location
* The search results' Location object now have new `title` and `description` fields

## 4.0.0

* **BREAKING CHANGES** Please update to Flutter 3.29+ before updating to this version
Expand Down
6 changes: 4 additions & 2 deletions geocoding/lib/geocoding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ export 'package:geocoding_platform_interface/geocoding_platform_interface.dart';
/// resolved into a single [Location], multiple [Location] instances may be
/// returned.
Future<List<Location>> locationFromAddress(
String address,
) =>
String address, {
Region? targetRegion,
}) =>
GeocodingPlatform.instance!.locationFromAddress(
address,
targetRegion: targetRegion,
);

/// Returns a list of [Placemark] instances found for the supplied
Expand Down
8 changes: 4 additions & 4 deletions geocoding/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: geocoding
description: A Flutter Geocoding plugin which provides easy geocoding and reverse-geocoding features.
version: 4.0.0
version: 4.1.0
repository: https://github.com/baseflow/flutter-geocoding/tree/main/geocoding
issue_tracker: https://github.com/Baseflow/flutter-geocoding/issues

Expand All @@ -12,9 +12,9 @@ dependencies:
flutter:
sdk: flutter

geocoding_platform_interface: ^3.0.0
geocoding_android: ^4.0.0
geocoding_ios: ^3.0.0
geocoding_platform_interface: ^4.0.0
geocoding_android: ^4.1.0
geocoding_ios: ^3.1.0

dev_dependencies:
flutter_test:
Expand Down
7 changes: 5 additions & 2 deletions geocoding/test/geocoding_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import 'package:mockito/mockito.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';

final mockLocation = Location(
title: '',
description: '',
latitude: 52.2165157,
longitude: 6.9437819,
timestamp: DateTime.fromMillisecondsSinceEpoch(0).toUtc(),
Expand Down Expand Up @@ -48,8 +50,9 @@ class MockGeocodingPlatform extends Mock
GeocodingPlatform {
@override
Future<List<Location>> locationFromAddress(
String address,
) async {
String address, {
Region? targetRegion,
}) async {
return [mockLocation];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,37 @@ boolean isPresent() {
* @param callback the GeocodeListenerAdapter that listens for success or error
* @return a list of Address objects. Returns null or empty list if no matches were found or there is no backend service available.
*/
void placemarkFromAddress(String address, GeocodeListenerAdapter callback) {
void placemarkFromAddress(
String address,
Double lowerLeftLatitude,
Double lowerLeftLongitude,
Double upperRightLatitude,
Double upperRightLongitude,
GeocodeListenerAdapter callback
) {
final Geocoder geocoder = createGeocoder(androidContext, locale);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getAddressesWithGeocodeListener(geocoder, address, 5, callback);
getAddressesWithGeocodeListener(
geocoder,
address,
5,
lowerLeftLatitude,
lowerLeftLongitude,
upperRightLatitude,
upperRightLongitude,
callback
);
} else {
try {
List<Address> addresses = deprecatedGetFromLocationName(geocoder, address);
List<Address> addresses = deprecatedGetFromLocationName(
geocoder,
address,
lowerLeftLatitude,
lowerLeftLongitude,
upperRightLatitude,
upperRightLongitude
);
callback.onGeocode(addresses);
} catch (IOException ex) {
callback.onError(ex.getMessage());
Expand All @@ -68,13 +91,33 @@ void placemarkFromAddress(String address, GeocodeListenerAdapter callback) {
}

@SuppressWarnings("deprecation")
private List<Address> deprecatedGetFromLocationName(Geocoder geocoder, String address) throws IOException {
return geocoder.getFromLocationName(address, 5);
private List<Address> deprecatedGetFromLocationName(
Geocoder geocoder,
String address,
Double lowerLeftLatitude,
Double lowerLeftLongitude,
Double upperRightLatitude,
Double upperRightLongitude
) throws IOException {
if (lowerLeftLatitude == null || lowerLeftLongitude == null || upperRightLatitude == null || upperRightLongitude == null) {
return geocoder.getFromLocationName(address, 5);
} else {
return geocoder.getFromLocationName(address, 5, lowerLeftLatitude, lowerLeftLongitude, upperRightLatitude, upperRightLongitude);
}
}

@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
private void getAddressesWithGeocodeListener(Geocoder geocoder, String address, int maxResults, GeocodeListenerAdapter callback) {
geocoder.getFromLocationName(address, maxResults, new Geocoder.GeocodeListener() {
private void getAddressesWithGeocodeListener(
Geocoder geocoder,
String address,
int maxResults,
Double lowerLeftLatitude,
Double lowerLeftLongitude,
Double upperRightLatitude,
Double upperRightLongitude,
GeocodeListenerAdapter callback
) {
final Geocoder.GeocodeListener listener = new Geocoder.GeocodeListener() {
@Override
public void onGeocode(List<Address> geocodedAddresses) {
callback.onGeocode(geocodedAddresses);
Expand All @@ -84,7 +127,12 @@ public void onGeocode(List<Address> geocodedAddresses) {
public void onError(@Nullable String errorMessage) {
callback.onError(errorMessage);
}
});
};
if (lowerLeftLatitude == null || lowerLeftLongitude == null || upperRightLatitude == null || upperRightLongitude == null) {
geocoder.getFromLocationName(address, maxResults, listener);
} else {
geocoder.getFromLocationName(address, maxResults, lowerLeftLatitude, lowerLeftLongitude, upperRightLatitude, upperRightLongitude, listener);
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@ private void setLocaleIdentifier(MethodCall call, Result result) {
result.success(true);
}

// Parses a string as a double and returns the parsed value.
// If parsing is not possible or fails, returns null.
private static Double parseDoubleOrReturnNull(final String _string){
try{
return Double.parseDouble(_string);
}catch (Throwable t){
return null;
}
}

private void onLocationFromAddress(MethodCall call, Result result) {
final String address = call.argument("address");

Expand All @@ -114,8 +124,13 @@ private void onLocationFromAddress(MethodCall call, Result result) {
null);
}

geocoding.placemarkFromAddress(address, new GeocodeListenerAdapter() {

geocoding.placemarkFromAddress(
address,
parseDoubleOrReturnNull(call.argument("targetRegionSLat")), // lowerLeftLatitude,
parseDoubleOrReturnNull(call.argument("targetRegionWLng")), // lowerLeftLongitude,
parseDoubleOrReturnNull(call.argument("targetRegionNLat")), // upperRightLatitude,
parseDoubleOrReturnNull(call.argument("targetRegionELng")), // upperRightLongitude
new GeocodeListenerAdapter() {
@Override
public void onGeocode(List<Address> addresses) {
if (addresses != null && addresses.size() > 0) {
Expand Down Expand Up @@ -148,8 +163,13 @@ private void onPlacemarkFromAddress(final MethodCall call, final Result result)
null);
}

geocoding.placemarkFromAddress(address, new GeocodeListenerAdapter() {

geocoding.placemarkFromAddress(
address,
parseDoubleOrReturnNull(call.argument("targetRegionSLat")), // lowerLeftLatitude,
parseDoubleOrReturnNull(call.argument("targetRegionWLng")), // lowerLeftLongitude,
parseDoubleOrReturnNull(call.argument("targetRegionNLat")), // upperRightLatitude,
parseDoubleOrReturnNull(call.argument("targetRegionELng")), // upperRightLongitude
new GeocodeListenerAdapter() {
@Override
public void onGeocode(List<Address> addresses) {
if (addresses != null && addresses.size() > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ public static List<Map<String, Object>> toLocationHashMapList(List<Address> addr
private static Map<String, Object> toLocationHashmap(Address address) {
Map<String, Object> location = new HashMap<>();

location.put("title", address.getFeatureName());
{
final int maxAddressLineIndex = address.getMaxAddressLineIndex();
final StringBuilder descriptionString = new StringBuilder();
for (int i = 0; i <= maxAddressLineIndex; i++) {
if (i > 0) {
descriptionString.append("\n");
}
descriptionString.append(address.getAddressLine(i));
}
location.put("description", descriptionString.toString());
}
location.put("latitude", address.getLatitude());
location.put("longitude", address.getLongitude());
location.put("timestamp", Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTimeInMillis());
Expand Down
5 changes: 3 additions & 2 deletions geocoding_android/lib/geocoding_android.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ class GeocodingAndroid extends GeocodingPlatform {

@override
Future<List<Location>> locationFromAddress(
String address,
) async {
String address, {
Region? targetRegion,
}) async {
final parameters = <String, String>{
'address': address,
};
Expand Down
4 changes: 2 additions & 2 deletions geocoding_android/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: geocoding_android
description: A Flutter Geocoding plugin which provides easy geocoding and reverse-geocoding features.
version: 4.0.1
version: 4.1.0
repository: https://github.com/baseflow/flutter-geocoding/tree/main/geocoding_android
issue_tracker: https://github.com/Baseflow/flutter-geocoding/issues

Expand All @@ -12,7 +12,7 @@ dependencies:
flutter:
sdk: flutter

geocoding_platform_interface: ^3.2.0
geocoding_platform_interface: ^4.0.0

dev_dependencies:
flutter_test:
Expand Down
2 changes: 2 additions & 0 deletions geocoding_android/test/geocoding_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import 'package:geocoding_android/geocoding_android.dart';
import 'package:geocoding_platform_interface/geocoding_platform_interface.dart';

final mockLocation = Location(
title: '',
description: '',
latitude: 52.2165157,
longitude: 6.9437819,
timestamp: DateTime.fromMillisecondsSinceEpoch(0).toUtc(),
Expand Down
4 changes: 4 additions & 0 deletions geocoding_ios/ios/Classes/Extensions/CLPlacemarkExtensions.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ - (NSDictionary *)toLocationDictionary {
if (self.location == nil) {
return nil;
}

NSArray *lines = self.addressDictionary[@"FormattedAddressLines"];

NSMutableDictionary<NSString *, NSObject*> *dict = [[NSMutableDictionary alloc] initWithDictionary:@{
@"title": self.name,
@"description": [lines componentsJoinedByString:@", "] ?: [NSNull null],
@"latitude": @(self.location.coordinate.latitude),
@"longitude": @(self.location.coordinate.longitude),
@"timestamp": @([CLPlacemark currentTimeInMilliSeconds: self.location.timestamp]),
Expand Down
4 changes: 4 additions & 0 deletions geocoding_ios/ios/Classes/GeocodingHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ typedef void (^GeocodingFailure)(NSString* errorCode, NSString* errorDescription

- (void) geocodeFromAddress: (NSString *)address
locale: (NSLocale *)locale
sLat: (CGFloat)sLat
wLng: (CGFloat)sLng
nLat: (CGFloat)nLat
eLng: (CGFloat)nLng
success: (_Nonnull GeocodingSuccess)successHandler
failure: (_Nonnull GeocodingFailure)failureHandler;

Expand Down
20 changes: 18 additions & 2 deletions geocoding_ios/ios/Classes/GeocodingHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,32 @@ - (id)init {

- (void) geocodeFromAddress: (NSString *)address
locale: (NSLocale *)locale
sLat: (CGFloat) sLat
wLng: (CGFloat) sLng
nLat: (CGFloat) nLat
eLng: (CGFloat) nLng
success: (GeocodingSuccess)successHandler
failure: (GeocodingFailure)failureHandler {

if (address == nil) {
failureHandler(@"ARGUMENT_ERROR", @"Please supply a valid string containing the address to lookup");
return;
}


CLRegion* region;
if (sLat == 0 || sLng == 0 || nLat == 0 || nLng == 0){
region = nil;
}else{
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(sLat + (nLat-sLat) / 2, sLng + (nLng-sLng) / 2);
//Computing the radius based on lat delta, since 1 lat = 111 km no matter the location
float latDelta = nLat - sLat;
float radiusLat = (latDelta/2);
float radius = radiusLat * 111000;
region = [[CLCircularRegion alloc] initWithCenter:center radius:radius identifier:@"Search Radius"];
}

[_geocoder geocodeAddressString:address
inRegion:nil
inRegion:region
preferredLocale:locale
completionHandler:^(NSArray< CLPlacemark *> *__nullable placemarks, NSError *__nullable error)
{
Expand Down
14 changes: 14 additions & 0 deletions geocoding_ios/ios/Classes/GeocodingPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,27 @@ + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
[registrar addMethodCallDelegate:instance channel:channel];
}

+ (CGFloat) parseCGFloat:(NSString*)numberString {
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle=NSNumberFormatterDecimalStyle;
return [[formatter numberFromString:numberString] doubleValue];
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([@"locationFromAddress" isEqualToString:call.method]) {
NSString* address = call.arguments[@"address"];
NSString* targetRegionSLat = call.arguments[@"targetRegionSLat"];
NSString* targetRegionNLat = call.arguments[@"targetRegionNLat"];
NSString* targetRegionWLng = call.arguments[@"targetRegionWLng"];
NSString* targetRegionELng = call.arguments[@"targetRegionELng"];

GeocodingHandler* handler = [[GeocodingHandler alloc] init];
[handler geocodeFromAddress:address
locale:[GeocodingPlugin parseLocale: call.arguments]
sLat:[GeocodingPlugin parseCGFloat: targetRegionSLat]
wLng:[GeocodingPlugin parseCGFloat: targetRegionWLng]
nLat:[GeocodingPlugin parseCGFloat: targetRegionNLat]
eLng:[GeocodingPlugin parseCGFloat: targetRegionELng]
success:^(NSArray<CLPlacemark *> * placemarks) {
result([GeocodingPlugin toLocationResult: placemarks]);
}
Expand Down
5 changes: 4 additions & 1 deletion geocoding_ios/lib/geocoding_ios.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ class GeocodingIOS extends GeocodingPlatform {
}

@override
Future<List<Location>> locationFromAddress(String address) async {
Future<List<Location>> locationFromAddress(
String address, {
Region? targetRegion,
}) async {
final parameters = <String, String>{
'address': address,
};
Expand Down
4 changes: 2 additions & 2 deletions geocoding_ios/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: geocoding_ios
description: A Flutter Geocoding plugin which provides easy geocoding and reverse-geocoding features.
version: 3.0.2
version: 3.1.0
repository: https://github.com/baseflow/flutter-geocoding/tree/main/geocoding_ios
issue_tracker: https://github.com/Baseflow/flutter-geocoding/issues

Expand All @@ -12,7 +12,7 @@ dependencies:
flutter:
sdk: flutter

geocoding_platform_interface: ^3.2.0
geocoding_platform_interface: ^4.0.0

dev_dependencies:
flutter_test:
Expand Down
2 changes: 2 additions & 0 deletions geocoding_ios/test/geocoding_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import 'package:geocoding_ios/geocoding_ios.dart';
import 'package:geocoding_platform_interface/geocoding_platform_interface.dart';

final mockLocation = Location(
title: '',
description: '',
latitude: 52.2165157,
longitude: 6.9437819,
timestamp: DateTime.fromMillisecondsSinceEpoch(0).toUtc(),
Expand Down
Loading