DEV Community

Cover image for How to Automatically Fill Addresses in Lifestyle Apps
Jackson for HMS Core

Posted on

How to Automatically Fill Addresses in Lifestyle Apps

Filling in addresses is a task that users of lifestyle apps and mini programs that provide services such as group buying, takeout, package delivery, housekeeping, logistics, and moving services often have to perform. Generally, this requires users to manually fill in their address information, for example, selecting California, Los Angeles, and Hollywood Blvd in sequence using several drop-down list boxes and then manually entering their names and phone numbers. This process usually takes some time and is prone to input error.

Wouldn't it be handy if there was an automatic way for users to fill in addresses quickly and accurately? With HMS Core Location Kit's fused location and geocoding capabilities, a lifestyle app can automatically pinpoint the current location of a user or obtain the street address of a map location, and fill that information in the address box. Thanks to this, users are freed from the hassle of having to manually enter addresses, as well preventing human error. In this article, I will explain how you can easily integrate this feature into your app and provide you with sample code.

Demo

Demo Result

Development Procedure

Prepare for the development

1.Sign in to AppGallery Connect and click My projects. Find your project, go to Project settings > Manage APIs, and toggle on the Location Kit switch. Then, click the app for which you need to configure the signing certificate fingerprint, and go to Project settings > General information. In the App information area, click Add next to SHA-256 certificate fingerprint, and enter the SHA-256 certificate fingerprint.

2.Go to Project settings > General information. In the App information area, click agconnect-services.json to download the configuration file. Then, copy the configuration file to the app's root directory.

3.Configure the project-level build.gradle file.

buildscript {
    repositories {
        google()
        jcenter()
        maven { url 'https://developer.huawei.com/repo/' }
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.2'
        classpath 'com.huawei.agconnect:agcp:1.6.0.300'
    }
}

allprojects {
    repositories {
        maven { url 'https://developer.huawei.com/repo/' }
        google()
        jcenter()
        mavenCentral()
    }
}
Enter fullscreen mode Exit fullscreen mode

Configure the app-level build.gradle file.

plugins {
    id 'com.android.application'
    id 'com.huawei.agconnect'
}
Enter fullscreen mode Exit fullscreen mode

Add the following build dependency in the dependencies block in the app-level build.gradle file:

implementation 'com.huawei.hms:location:6.3.0.300'
Enter fullscreen mode Exit fullscreen mode

Check permissions

1.Declare the ACCESS_COARSE_LOCATION (approximate location permission), ACCESS_FINE_LOCATION (precise location permission), and ACCESS_BACKGROUND_LOCATION permissions in the AndroidManifest.xml file.

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
Enter fullscreen mode Exit fullscreen mode

2.Dynamically apply for related location permissions (according to requirements for dangerous permissions in Android 6.0 or later).

if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
    Log.i(TAG, "android sdk < 28 Q");
    if (ActivityCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        String[] strings =
                {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
        ActivityCompat.requestPermissions(this, strings, 1);
    }
} else {
    if (ActivityCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this,
            "android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
        String[] strings = {Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION,
                "android.permission.ACCESS_BACKGROUND_LOCATION"};
        ActivityCompat.requestPermissions(this, strings, 2);
    }
}
Enter fullscreen mode Exit fullscreen mode

Obtain the location result

1.Set location parameters, including the location update interval and location type

mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
mSettingsClient = LocationServices.getSettingsClient(this);
mLocationRequest = new LocationRequest();
// Set the location update interval, in milliseconds. 
mLocationRequest.setInterval(5000);
// Set the priority.
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
Enter fullscreen mode Exit fullscreen mode

2.Call the getSettingsClient() method to obtain a SettingsClient instance, and call checkLocationSettings() to check the device location settings.

LocationSettingsRequest locationSettingsRequest = builder.build();
// Before requesting location updates, call checkLocationSettings to check the device location settings.
Task<LocationSettingsResponse> locationSettingsResponseTask =
        mSettingsClient.checkLocationSettings(locationSettingsRequest);
Enter fullscreen mode Exit fullscreen mode

After checking that the device location function is enabled, call requestLocationUpdates() to request location updates.

locationSettingsResponseTask.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
    @Override
    public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
        Log.i(TAG, "check location settings success");
        mFusedLocationProviderClient
                .requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.getMainLooper())
                .addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        Log.i(TAG, "requestLocationUpdatesWithCallback onSuccess");
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(Exception e) {
                        Log.e(TAG, "requestLocationUpdatesWithCallback onFailure:" + e.getMessage());
                    }
                });
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(Exception e) {
        Log.e(TAG, "checkLocationSetting onFailure:" + e.getMessage());
        int statusCode = 0;
        if (e instanceof ApiException) {
            statusCode = ((ApiException) e).getStatusCode();
        }
        switch (statusCode) {
            case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                try {
                    // When startResolutionForResult is called, a popup will 
                    // appear, asking the user to grant relevant permissions.
                    if (e instanceof ResolvableApiException) {
                        ResolvableApiException rae = (ResolvableApiException) e;
                        rae.startResolutionForResult(MainActivity.this, 0);
                    }
                } catch (IntentSender.SendIntentException sie) {
                    Log.e(TAG, "PendingIntent unable to execute request.");
                }
                break;
            default:
                break;
        }
    }
});
Enter fullscreen mode Exit fullscreen mode

Obtain the address of the current location through reverse geocoding

After obtaining the longitude and latitude of a location, pass them to the geocoding service (GeocoderService) to obtain a geocoding request object. Then, call the getFromLocation method and set request (GetFromLocationRequest) parameters to obtain the address of the location.

if (null == mLocationCallback) {
    mLocationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            if (locationResult != null) {
                List<Location> locations = locationResult.getLocations();
                if (!locations.isEmpty()) {
                    ExecutorUtil.getInstance().execute(new Runnable() {
                        @Override
                        public void run() {
                            Locale locale = new Locale("zh", "CN");
                            GeocoderService geocoderService = LocationServices.getGeocoderService(MainActivity.this, locale);
                            GetFromLocationRequest getFromLocationRequest = new GetFromLocationRequest(locations.get(0).getLatitude(), locations.get(0).getLongitude(), 1);
                            geocoderService.getFromLocation(getFromLocationRequest)
                                    .addOnSuccessListener(new OnSuccessListener<List<HWLocation>>() {
                                        @Override
                                        public void onSuccess(List<HWLocation> hwLocation) {
                                            printGeocoderResult(hwLocation);
                                        }
                                    })
                                    .addOnFailureListener(new OnFailureListener() {
                                        @Override
                                        public void onFailure(Exception e) {
                                            Log.i(TAG, e.getMessage());
                                        }
                                    });
                        }
                    });
                }
            }
        }
        @Override
        public void onLocationAvailability(LocationAvailability locationAvailability) {
            if (locationAvailability != null) {
                boolean flag = locationAvailability.isLocationAvailable();
                Log.i(TAG, "onLocationAvailability isLocationAvailable:" + flag);
            }
        }
    };
}
Enter fullscreen mode Exit fullscreen mode

Finally, display the obtained address on the screen to complete the implementation.

References

Location Kit official website
Location Kit Development Guide
Reddit to join developer discussions
GitHub to download the sample code
Stack Overflow to solve integration problems

Top comments (0)