Leku
:earth_africa: Map location picker component for Android. Based on Google Maps. An alternative to Google Place Picker.
Install / Use
/learn @AdevintaSpain/LekuREADME
Component library for Android that uses Google Maps and returns a latitude, longitude and an address based on the location picked with the Activity provided.
</div> <br/> <p align="center"> <b><a href="#features">Features</a></b> | <b><a href="#download">Download</a></b> | <b><a href="#permissions">Permissions</a></b> | <b><a href="#usage">Usage</a></b> | <b><a href="#localization">Localization</a></b> | <b><a href="#customization">Customization</a></b> | <b><a href="#tracking">Tracking</a></b> | <b><a href="#extra">Extra</a></b> | <b><a href="#who-made-this">Who Made This</a></b> | <b><a href="#apps-using-leku">Apps using Leku</a></b> | <b><a href="#contribute">Contribute</a></b> | <b><a href="#bugs-and-feedback">Bugs and Feedback</a></b> | <b><a href="#license">License</a></b> </p> <br/>Features
<img align="right" width="0" height="368px" hspace="20"/> <img src="docs/images/new_design_screenshot.png" height="368px" align="right" />- Search by voice
- Search by text
- Geo Location by GPS, network
- Google Places (optional)
- Google Time Zone API (optional)
- Pick locations using "touch" gestures on the map
- Customization (Theme and layout)
- Events Tracking
- Multi-language support (English, Spanish and Vietnamese supported by default)
- RTL (Right-To-Left) layout support <br><br><br>
Prerequisites
minSdkVersion >= 23<br/> Google Play Services = 19.0.0<br/> AndroidX
Download
Include the mavenCentral repository in your top build.gradle:
Enabled by default on AndroidStudio projects
allprojects {
mavenCentral()
}
Include the dependency in your app build.gradle:
dependencies {
implementation 'com.adevinta.android:leku:13.0.0'
}
Alternatively, if you are using a different version of Google Play Services and AndroidX use this instead:
implementation ('com.adevinta.android:leku:13.0.0') {
exclude group: 'com.google.android.gms'
exclude group: 'androidx.appcompat'
}
Troubleshoot
If you find this issue:
Execution failed for task ':app:transformClassesWithMultidexlistForDebug'. com.android.build.api.transform.TransformException: Error while generating the main dex list: Error while merging dex archives: Program type already present: com.google.common.util.concurrent.ListenableFuture Learn how to resolve the issue at https://developer.android.com/studio/build/dependencies#duplicate_classes.
The workaround for this is:
// Add this to your app build.gradle.kts file
configurations.all {
// this is a workaround for the issue:
// https://stackoverflow.com/questions/52521302/how-to-solve-program-type-already-present-com-google-common-util-concurrent-lis
exclude group: 'com.google.guava', module: 'listenablefuture'
}
Permissions
You must add the following permissions in order to use the Google Maps Android API:
-
android.permission.INTERNET Used by the API to download map tiles from Google Maps servers.
-
android.permission.ACCESS_NETWORK_STATE Allows the API to check the connection status in order to determine whether data can be downloaded.
The following permissions are not required to use Google Maps Android API v2, but are recommended.
-
android.permission.ACCESS_COARSE_LOCATION Allows the API to use WiFi or mobile cell data (or both) to determine the device's location. The API returns the location with an accuracy approximately equivalent to a city block.
-
android.permission.ACCESS_FINE_LOCATION Allows the API to determine as precise a location as possible from the available location providers, including the Global Positioning System (GPS) as well as WiFi and mobile cell data.
-
android.permission.WRITE_EXTERNAL_STORAGE Allows the API to cache map tile data in the device's external storage area.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.location.network" android:required="false" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
You must also explicitly declare that your app uses the android.hardware.location.network or android.hardware.location.gps hardware features if your app targets Android 5.0 (API level 21) or higher and uses the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission in order to receive location updates from the network or a GPS, respectively.
Note: It supports runtime permissions for Android 6 (Marshmallow). You don't need to do anything, it will ask for permissions if needed.
Usage
To use the LocationPickerActivity first you need to add these lines to your AndroidManifest file:
<activity
android:name="com.adevinta.leku.LocationPickerActivity"
android:label="@string/leku_title_activity_location_picker"
android:theme="@style/Theme.MaterialComponents.Light.NoActionBar"
android:windowSoftInputMode="adjustPan"
android:parentActivityName=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data android:name="android.app.searchable"
android:resource="@xml/leku_searchable" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>
Then you have setup the call to start this activity wherever you like, always as a ActivityResultLauncher. You can set a default location, search zone and other customizable parameters to load when you start the activity. You only need to use the Builder setters like:
val lekuActivityResultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK) {
Log.d("RESULT****", "OK")
val latitude = data?.getDoubleExtra(LATITUDE, 0.0)
Log.d("LATITUDE****", latitude.toString())
val longitude = data?.getDoubleExtra(LONGITUDE, 0.0)
Log.d("LONGITUDE****", longitude.toString())
val address = data?.getStringExtra(LOCATION_ADDRESS)
Log.d("ADDRESS****", address.toString())
val postalcode = data?.getStringExtra(ZIPCODE)
Log.d("POSTALCODE****", postalcode.toString())
val bundle = data?.getBundleExtra(TRANSITION_BUNDLE)
Log.d("BUNDLE TEXT****", bundle?.getString("test").toString())
val fullAddress = data?.getParcelableExtra<Address>(ADDRESS)
if (fullAddress != null) {
Log.d("FULL ADDRESS****", fullAddress.toString())
}
val timeZoneId = data?.getStringExtra(TIME_ZONE_ID)
if (timeZoneId != null) {
Log.d("TIME ZONE ID****", timeZoneId)
}
val timeZoneDisplayName = data?.getStringExtra(TIME_ZONE_DISPLAY_NAME)
if (timeZoneDisplayName != null) {
Log.d("TIME ZONE NAME****", timeZoneDisplayName)
}
} else {
Log.d("RESULT****", "CANCELLED")
}
}
val activity = context as MainActivity
val locationPickerIntent = LocationPickerActivity.Builder(applicationContext)
.withLocation(41.4036299, 2.1743558)
.withGeolocApiKey("<PUT API KEY HERE>")
.withGooglePlacesApiKey("<PUT API KEY HERE>")
.withSearchZone("es_ES")
.withSearchZone(SearchZoneRect(LatLng(26.525467, -18.910366), LatLng(43.906271, 5.394197)))
.withDefaultLocaleSearchZone()
.shouldReturnOkOnBackPressed()
.withStreetHidden()
.withCityHidden()
.withZipCodeHidden()
.withSatelliteViewHidden()
.withGooglePlacesEnabled()
.withGoogleTimeZoneEnabled()
.withVoiceSearchHidden()
.withUnnamedRoadHidden()
.withSolidBottomColor()
.withSearchBarHidden()
.build()
activity.lekuActivityResultLauncher.launch(locationPickerIntent)
That's all folks!
Google Places
Leku now supports Google Places queries using the search box. If you want to enable it these are the steps you need to follow:
-
Enable Google Places API for Android on your google developer console.
-
Add the key to the location picker builder
val locationPickerIntent = LocationPickerActivity.Builder(context)
.withGooglePlacesApiKey("<PUT API KEY HERE>")
If you set up the same credential for both APIs (Geo - Places) you don't need this step
And you are good to go. :)
Localization
If you would like to add more language translations the only thing you have to do is:
- Crate a new strings resource folder and file for your language like "/values-ru".
- Add all text translations for those strings:
<string name="leku_title_activity_location_picker">Location Picker</string>
<string name="leku_load_location_error">Something went wrong. Please try again.</string>
<string name="leku_no_search_results">There are no results for your search</string>
<string name="leku_unknown_location">unknown location</string>
<string name="leku_voice_search_promp">Search by voice…</
