Saturday, September 3, 2022
HomeWordPress DevelopmentEasy Google Map App - Jetpack Compose

Easy Google Map App – Jetpack Compose


Step-by-step guides to implement Google Map app utilizing Jetpack Compose parts for the Android Maps SDK

This text was initially printed at vtsen.hashnode.dev on Aug 13, 2022.

This straightforward Google Map app is predicated on the simplified model of pattern app from this Google Map compose library. As well as, I added the next options into this pattern app:

Simple Google Map App Written in Jetpack Compose



Setup Google Cloud Undertaking

The very first thing you should do is establishing a Google cloud undertaking to generate an API key which lets you use the Google Maps SDK API.

  1. Setup New Undertaking in console.cloud.google.com
  2. In your undertaking dashboard, go to APIs overview
  3. In API & Companies web page, go to Library
  4. Seek for Maps SDK for Android and allow it
  5. Again to the API & Companies web page, go to Credentials
  6. Choose + CREATE CREDENTIALS, then choose API key
  7. The API key’s now generated. Click on on the API Key 1 to edit it. You’ll be able to rename the API key title to no matter you want. For this pattern app objective, you do not want to set any restrictions on this API key.
    • Choose None for Utility restrictions
    • Choose Do not limit key for API restrictions

These are simply temporary directions. For detailed official directions, see beneath:

Please notice I have never setup any billing account or allow billing and it nonetheless works.

After you have the API key, it’s time to implement the code.



1. Add dependencies in construct.gradle

These are the libraries wanted to make use of Google Map compose library.

implementation 'com.google.maps.android:maps-compose:2.1.1'  
implementation 'com.google.android.gms:play-services-maps:18.0.2'  
implementation "androidx.compose.basis:basis:1.2.0-beta02"
Enter fullscreen mode

Exit fullscreen mode



2. Setup Secrets and techniques Gradle Plugin

Secrets and techniques Gradle Plugin is mainly a library that can assist you conceal your API key with out committing it to the model management system.

It permits you to outline your variable (e.g. API key) within the native.properties file (which isn’t checked into model management) and retrieve the variable. For instance, you’ll be able to retrieve the variable within the AndroidManifest.xml file.

These are the steps so as to add the Secrets and techniques Gradle plugin.

In undertaking degree construct.gradle:

buildscript {  
  ...
  dependencies {  
    classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1"  
  }  
}
Enter fullscreen mode

Exit fullscreen mode

In app degree construct.gradle:

plugins {  
  ...   
  id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'  
}
Enter fullscreen mode

Exit fullscreen mode



3. Add MAPS_API_KEY in native.properties

In native.properties file, copy the API key you get from Setup Google Cloud Undertaking steps above and paste it right here.

MAPS_API_KEY=Your API Key right here
Enter fullscreen mode

Exit fullscreen mode



4. Add meta-data in AndroidManifest.xml

With a purpose to learn the MAPS_API_KEY variable that you simply outlined in native.properties, you should add the <meta-data> within the AndroidManifext.xml.

Add this <meta-data> tag throughout the <software> tag.

<software  
  ...
  <meta-data  android:title="com.google.android.geo.API_KEY"  
  android:worth="${MAPS_API_KEY}" />
  ...
</software>
Enter fullscreen mode

Exit fullscreen mode

If you don’t setup Secrets and techniques Gradle plugin above, you’re going to get this error:

Attribute meta-data#com.google.android.geo.API_KEY@worth at AndroidManifest.xml:14:13-44 requires a placeholder substitution however no worth for <MAPS_API_KEY> is supplied.
Enter fullscreen mode

Exit fullscreen mode



5. Add Web and Location Permissions

For the reason that app must entry web and site permissions, we add these permissions within the AndroidManifest.xml.

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission android:title="android.permission.INTERNET" />
    <uses-permission android:title="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:title="android.permission.ACCESS_COARSE_LOCATION" />

    ...
</manifest>
Enter fullscreen mode

Exit fullscreen mode

## 6. Implement GoogleMap() and Marker()
GoogleMap() and Marker() are the composable capabilities from the library that we will name to point out the map and the markers on the map.

The map reveals the present place if obtainable, and it’s defaulted to Sydney.

@Composable  
personal enjoyable MyGoogleMap(  
    currentLocation: Location,  
    cameraPositionState: CameraPositionState,  
    onGpsIconClick: () -> Unit) {  

    val mapUiSettings by keep in mind {  
        mutableStateOf(  
            MapUiSettings(zoomControlsEnabled = false)  
        )  
    }  

    GoogleMap(  
        modifier = Modifier.fillMaxSize(),  
        cameraPositionState = cameraPositionState,  
        uiSettings = mapUiSettings,  
    ){  
        Marker(  
            state = MarkerState(
                place = LocationUtils.getPosition(currentLocation)),  
            title = "Present Place"  
       )  
    }  

    GpsIconButton(onIconClick = onGpsIconClick)  

    DebugOverlay(cameraPositionState)  
}
Enter fullscreen mode

Exit fullscreen mode

By default, the zoom management is on. To show it off, you create a brand new MapUiSettings and move that into the GoogleMap() as parameter.

The map even have GPS icon. While you click on on it, it strikes the digicam to the present location. It additionally requests location permission and to allow machine location setting if these requests haven’t been granted earlier than.

