All tutorials
Android
The what3words Free API plan will no longer include convert-to-coordinate requests. To continue using this feature, please upgrade to one of our paid plans starting from £7.99/month. Learn more about our API plans here.
As a reminder, emergency services can make use of the what3words API for free, and we have a dedicated plan for NGOs and registered charities. If your organisation falls within these categories, please get in touch. For any questions or assistance, feel free to reach out to support@what3words.com.
If you are migrating from version 3.x of the Android API Wrapper library, please refer to the Migration Guide from Version 3.x to 4.x for detailed instructions.
The Android API wrapper helps developers easily integrate the what3words API into their Android applications, avoiding the complexity of managing low-level API calls.
The what3words API allows conversion between what3words addresses (e.g., ///index.home.raft) and coordinates (e.g., -0.203586, 51.521251). It features powerful autosuggest functions to validate and autocorrect user input, restrict suggestions to specific areas, request sections of the what3words grid as GeoJSON, and list all supported languages. Advanced users can also post-process voice output with autosuggest.
All coordinates are in latitude, longitude pairs using the WGS-84 standard, with latitudes ranging from -90 to 90.
Full sample app for the wrapper can be found in our Github repo
Android Sample Apps
Installation
The library is available through Maven Central. Please add the following to your gradle.build:
android { ... compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } repositories { mavenCentral() } dependencies { implementation("com.what3words:w3w-android-wrapper:$latest_version") }
Setup
Android Manifest
Add to AndroidManifest.xml
:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yourpackage.yourapp"> <uses-permission android:name="android.permission.INTERNET" /> <!-- add if using voice api autosuggest --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> </manifest>
Usage
This step-by-step guide demonstrates the usage of the new Android API Wrapper library using Kotlin Coroutines. For a cleaner architecture or a Java example, refer to the sample app.
We’ve restructured What3WordsV3 into two distinct classes, each serving specific functions:
- W3WApiTextDataSource: Handles text-based tasks like address searching and conversions.
- W3WApiVoiceDataSource: Specialises in voice-based address suggestions.
W3WApiTextDataSource
The W3WApiTextDataSource
class facilitates the conversion of coordinates to what3words addresses and vice versa, as well as providing suggestions for slightly incomplete what3words addresses.
Create an instance of W3WApiTextDataSource via the factory method:
val textDataSource = W3WApiTextDataSource.create(context, "YOUR_API_KEY")
If you are running your own Enterprise Suite API Server, specify the URL to your server:
val textDataSource = W3WApiTextDataSource.create(context, "YOUR_API_KEY", "YOUR_SERVER_ENPOINT")
Convert Coordinates to what3words Address
This function converts coordinates (expressed as latitude and longitude) to a what3words address.
More information about convertTo3wa
, including returned results, is available in the what3words REST API documentation.
Find the words for (lat:51.222011
, long: 0.152311
):
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... val coordinates = W3WCoordinates("51.222011", "0.152311") val language = W3WRFC5646Language.EN_GB CoroutineScope(Dispatchers.IO).launch { // Run to convert method in Dispatchers.IO val result = textDataSource.convertTo3wa(coordinates, language) //Switch to Dispatcher.Main to update your views with the results if needed withContext(Dispatchers.Main) { when (result) { is W3WResult.Failure -> { Log.e("MainActivity", "Error: ${result.message}") } is W3WResult.Success -> { Log.d("MainActivity", "what3words address: ${result.value.address}") } } } } } }
Convert what3words Address to Coordinates
This function converts a 3 word address to a position, expressed as coordinates of latitude and longitude.
This function takes the words parameter as a string of what3words address e.g.filled.count.soap
More information about convertToCoordinates
, including returned results is available in the what3words REST API documentation.
Find the coordinates for ///filled.count.soap
:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... val w3wAddress = "filled.count.soap" CoroutineScope(Dispatchers.IO).launch { val result = textDataSource.convertToCoordinates(w3wAddress) withContext(Dispatchers.Main) { when (result) { is W3WResult.Failure -> { Log.e("MainActivity", "Error: ${result.message}") } is W3WResult.Success -> { Log.d("MainActivity", "Coordinates: ${result.value.center.lat}, ${result.value.center.lng}") } } } } } }
AutoSuggest
When presented with a what3words address that may be incorrectly entered, AutoSuggest returns a list of potential correct what3wordsaddresses. It needs the first two words plus at least the first character of the third word to produce suggestions.
This method provides corrections for mis-typed words (including plural vs singular), and words being in the wrong order.
Optionally, clipping can narrow down the possibilities, and limit results to:
- One or more countries
- A geographic area (a circle, box or polygon)
This dramatically improves results, so we recommend that you use clipping if possible.
To improve results even further, set the focus
to user’s current location. This will make autosuggest
return results which are closer to the user.
More information about autosuggest
, including returned results is available in the what3words REST API documentation.
Example: Basic AutoSuggest call
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... val incompletedW3WAddress = "filled.count.so" CoroutineScope(Dispatchers.IO).launch { // Run to auto suggest method in Dispatchers.IO val result = textDataSource.autosuggest(incompletedW3WAddress) //Switch to Dispatcher.Main to update your views with the results if needed withContext(Dispatchers.Main) { when (result) { is W3WResult.Failure -> { Log.e("MainActivity", "Error: ${result.message}") } is W3WResult.Success -> { if (result.value.isNotEmpty()) { Log.d("MainActivity", "Suggestions: ${result.value.joinToString { it.w3wAddress.address }}") } else { Log.d("MainActivity", "No suggestions found") } } } } } } }
Get Grid Section
Grid Section returns a section of the what3words 3m x 3m grid as a set of horizontal and vertical lines covering the requested area, which can then be drawn onto a map.
The requested box must not exceed 4km from corner to corner, or a BadBoundingBoxTooBig
error will be returned.
More information about gridSection
, including returned results is available in the what3words REST API documentation.
Get a grid for (51.222609, 0.152898
) in the south-west, and (51.222011, 0.152311
) in the north-east:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... CoroutineScope(Dispatchers.IO).launch { // Run to gridSection method in Dispatchers.IO val result = w3WApiTextDataSource.gridSection( W3WRectangle(W3WCoordinates(51.222609, 0.152898), W3WCoordinates(51.222011, 0.152311))) //Switch to Dispatcher.Main to update your views with the results if needed withContext(Dispatchers.Main) { when (result) { is W3WResult.Failure -> { Log.e("MainActivity", "Error: ${result.message}") } is W3WResult.Success -> { val gridSection = result.value // Convert to GeoJSON val geoJsonString = gridSection.toGeoJSON() } } } } } }
Get Available Languages
This function returns the currently supported languages. It will return the two letter code, and the name of the language both in that language and in English.
More information about availableLanguages
, including returned results is available in the what3words REST API documentation.
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... CoroutineScope(Dispatchers.IO).launch { // Run to availableLanguages method in Dispatchers.IO val result = textDataSource.availableLanguages() //Switch to Dispatcher.Main to update your views with the results if needed withContext(Dispatchers.Main) { when (result) { is W3WResult.Failure -> { Log.e("MainActivity", "Error: ${result.message}") } is W3WResult.Success -> { result.value.forEach { Log.d("MainActivity", "languageCode: ${it.code} - locale: ${it.locale}") } } } } } } }
W3WApiVoiceDataSource
The W3WApiVoiceDataSource
class allows searching for what3words addresses using voice input. Ensure you have a Voice API plan enabled in your account to use this feature.
Create a W3WApiVoiceDataSource Instance:
val voiceDataSource = W3WApiVoiceDataSource("YOUR_API_KEY")
If you are running your own Enterprise Suite API Server, you can specify the URL to your server:
val voiceDataSource = W3WApiVoiceDataSource("YOUR_API_KEY", "YOUR_SERVER_ENDPOINT")
Create a W3WMicrophone instance to handle voice recording:
val microphone = W3WMicrophone()
You can set up callbacks to receive information about the recording progress:
microphone.setEventsListener(object : W3WAudioStream.EventsListener { override fun onVolumeChange(volume: Float) { } override fun onError(error: W3WError) { } override fun onAudioStreamStateChange(state: W3WAudioStreamState) { } })
Perform Voice AutoSuggest
The Voice API AutoSuggest allows the user to say what3words and using speech recognition technology displays what3words address suggestions to the user.
Before enabling Voice AutoSuggest you will need to add a Voice API plan in your account.
For a full working example with voice and AUDIO_RECORD
permission, request check our sample app.
Note: Please bear in mind that the Android Emulator cannot record audio. Therefore, you will need to test on a real device that can record.
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... val voiceLanguage = W3WRFC5646Language.EN_GB CoroutineScope(Dispatchers.IO).launch { // Perform the Voice AutoSuggest in Dispatchers.IO voiceDataSource.autosuggest( microphone, voiceLanguage, null, // W3WAutosuggestOptions null, // onSpeechDetected ) { result -> //Switch to Dispatcher.Main to update your views with the results if needed withContext(Dispatchers.IO) { is W3WResult.Failure -> { Log.e("MainActivity", "Error: ${result.message}") } is W3WResult.Success -> { if (result.value.isNotEmpty()) { Log.d("MainActivity", "Suggestions: ${result.value.joinToString { it.w3wAddress.address }}") } else { Log.d("MainActivity", "No suggestions found") } } } } } } }
Using AutosuggestHelper Class
Add what3words AutoSuggest to an existing text field
Add the API and helper wherever you make your class variables and be sure to use your API key:
val dataSource = W3WApiTextDataSource.create(context, "YOUR_API_KEY_HERE") val autosuggestOptions = W3WAutosuggestOptions.Builder(). .focus(...) .clipToCountry(...) // others options as well .build() val autosuggestHelper = AutosuggestHelper(dataSource).options(autosuggestOptions)
Next step is to use a TextWatcher
(or doOnTextChanged EditText
extension) and let AutoSuggestHelper know about the changed text and add what3words suggestion data to your existing RecyclerView/Adapter. (check sample for complete working example with custom data model and RecyclerView adapter to show different autosuggest sources and EditText and RecyclerView setup.
editText.doOnTextChanged { text, _, _, _ -> // update options in case of new clippings applying/changing dynamically i.e: Location. autosuggestHelper.options(autosuggestOptions).update( text.toString(), onSuccessListener = { suggestionResults -> suggestionResults.forEach { suggestion -> //Add suggestion to existing RecyclerView adapter list.add(suggestion) Log.i("MainActivity", suggestion.w3wAddress.address) } //notify adapter that there's changes on the data. adapter.notifyDataSetChanged() }, onFailureListener = { //log any errors returned by what3words API. Log.e("MainActivity", it.message) } ) }
Get the full what3words address once the user has selected a row
When user selects a row from the RecyclerView autosuggestHelper.selected()
or autosuggestHelper.selectedWithCoordinates()
should be called to retrieve the full what3words address with or without coordinates.
Note: that selectedWithCoordinates()
will convert the what3words address to a lat/lng which will count against your plan’s quota.
autosuggestHelper.selectedWithCoordinates( query.text.toString(), selectedSuggestion, onSuccessListener = { suggestion -> Log.d("MainActivity", "suggestion selected from what3words: ${suggesstion.w3wAddress.address}, lat=${suggestion.w3wAddress.center?.lat} lng=${suggestion.w3wAddress.center?.lng}") }, onFailureListener = { Log.e("MainActivity", it.message) } )
RegEx Functions
This section introduces RegEx functions that can assist with checking and finding possible what3words addresses in strings. The three main functions covered are:
isPossible3wa
– Match what3words address format;findPossible3wa
– Find what3words address in Text;isValid3wa
– Verify a what3words address with the API;
isPossible3wa
Our API wrapper RegEx function “isPossible3wa
” can be used used to detect if a text string (like “filled.count.soap
“) in the format of a what3words address without having to ask the API. This functionality checks if a given string could be a what3words address. It returns true if it could be, otherwise false.
Note: This function checks the text format but not the validity of a what3words address. Use isValid3wa
to verify validity.
com.what3words.javawrapper.What3WordsV3.isPossible3wa("filled.count.soap") returns true com.what3words.javawrapper.What3WordsV3.isPossible3wa("not a 3wa") returns false com.what3words.javawrapper.What3WordsV3.isPossible3wa("not.3wa address") returns false
findPossible3wa
Our API wrapper RegEx function “findPossible3wa
” can be used to detect a what3words address within a block of text, useful for finding a what3words address in fields like Delivery Notes
. For example, it can locate a what3words address in a note like “Leave at my front door ///filled.count.soap
”. The function will match if there is a what3words address within the text. If no possible addresses are found, it returns an empty list.
Note:
- This function checks the text format but not the validity of a what3words address. Use
isValid3wa
to verify validity. - This function is designed to work across languages but do not work for
Vietnamese (VI)
due to spaces within words.
com.what3words.javawrapper.What3WordsV3.findPossible3wa("Please leave by my porch at filled.count.soap") returns ["filled.count.soap"] com.what3words.javawrapper.What3WordsV3.findPossible3wa("Please leave by my porch at filled.count.soap or deed.tulip.judge") returns ["filled.count.soap", "deed.tulip.judge"] com.what3words.javawrapper.What3WordsV3.findPossible3wa("Please leave by my porch at") returns []
isValid3wa
Our API wrapper RegEx function “isValid3wa
” can be used to determine if a string is a valid what3words address by checking it against the what3words RegEx filter and verifying it with the what3words API.
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... CoroutineScope(Dispatchers.IO).launch { // Run to gridSection method in Dispatchers.IO val result = w3WApiTextDataSource.isValid3wa("filled.count.soap") //Switch to Dispatcher.Main to update your views with the results if needed withContext(Dispatchers.Main) { when (result) { is W3WResult.Failure -> { Log.e("MainActivity", "Error: ${result.message}") } is W3WResult.Success -> { Log.d("MainActivity", "isValid: ${result.value}") } } } } } }
Troubleshooting
If you encounter errors or issues related to convert-to-coordinate requests while using the Free plan, please check the network panel for the following error message Error 402 payment required
and its response, indicating the need to upgrade to a higher plan:
{ "error": { "code": "QuotaExceeded", "message": "Quota Exceeded. Please upgrade your usage plan, or contact support@what3words.com" } }
For more information, visit our API plans page. If you need further assistance, contact support@what3words.com.