Share
Explore

Google Location Services, Maps, Markers v c302

The Completed Project:
You can either rebuild City Maps from the instructions below, or jump ahead to read the last chapter by getting the finalize Project and studying along here:

Here we work with Google Maps API, which we must register to use.
Start by visiting https://console.cloud.google.com
and Creating a Project and an API Key:

Make an Android to do the following:
How to use the Google Maps Android API
The Google Location Services API
Show a user’s current location
Display and customize markers on a map
Display a specifed address on the map.
image.png


In creating a new lab project for building an Android app with Kotlin DSL that integrates Google Maps and location services, we will ensure that all parts of the project are consistent and use Kotlin DSL formulations.
The project will be called `myapp`.

In the Create New Project dialog, on the Create Android Project view, enter the name of the app as myapp if you wish to remain congruent with the package naming conventions in these code templates. If you name your App something else, just change the applicable package import strings.
Select your preferred folder location for the project files, make sure that Include Kotlin support, and click Next:

On the Target Android Devices view, check the Phone and Tablet box and select the minimum SDK you want the app to support. Specify API 16 from the Minimum SDK drop down and click Next.

On the Add an Activity to Mobile view, select the Google Maps Activity and click Next.
Create the standard empty activities template and do a special procedure to add maps support:
image.png
On the Configure Activity view, click Finish to complete the project creation process.

Android Studio will use Gradle to build your project. This may take a few seconds.
{When you update your starter template, frequently do File - Sync Project with Gradle Files, and do Build - Clean/ Rebuild / Make Project.


Lab Structure Overview:


1. **MainActivity.kt**:
Kotlin source file for the main activity handling user interactions with the map and location services.
2. **activity_main.xml**:
Layout file defining the UI, including the map view and address input.
3. **Project-level build.gradle.kts**:
Kotlin DSL file to configure project-wide settings like repositories and classpath dependencies.
4. **Module-level build.gradle.kts (app)**:
Kotlin DSL file for app-specific configurations like dependencies and Android-specific settings.
5. **settings.gradle.kts**:
Settings file for the project, specifying plugin management and resolution strategy.

Open MapsActivity.kt. Add the project code shown here :

image.png


MainActivity.kt : To have a complete and functional MainActivity.kt file.
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions

class MainActivity : AppCompatActivity(), OnMapReadyCallback {

private lateinit var mMap: GoogleMap
private val LOCATION_PERMISSION_REQUEST = 1

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// Obtain the SupportMapFragment and get notified when the map is ready to be used.
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment?
mapFragment?.getMapAsync(this)

// Check if we have location permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Request the permission
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
LOCATION_PERMISSION_REQUEST)
}
}

override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap

// Add a marker in Sydney, Australia, and move the camera
val sydney = LatLng(-34.0, 151.0)
mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))

