Unable to get place predictions using new Google Places API with custom AutocompleteTextView and ArrayAdapter

24 Views Asked by At

My app intends to provide nearby places suggestion when a user is inputting his address. It will also allow the user to interact with the visible map while inputting his address where necessary.

After implementing an AutoCompleteTextView with a custom ArrayAdapter backed by static data the application worked fine.

Activity

class DeliveryDestinationMapActivity : AppCompatActivity(),
    OnMapReadyCallback,
    DeliverySummaryFragment.Callback,
    DeliverySummaryCallback, LifecycleObserver {

    private lateinit var editAutoCompleteAddress: MaterialAutoCompleteTextView
    private lateinit var placeAutocompleteAdapter: PlaceSampleAutoCompleteAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_delivery_destination_map)

        val apiKey = BuildConfig.MAPS_API_KEY
        if (apiKey.isEmpty() || (apiKey == "DEFAULT_API_KEY")) { 
            Log.e("Places test", "No api key")
            finish()
            return
        }
        Places.initializeWithNewPlacesApiEnabled(applicationContext, apiKey)
        placesApiClient = Places.createClient(this)
        
        placeAutocompleteAdapter = PlaceSampleAutoCompleteAdapter(this, placesApiClient)/*PlaceAutoCompleteArrayAdapter(this, placesApiClient)*/

        editAutoCompleteAddress = findViewById(R.id.edit_autocomplete_address)
        editAutoCompleteAddress.setAdapter(placeAutocompleteAdapter)
        editAutoCompleteAddress.onItemClickListener =
            AdapterView.OnItemClickListener { parent, view, position, id ->
                val prediction = parent.getItemAtPosition(position) as String
                val placeId = prediction
                val primaryText = prediction

                Log.i("API_EXCEPTION_TAG", "Autocomplete item selected: (placeId:$placeId) -> (primaryText:$primaryText)");

                editAutoCompleteAddress.apply {
                    setText(prediction)
                    setSelection(editAutoCompleteAddress.length())
                }
            }
    }
}

Custom ArrayAdapter with static data

class PlaceSampleAutoCompleteAdapter(context: Context, val placesApiClient: PlacesClient)
    : ArrayAdapter<String>(context, 0), Filterable {

    private val sessionToken = AutocompleteSessionToken.newInstance()
    
    private var sampleStringResultFull = mutableListOf<String>()

    override fun getCount(): Int {
        return sampleStringResultFull.size
    }

    override fun getItem(position: Int): String? {
        return sampleStringResultFull[position]
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        var rowView = convertView
        if (rowView == null) {
            rowView = LayoutInflater.from(context).inflate(R.layout.item_place_auto_complete_prediction, parent, false)
        }
        val testString = getItem(position)

        val textPlaceAddress = rowView?.findViewById<TextView>(R.id.text_title_address)
        val textPlaceCountryState = rowView?.findViewById<TextView>(R.id.text_address_country_state)
        textPlaceAddress?.text = testString
        textPlaceCountryState?.text = testString
        return rowView!!
    }

    override fun getFilter(): Filter {
        return sampleStringFilter
    }

    private val sampleStringFilter = object : Filter() {
        override fun performFiltering(constraint: CharSequence?): FilterResults {
            val filterResults = FilterResults()
            var filterData = mutableListOf<String>()

            if (!constraint.isNullOrEmpty()) {
                sampleStringResultFull.clear()
                filterData = getAutocompleteSampleStrings(constraint)
            }
            filterResults.values = filterData
            filterResults.count = filterData.size

            return filterResults
        }

        override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
            if (results != null && results.count > 0) {
                sampleStringResultFull = results.values as MutableList<String>
                notifyDataSetChanged()
            }
            else {
                notifyDataSetInvalidated()
            }
        }

        override fun convertResultToString(resultValue: Any?): CharSequence {
            if (resultValue is String) {
                return resultValue
            }
            return super.convertResultToString(resultValue)
        }
    }

    private fun getAutocompleteSampleStrings(constraint: CharSequence): MutableList<String> {
        val remoteStrings = mutableListOf<String>("Afghanistan", "Albania", "Algeria", "Armenia", "Australia", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Côte d Ivoire", "Cabo Verde", "Cambodia", "Cameroon", "Canada", "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Italy", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Montenegro", "Morocco", "Mozambique", "North Macedonia", "Norway", "Oman", "Pakistan", "Palau", "Palestine State", "Panama", "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Somalia", "South Africa", "South Korea", "South Sudan", "Spain", "Tanzania", "Thailand", "Timor-Leste", "Togo", "Tonga", "United Arab Emirates", "United Kingdom", "United States of America")
        val patterns = constraint.toString().lowercase().trim()
        remoteStrings.forEach { if (it.contains(patterns)) sampleStringResultFull.add(it)  }
        notifyDataSetChanged()
        return sampleStringResultFull
    }
}

This is my final implementation of the arrayadapter that i'm unable to make work. I have tried debugging the problem with a debugger line by line. I assume there is some sort of async problem.

Can anyone figure the problem.

Custom ArrayAdapter with remote google places predictions(function)

private fun getAutocompleteSampleStrings(constraint: CharSequence): MutableList<String> {
        var remotePredictionList = mutableListOf<String>()
        val request = FindAutocompletePredictionsRequest.builder()
            .setTypesFilter(listOf(PlaceTypes.ADDRESS, PlaceTypes.COUNTRY, PlaceTypes.GEOCODE, PlaceTypes.CITIES))
            .setSessionToken(sessionToken)
            .setQuery(constraint.toString())
            .build()

        // Perform autocomplete predictions request
        placesApiClient.findAutocompletePredictions(request)
            .addOnSuccessListener { response ->
                val predictions = response.autocompletePredictions
                clear()
                predictions.forEach { remotePredictionList.add(it.getFullText(null).toString()) }
                notifyDataSetChanged()
            }
            .addOnFailureListener { exception ->
                if (exception is com.google.android.gms.common.api.ApiException) {
                    val apiException = exception as com.google.android.gms.common.api.ApiException
                    Thread.currentThread().name
                    Log.e("API_EXCEPTION_TAG", "Place not found: " + apiException.message);
                }
            }
        return remotePredictionList
    }
0

There are 0 best solutions below