Jetpack Compose Google Places Show Nearby Places

December 16, 2021

Setup Google Places.

ViewModel

  • I am using [Hilt Dependency Injection] to inject application context into ViewModel.
  • I store GOOGLE_PLACES_API_KEY via gradle.
import com.google.android.libraries.places.api.model.Place as GooglePlace

class SelectPlaceViewModel(@ApplicationContext applicationContext: Context) : ViewModel() {
    init {
        Places.initialize(context, BuildConfig.GOOGLE_PLACES_API_KEY)
    }

    private val placesClient by lazy {  Places.createClient(applicationContext) }

    private val DEFAULT_PLACE_FIELDS = listOf(
        GooglePlace.Field.ID,
        GooglePlace.Field.NAME,
        GooglePlace.Field.ADDRESS,
        // GooglePlace.Field.ADDRESS_COMPONENTS, // not supported in placesClient.findCurrentPlace
        GooglePlace.Field.TYPES,
        GooglePlace.Field.LAT_LNG,
        GooglePlace.Field.VIEWPORT,
        GooglePlace.Field.ICON_URL
    )


    @SuppressWarnings("MissingPermission")
    suspend fun findCurrentPlaces(): List<GooglePlace> {
        val fields = DEFAULT_PLACE_FIELDS
        val request: FindCurrentPlaceRequest = FindCurrentPlaceRequest.newInstance(fields)
        val placeResponse: FindCurrentPlaceResponse = placesClient.findCurrentPlace(request).await()

        return placeResponse.placeLikelihoods.map { placeLikelihood ->
            val place: GooglePlace = placeLikelihood.place
            place
        }
    }
}

Composable

@Composable
fun SelectPlaceScreen(viewModel: SelectPlaceViewModel = viewModel()) {
    val context = LocalContext.current
    var gplaces by remember { mutableStateOf<List<GooglePlace>>( emptyList()) }
    
    LaunchedEffect(true) {
        gplaces = viewModel.findCurrentPlaces()
        // showBusy = false
    }


    RequireLocationPermission(navigateToSettingsScreen = {
        context.startActivity(
            Intent(
                Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                Uri.fromParts("package", context.packageName, null)
            )
        )
    }) {
        LazyColumn() {
            items(gplaces) { place ->
                Row {
                    Icon(
                        modifier = Modifier
                            .padding(4.dp)
                            .size(24.dp),
                        // painter = painterResource(icon),
                        painter = rememberImagePainter(place.iconUrl!!),
                        contentDescription = "")
                    Column {
                        Text(place.name ?: "NA", style = MaterialTheme.typography.subtitle1)
                        CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
                            Text(place.address ?: "", style = MaterialTheme.typography.body2)
                        }
                    }
                }

                Divider(color = MaterialTheme.colors.onSurface.copy(alpha = 0.2f))
            }
        }
    }
}
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.