// If we have location permission, enable the My Location layer
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mMap.isMyLocationEnabled = true
}
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
LOCATION_PERMISSION_REQUEST -> {
// If request is cancelled, the result arrays are empty.
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
// Permission was granted, do the location-related task you need to do.
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if(::mMap.isInitialized) {
mMap.isMyLocationEnabled = true
}
// activity_main.xml

To provide a complete activity_main.xml that includes a Google Map view and address input UI components, we can incorporate a SupportMapFragment to display the map and an EditText for user input to enter an address.
Additionally, we'll add a Button to trigger the map centering on the address entered. Here's the updated activity_main.xml:


Below is the updated activity_main.xml file that includes the SupportMapFragment for displaying Google Maps. This code assumes you want the map to fill the entire screen of the activity.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</RelativeLayout>

This XML layout file defines a single SupportMapFragment that takes up the entire screen, as indicated by match_parent for both layout_width and layout_height. Once this file is set up, you can run your application, and it should display the map.
Remember to handle runtime permissions for accessing the location if you plan on showing the user's current location or any features that require location access.

You also need to implement the OnMapReadyCallback in your MainActivity to interact with the map once it's ready.



Here's a simple strings.xml file for your Android project that includes strings for the UI components in activity_main.xml:

<resources>
<string name="app_name">MyApp</string>
<string name="enter_address">Enter an address</string>
<string name="find_location">Find Location</string>
<!-- Add other strings for your app here -->
</resources>

In this strings.xml file:

The app_name string is the name of your application.
The enter_address string is used as a hint in the EditText where users will input an address.

The find_location string is the text on the Button that users can click to find the location they entered.

The strings.xml file is usually located in the res/values/ directory of your Android project. It's a good practice to use the strings.xml file for all user-facing text in your app, as it simplifies localization and maintenance.

To ensure the new lab app for location tracking and Google Maps integration is complete and functional, we need to ensure several components and configurations are correctly addressed:

AndroidManifest.xml: You need the proper permissions and metadata for Google Maps and location services:

Complete version of the AndroidManifest.xml for an application that uses Google Maps and location services:

Here's the completely updated AndroidManifest.xml file for your Android app with Google Maps integration. This includes all the necessary permissions and the Google Maps API key configuration:

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

<!-- Permissions for Google Maps and Location -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<!-- Google Maps API Key -->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_API_KEY_HERE"/>

<!-- Main Activity -->
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Additional activities and services if necessary -->
</application>
</manifest>

Make sure to replace "YOUR_API_KEY_HERE" with your actual Google Maps API key. Adjust the android:icon, android:label, and android:theme attributes to match your application's resources.

This AndroidManifest.xml sets up the necessary permissions for using Google Maps and accessing location services, and it defines the main entry point for your application.

Remember, if your app targets Android 10 (API level 29) or higher and needs to access the location in the background, you'll need to request the ACCESS_BACKGROUND_LOCATION permission as well. Also, from Android 6.0 (Marshmallow) onwards, you must request location permissions at runtime in addition to declaring them in the manifest.

Remember to sync your project with the updated manifest file after making changes.



Project-Level build.gradle.kts:```kotlin // Project-level build.gradle.kts
buildscript { repositories { google() mavenCentral() } dependencies { // Define classpath for Google Services and Android Gradle Plugin using compatible versions } }
plugins { id("com.android.application") version "<version>" apply false id("org.jetbrains.kotlin.android") version "<version>" apply false }
allprojects { repositories { google() mavenCentral() } }
tasks.register("clean", Delete::class) { delete(rootProject.buildDir) } ```

Module-Level build.gradle.kts (app): ```kotlin // Module-level build.gradle.kts
plugins { id("com.android.application") kotlin("android") // Add other plugins like kotlin-parcelize if needed }
android { // Define compileSdk, defaultConfig, buildTypes, and other Android configurations }
dependencies { // Include necessary dependencies like Kotlin standard library, Google Maps, Location Services, and others } ```

settings.gradle.kts: ```kotlin // settings.gradle.kts
pluginManagement { repositories { google() mavenCentral() gradlePluginPortal() } }
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) repositories { google() mavenCentral() } }
rootProject.name = "myapp" include(":app") ```
Instructions to create this App:
1. **Setting Up the Project**:
- Create a new project in Android Studio with a Google Maps Activity. - Name the project `myapp`.

2. **Google Maps API Key**: - Ensure you have a valid Google Maps API key. - Add the API key to your project's `AndroidManifest.xml`.

3. **Adding Dependencies**: - Add dependencies for Google Maps and location services in your module-level `build.gradle.kts` file.

4. **Writing Code**: - Implement `MainActivity.kt` to handle map display and location updates. - Design `activity_main.xml` with a map view and UI controls for user inputs. - Use View Bindings to reference UI components in your Kotlin code. - Utilize `setOnClickListener` for button interaction.

5. **Working with GeoJSON**: - If working with simulated location data, parse GeoJSON files using Gson in Kotlin.

6. **Running the App**: - Test your app in an Android Virtual Device (AVD) to ensure location services and map integration work as expected.


Below is the updated activity_main.xml file that includes the SupportMapFragment for displaying Google Maps. This code assumes you want the map to fill the entire screen of the activity.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</RelativeLayout>

This XML layout file defines a single SupportMapFragment that takes up the entire screen, as indicated by match_parent for both layout_width and layout_height. Once this file is set up, you can run your application, and it should display the map.
Remember to handle runtime permissions for accessing the location if you plan on showing the user's current location or any features that require location access. You also need to implement the OnMapReadyCallback in your MainActivity to interact with the map once it's ready. If you have any further customizations or features, they will need to be added accordingly.

megaphone

Now that you have made it this far:

Give into your obessive compulsive need to do : FILE →Sync Project with Gradle Files.
If you get depreciation warnings, note them to address later. For example, in my project here, I am told that Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0. We are still at Gradle 8.6, so not a rush.

DO one final BUILD → Make Project


Did you get something that looks like this?
BUILD SUCCESSFUL in 329ms 58 actionable tasks: 58 up-to-date
Build Analyzer results available

Your application has built successfully without any errors. This means all the files are in place and correctly set up for your application to run, including your `MainActivity.kt` with the Google Maps fragment implemented.
With the successful build, you're now at the exciting stage where you can run your application and see the Google Maps view live on an Android emulator or device.
Here is what you do next:

1. Run the App:
Click the green play button in Android Studio, or use the `Shift + F10` shortcut, to launch your app on the selected emulator or connected device.
2. Interact with the Map:
Once the app is running, you should see Google Maps displayed in your main activity. Try interacting with the map to ensure that it responds to user input such as pinches, zooms, and pans.
3. **Testing Markers**: If you added code for markers in `MainActivity.kt`, look for them on the map to ensure they are appearing as expected. You might have added a default marker on Sydney, so check if it's there and whether the title you set appears when you tap on it.
4. **Permissions Check**: If your app is using location services, it will prompt you for location permissions on the device. Make sure the permissions dialog appears, and that after granting permissions, any location-based features work as expected.
5. **Debug as Needed**: If there are any runtime issues, use the Logcat in Android Studio to troubleshoot. It will provide you with log output that can help identify the cause of any problems.
6. **Expand Functionality**: With the map set up, you can now continue to develop more features, such as searching for places, adding more markers, or integrating other map functionalities as needed for your app.
7. **Refine the App**: Consider the user interface and user experience. Make adjustments as needed to ensure the app is intuitive and efficient for users.
8. **Version Control**: It is a good practice to do Commits of your changes to your version control system to keep a record of your progress. Ensure not to include the API key or any sensitive information in the version control system. You can roll back changes that break previously working code based and use the GIT Diff tool to identify changes that might be responsible if this happens.
Remember, it's good practice to test on various devices with different screen sizes and OS versions to ensure compatibility. If you encounter any issues or need further assistance, feel free to reach out. Enjoy developing your app!

For the Android application featuring Google Maps functionality, as per the code and setup we are doing, I recommend trying:
1. **Emulator Device Choice**: Choose a Pixel series device, such as the Pixel 4 or Pixel 5, for emulation. These devices are fairly standard and representative of modern Android smartphones.
2. **API Level**: - Target an API level that aligns with your `minSdkVersion` and also one that's near the current latest stable release. - For broad coverage, you might consider API level 29 (Android 10) or 30 (Android 11), as these versions are widely used and support modern Android features. - Google Maps and location services are well-supported on these API levels.
3. **Emulator Configuration**: - **System Image**: Choose a system image with Google Play services (look for images labeled as "Google Play" in the system image selection in AVD Manager). This is crucial for testing Google Maps functionality. - **RAM and VM Heap**: Assign adequate RAM (e.g., 2GB or more) and a suitable VM heap size to ensure smooth performance. - **Screen Size and Resolution**: Default settings for the selected device (like Pixel 4) are generally adequate.
4. **Enable Hardware Acceleration**: Ensure that hardware acceleration is enabled in your emulator settings for better performance.
### Steps to Create the Emulator:
1. **Open the AVD Manager** in Android Studio (Tools > AVD Manager).
2. **Create a New Virtual Device**: Click on "Create Virtual Device" and select a device (e.g., Pixel 4).
3. **Choose a System Image**: Select a system image for API level 29 or 30 with Google Play services.
4. **Verify Configuration**: Check the configuration details such as RAM, VM heap, and ensure hardware acceleration is enabled.
5. **Finish Setup**: Click "Finish" to create your AVD.
6. **Run the Emulator**: Once the AVD is created, start the emulator from the AVD Manager and run your application.
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.