My map shows as follows:
I managed to create a single map before but only in an activity - now I want to create it in a fragment.
SelectLocationFragment
package com.udacity.project4.locationreminders.savereminder.selectreminderlocation
import android.Manifest
import android.app.Activity
import android.content.pm.PackageManager
import android.content.res.Resources
import android.location.Criteria
import android.location.LocationManager
import android.os.Bundle
import android.util.Log
import android.view.*
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.getSystemService
import androidx.databinding.DataBindingUtil
import androidx.navigation.fragment.findNavController
import com.google.android.gms.maps.*
import com.google.android.gms.maps.model.*
import com.udacity.project4.R
import com.udacity.project4.base.BaseFragment
import com.udacity.project4.databinding.FragmentSelectLocationBinding
import com.udacity.project4.locationreminders.savereminder.SaveReminderViewModel
import com.udacity.project4.utils.setDisplayHomeAsUpEnabled
import org.koin.android.ext.android.inject
import java.util.*
class SelectLocationFragment : BaseFragment(), OnMapReadyCallback {
private lateinit var map: GoogleMap
private lateinit var poiMarker: Marker
private lateinit var mapView: MapView
private val REQUEST_LOCATION_PERMISSION = 1
private lateinit var currentPOI: PointOfInterest
//Use Koin to get the view model of the SaveReminder
override val _viewModel: SaveReminderViewModel by inject()
private lateinit var binding: FragmentSelectLocationBinding
private val runningQOrLater = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
binding =
DataBindingUtil.inflate(inflater, R.layout.fragment_select_location, container, false)
// When the user confirms on the selected location,
binding.saveLocationButton.setOnClickListener {
// Send back the selected location details to the view model
_viewModel.selectedPOI.value = currentPOI
_viewModel.longitude.value = poiMarker.position.longitude
_viewModel.latitude.value = poiMarker.position.latitude
// Navigate back to the previous fragment to save the reminder and add the geofence
findNavController().navigate(SelectLocationFragmentDirections.actionSelectLocationFragmentToSaveReminderFragment())
}
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.lifecycleOwner = this
context?.let { MapsInitializer.initialize(it) }
setHasOptionsMenu(true)
setDisplayHomeAsUpEnabled(true)
mapView = binding.map
mapView.onCreate(savedInstanceState)
mapView.getMapAsync(this)
}
override fun onMapReady(googleMap: GoogleMap) {
googleMap.mapType = GoogleMap.MAP_TYPE_NORMAL
map = googleMap
setPoiClick(map)
setMapStyle(map)
/**
* Inside this functions we check for permissions
*/
enableMyLocation()
zoomOnMyLocation()
//These coordinates represent the lattitude and longitude of the Googleplex.
val latitude = 37.422160
val longitude = -122.084270
val zoomLevel = 15f
val homeLatLng = LatLng(latitude, longitude)
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
map.addMarker(MarkerOptions().position(homeLatLng))
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.map_options, menu)
}
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
// Change the map type based on the user's selection.
R.id.normal_map -> {
map.mapType = GoogleMap.MAP_TYPE_NORMAL
true
}
R.id.hybrid_map -> {
map.mapType = GoogleMap.MAP_TYPE_HYBRID
true
}
R.id.satellite_map -> {
map.mapType = GoogleMap.MAP_TYPE_SATELLITE
true
}
R.id.terrain_map -> {
map.mapType = GoogleMap.MAP_TYPE_TERRAIN
true
}
else -> super.onOptionsItemSelected(item)
}
// Places a marker on the map and displays an info window that contains POI name.
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
poiMarker = map.addMarker(
MarkerOptions()
.position(poi.latLng)
.title(poi.name)
)!!
poiMarker.showInfoWindow()
currentPOI = poi
}
// de bagat o anulare a punctelor dinainte
}
private fun setMapStyle(map: GoogleMap) {
try {
// Customize the styling of the base map using a JSON raw object
val success = map.setMapStyle(
context?.let { MapStyleOptions.loadRawResourceStyle(it, R.raw.map_style) }
)
if (!success) { Log.e("dra", "Style parsing failed.") }
} catch (e: Resources.NotFoundException) {
Log.e("dra", "Can't find style. Error: ", e)
}
}
// Checks that users have given permission
private fun isPermissionGranted() : Boolean {
return context?.let {
ContextCompat.checkSelfPermission(it, Manifest.permission.ACCESS_FINE_LOCATION)
} === PackageManager.PERMISSION_GRANTED
}
// Checks if users have given their location and sets location enabled if so.
private fun enableMyLocation() {
if (isPermissionGranted()) {
if (context?.let {
ActivityCompat.checkSelfPermission(it, Manifest.permission.ACCESS_FINE_LOCATION)
} != PackageManager.PERMISSION_GRANTED && context?.let {
ActivityCompat.checkSelfPermission(it, Manifest.permission.ACCESS_COARSE_LOCATION)
} != PackageManager.PERMISSION_GRANTED
) {
return
}
map.isMyLocationEnabled = true
}
else {
Toast.makeText(context, "App needs permissions to run!", Toast.LENGTH_LONG).show()
ActivityCompat.requestPermissions(
context as Activity,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION
)
}
}
private fun zoomOnMyLocation() {
val locationManager = getSystemService(requireContext(), LocationManager::class.java)
val criteria = Criteria()
if (context?.let {
ActivityCompat.checkSelfPermission(it, Manifest.permission.ACCESS_FINE_LOCATION)
} != PackageManager.PERMISSION_GRANTED && context?.let {
ActivityCompat.checkSelfPermission(it, Manifest.permission.ACCESS_COARSE_LOCATION)
} != PackageManager.PERMISSION_GRANTED
) {
return
}
val location = locationManager!!.getLastKnownLocation(
locationManager.getBestProvider(criteria, false)!!
)
if (location != null) {
map.animateCamera(
CameraUpdateFactory.newLatLngZoom(
LatLng(location.latitude, location.longitude), 13f
)
)
val cameraPosition = CameraPosition.Builder()
.target(LatLng(location.latitude, location.longitude)) // Sets the center of the map to location user
.zoom(17f) // Sets the zoom
.bearing(90f) // Sets the orientation of the camera to east
.tilt(40f) // Sets the tilt of the camera to 40 degrees
.build() // Creates a CameraPosition from the builder
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}
}
}
fragment_select_location.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.udacity.project4.locationreminders.savereminder.SaveReminderViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.gms.maps.MapView
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.udacity.project4.locationreminders.savereminder.selectreminderlocation"/>
<Button
android:id="@+id/saveLocationButton"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:background="#D71B60"
android:textColor="@color/white"
android:text="@string/save_location"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
I have tried the following "fixes":
- doble checked the API and the SHA code on the google cloud website/ and on my program
- I managed to make it work in an activity - but now I want to implement it in a fragment.
- The firebase login system works without problems so I didn't change any api/ setting there
- Google Maps is showing a blank map
- https://issuetracker.google.com/issues/228091313
- https://github.com/dotnet/maui/issues/8242
- https://developers.google.com/maps/documentation/android-sdk/renderer
- https://developers.google.com/android/reference/com/google/android/gms/maps/MapsInitializer
- Android MapView no longer working, even after using updated google tutorial
- SecurityException - GoogleCertificatesRslt: not allowed
- GoogleMaps widget error Unable to retrieve flag snapshot for com.google.android.libraries.consentverifier
- https://developers.google.com/maps/documentation/android-sdk/renderer
- Google Maps Android: java.lang.ClassCastException: android.widget.FrameLayout cannot be cast to com.google.android.gms.maps.SupportMapFragment
Please help me find the error! thanks