DebugOverlay simply an overlay display screen to point out the present digicam standing and place.



7. Request Location Permission

To examine whether or not the situation permission has already been granted, you utilize ContextCompat.checkSelfPermission() API.

enjoyable isLocationPermissionGranted(context: Context) : Boolean {  
    return (ContextCompat.checkSelfPermission(  
        context, 
        Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)  
}
Enter fullscreen mode

Exit fullscreen mode

If the situation permission just isn’t granted, you setup the callback whether or not the permission is granted or denied utilizing rememberLauncherForActivityResult() with ActivityResultContracts.RequestPermission().

To request the situation permission utilizing, you name the ActivityResultLauncher.launch().

@Composable  
enjoyable LocationPermissionsDialog(  
    onPermissionGranted: () -> Unit,  
    onPermissionDenied: () -> Unit,  
) {  
    val requestLocationPermissionLauncher = rememberLauncherForActivityResult(  
        ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->  

        if (isGranted) {  
            onPermissionGranted()  
        } else {  
            onPermissionDenied()  
        }  
    }  

    SideEffect {
        requestLocationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)  
    }  
}
Enter fullscreen mode

Exit fullscreen mode

Be aware: Inititally I used the permissions library from accompanist. It labored provided that the permission is granted,. It didn’t work properly when the permission denied and I wish to request the permission once more. So I made a decision to make use of rememberLauncherForActivityResult as a substitute.



8. Allow Location Setting

When the situation permission has already granted, you wish to make sure that the situation setting is turned on. Whether it is off, you wish to request the consumer to show it on.

Much like request location permission above, you utilize rememberLauncherForActivityResult() to register allow location setting request callback.

val enableLocationSettingLauncher = rememberLauncherForActivityResult(  
    contract = ActivityResultContracts.StartIntentSenderForResult()  
) { activityResult ->  
  if (activityResult.resultCode == Exercise.RESULT_OK)  
        onSuccess()  

    else {  
        onFailure()  
    }  
}
Enter fullscreen mode

Exit fullscreen mode

To examine whether or not the situation setting is turned on, you name
SettingsClient.checkLocationSettings() API which returns the Process<LocationSettingsResponse> which lets you arrange the failure and success callbacks.

If the callback is failed, it means the machine location setting is off. In that case, you wish to request consumer to allow it (whether it is resolvable – exception is ResolvableApiException). To do this, you name ActivityResultLauncher.launch() API with the decision PendingIntent that you simply get from the exception.

val locationRequest = LocationRequest.create().apply {  
  precedence = Precedence.PRIORITY_HIGH_ACCURACY  
}  
val locationRequestBuilder = LocationSettingsRequest.Builder()  
    .addLocationRequest(locationRequest)  
val locationSettingsResponseTask = LocationServices.getSettingsClient(context)  
    .checkLocationSettings(locationRequestBuilder.construct())  

locationSettingsResponseTask.addOnSuccessListener {  
  onSuccess()  
}  

locationSettingsResponseTask.addOnFailureListener { exception ->  
  if (exception is ResolvableApiException){  
        attempt {  
            val intentSenderRequest =  
                IntentSenderRequest.Builder(exception.decision).construct()  
            enableLocationSettingLauncher.launch(intentSenderRequest)  

        } catch (sendEx: IntentSender.SendIntentException) {  
            sendEx.printStackTrace()  
        }  
    } else {  
        onFailure()  
    }  
}
Enter fullscreen mode

Exit fullscreen mode

Discuss with LocationSettingDialog() within the supply code.



8. Get the final recognized location

Lastly, you wish to get the final recognized location, which can also be a present location if the machine location setting is turned on.

First, you arrange the LocationCallback() to obtain the LocationResult which has the final recognized location info. The callback is then eliminated to save lots of energy.

To request the situation replace, you name FusedLocationProviderClient.requestLocationUpdates() API by passing within the LocationRequest, LocationCallback and Looper.

@SuppressLint("MissingPermission")  
enjoyable requestLocationResultCallback(  
    fusedLocationProviderClient: FusedLocationProviderClient,  
    locationResultCallback: (LocationResult) -> Unit  
) {  

    val locationCallback = object : LocationCallback() {  
        override enjoyable onLocationResult(locationResult: LocationResult) {  
            tremendous.onLocationResult(locationResult)  

            locationResultCallback(locationResult)  
            fusedLocationProviderClient.removeLocationUpdates(this)  
        }  
    }  

    val locationRequest = LocationRequest.create().apply {  
      interval = 0  
      fastestInterval = 0  
      precedence = Precedence.PRIORITY_HIGH_ACCURACY  
    }
    Looper.myLooper()?.let { looper ->  
    fusedLocationProviderClient.requestLocationUpdates(  
        locationRequest,  
        locationCallback,  
        looper  
        )  
    }  
}
Enter fullscreen mode

Exit fullscreen mode



Conclusion

The app requests the situation permission and request to allow location setting throughout begin up. It requests once more when the consumer click on within the GPS icon (if requests have not been granted). It additionally strikes the digicam again to present place when the GPS icon is clicked.

For particulars and if you wish to mess around with the app, seek advice from the next supply code.



Supply Code

GitHub Repository: Demo_SimpleGoogleMap



See Additionally

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments