I am developing location based android app using google maps but when I run project I am getting crash and getting following exception java.lang.IllegalStateException: Fragment MapFragment{2fe7116} (69b05d78-5cf3-46a9-829c-6b6507944575) not attached to an activity. at androidx.fragment.app.Fragment.requireActivity(Fragment.java:995)
I am getting exception in following function in my MapFragment
@SuppressLint("MissingPermission")
private fun getDeviceLocation() {
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try {
if (locationPermissionGranted) {
val locationResult = fusedLocationProviderClient.lastLocation
locationResult.addOnCompleteListener(requireActivity()) { task ->
if (task.isSuccessful) {
// Set the map's camera position to the current location of the device.
lastKnownLocation = task.result
if (lastKnownLocation != null) {
map.moveCamera(
CameraUpdateFactory.newLatLngZoom(
LatLng(
lastKnownLocation!!.latitude,
lastKnownLocation!!.longitude
), DEFAULT_ZOOM.toFloat()
)
)
} else {
gotoDefaultLocation()
}
} else {
Log.d(TAG, "Current location is null. Using defaults.")
Log.e(TAG, "Exception: %s", task.exception)
gotoDefaultLocation()
}
}
}
} catch (e: SecurityException) {
MakeToast("Standort Zugriff leider nicht erlaubt")
Log.e("Exception: %s", e.message, e)
}
}
I have followed all stackoverflow answer it did not solve my problem
I have tried following stackoverflow answer as well java.lang.IllegalStateException: Fragment not attached to Activity I want to know where exactly I am making mistake
below My Full MapFragment.kt
@AndroidEntryPoint
class MapFragment : Fragment(), OnMapReadyCallback, GoogleMap.OnMarkerClickListener,
GoogleMap.OnInfoWindowClickListener {
private val binding by lazy { MapFragmentBinding.inflate(layoutInflater) }
private var locationPermissionGranted: Boolean = false
// private var mMap: MapView? = null
private lateinit var map: GoogleMap
private val cafMarker: MutableList<CafMarker> = mutableListOf()
private val viewModel by viewModels<MapViewModel>()
@Inject
lateinit var sharedPref: SharedPref
// Declare a variable for the cluster manager.
private lateinit var clusterManager: ClusterManager<CafMarker>
private val markerAdapter by lazy { MarkerAdapter() }
private lateinit var dialogMarker: Dialog
private var isRegistered: Boolean = false
// The entry point to the Places API.
private lateinit var placesClient: PlacesClient
private var lastKnownLocation: Location? = null
private var cameraPosition: CameraPosition? = null
// The entry point to the Fused Location Provider.
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
private val defaultLocation = LatLng(51.1633611, 10.4476833)
lateinit var CurrentChargePoint: ChargePoint
lateinit var cp: ChargePoint
private var ChargePoints: MutableList<ChargePoint> = mutableListOf<ChargePoint>()
private val TAG = "MapFragment"
private lateinit var activityContext: Context
companion object {
fun newInstance() = MapFragment()
val REQUEST_CODE_LOCATION = 32
private const val COUNTRY_ZOOM = 5.85
private const val DEFAULT_ZOOM = 15
private const val PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1
private const val KEY_CAMERA_POSITION = "camera_position"
private const val KEY_LOCATION = "location"
private const val M_MAX_ENTRIES = 5
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
Log.d("setNavigationToken", "setNavigation: ${sharedPref.token}")
activityContext = requireContext()
binding.mapView.onCreate(savedInstanceState)
binding.mapView.getMapAsync(this)
binding.mapView.setOnClickListener(clickListener)
binding.gotoBookingButton.setOnClickListener(clickListener);
binding.StationInfo.isVisible = false;
createChannel("caf", "alarm")
if (savedInstanceState != null) {
lastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION)
cameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION)
}
binding.qrButton.setOnClickListener(clickListener)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.map(sharedPref.token)
Log.d("onViewCreatedToken", "onViewCreated: ${sharedPref.token}")
}
val clickListener = View.OnClickListener { view ->
when (view.getId()) {
// R.id.gotoBookingButton -> {
// appCommon.CurrentChargePoint = CurrentChargePoint
// if (sharedPref.token.length > 0) {
// Log.d("@@@@@@@", ": $sharedPref")
//// appCommon.isAdhocBooking = false
// findNavController().navigate(R.id.navigation_reserve)
// } else {
// findNavController().navigate(R.id.navigation_settings_login)
// }
// }
R.id.mapView -> {
binding.StationInfo.isVisible = false
}
R.id.qrButton -> {
findNavController().navigate(R.id.activity_qr)
}
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
binding.mapView.onSaveInstanceState(outState)
}
@SuppressLint("MissingPermission")
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
gotoDefaultLocation()
if (ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_CODE_LOCATION
)
return
}
locationPermissionGranted = true
map.isMyLocationEnabled = true;
//gMap.addMarker(MarkerOptions().position(devDefault).title("Hier bin ich"))
updateLocationUI()
getDeviceLocation()
map.setOnMarkerClickListener(this)
getChargePoints()
// FetchChargePoints()
}
val broadCastReceiver = object : BroadcastReceiver() {
override fun onReceive(contxt: Context?, intent: Intent?) {
when (intent?.action) {
SET_MAP_PERMISSIONS -> {
if (intent.extras?.get("result")?.toString()!!
.toInt() == PackageManager.PERMISSION_GRANTED
) {
locationPermissionGranted = true
updateLocationUI()
getDeviceLocation()
getChargePoints()
}
}
// BROADCAST_CHANGE_TYPE_CHANGED -> handleChangeTypeChanged()
}
}
}
@SuppressLint("MissingPermission")
private fun updateLocationUI() {
if (map == null) {
return
}
try {
if (locationPermissionGranted) {
map.isMyLocationEnabled = true
map.uiSettings.isMyLocationButtonEnabled = true
} else {
map.isMyLocationEnabled = false
map.uiSettings.isMyLocationButtonEnabled = false
lastKnownLocation = null
getLocationPermission()
}
} catch (e: SecurityException) {
Log.e("Exception: %s", e.message, e)
}
}
private fun getLocationPermission() {
/*
* Request location permission, so that we can get the location of the
* device. The result of the permission request is handled by a callback,
* onRequestPermissionsResult.
*/
if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
)
== PackageManager.PERMISSION_GRANTED
) {
locationPermissionGranted = true
updateLocationUI()
} else {
ActivityCompat.requestPermissions(
requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION
)
}
}
@SuppressLint("MissingPermission")
private fun getDeviceLocation() {
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try {
if (locationPermissionGranted) {
val locationResult = fusedLocationProviderClient.lastLocation
locationResult.addOnCompleteListener(requireActivity()) { task ->
if (task.isSuccessful) {
// Set the map's camera position to the current location of the device.
lastKnownLocation = task.result
if (lastKnownLocation != null) {
map.moveCamera(
CameraUpdateFactory.newLatLngZoom(
LatLng(
lastKnownLocation!!.latitude,
lastKnownLocation!!.longitude
), DEFAULT_ZOOM.toFloat()
)
)
} else {
gotoDefaultLocation()
}
} else {
Log.d(TAG, "Current location is null. Using defaults.")
Log.e(TAG, "Exception: %s", task.exception)
gotoDefaultLocation()
}
}
}
} catch (e: SecurityException) {
MakeToast("Standort Zugriff leider nicht erlaubt")
Log.e("Exception: %s", e.message, e)
}
}
private fun gotoDefaultLocation() {
map.moveCamera(
CameraUpdateFactory
.newLatLngZoom(defaultLocation, COUNTRY_ZOOM.toFloat())
)
map.uiSettings.isMyLocationButtonEnabled = false
}
private fun MakeToast(text: String) {
val toast = text
Toast.makeText(
activity?.applicationContext,
toast,
Toast.LENGTH_SHORT
).show()
}
override fun onResume() {
super.onResume()
registerReceiver()
binding.mapView.onResume()
}
override fun onPause() {
super.onPause()
binding.mapView.onPause()
}
override fun onStart() {
super.onStart()
registerReceiver()
binding.mapView.onStart()
}
override fun onStop() {
super.onStop()
LocalBroadcastManager.getInstance(requireContext()).unregisterReceiver(broadCastReceiver)
binding.mapView.onStop()
}
override fun onDestroy() {
super.onDestroy()
// binding.mapView.onDestroy()
}
private fun registerReceiver() {
if (!isRegistered) {
val filter = IntentFilter()
filter.addAction(SET_MAP_PERMISSIONS)
// filter.addAction(END_PAYMENT)
LocalBroadcastManager.getInstance(requireContext())
.registerReceiver(broadCastReceiver, filter)
isRegistered = true
}
}
override fun onMarkerClick(p0: Marker): Boolean {
getCPs(p0)
UseCpInfo()
return true
}
private fun UseCpInfo() {
if (this::cp.isInitialized) {
CurrentChargePoint = cp // it means
// binding.StationInfo.isVisible = true
// val streetName = binding.StationInfo.findViewById(R.id.textViewStreet) as TextView
// val stationCity = binding.StationInfo.findViewById(R.id.textViewCity) as TextView
// val stationName = binding.StationInfo.findViewById(R.id.textViewStationName) as TextView
// stationName.text = cp.getCpLocName()
// streetName.text = cp.getStreetName()
// stationCity.text = cp.getCityName()
// Log.d("MapFragmentAdhok", "UseCpInfo: ${cp.hasType(ChargePointType.AdHoc)}")
// if (cp.hasType(ChargePointType.AdHoc)) {
// binding.textViewAvailability.text = "nur Direktladen, " + cp.Tarif + " Ct/kWh"
// } else if (cp.Available) {
// binding.textViewAvailability.text =
// String.format(Locale.GERMAN, "%.0f", cp.Tarif) + " Ct/kWh - " + String.format(
// Locale.GERMAN,
// "%.1f",
// cp.Power
// ) + " kW"
// } else {
// binding.textViewAvailability.text = "belegt, " + String.format(
// Locale.GERMAN,
// "%.0f",
// cp.Tarif
// ) + " Ct/kWh - " + String.format(Locale.GERMAN, "%.1f", cp.Power) + " kW"
// }
} else {
MakeToast("Station leider nicht verfügbar")
}
}
private fun getCPs(p0: Marker) {
for (i in 0 until ChargePoints.size) {
if (ChargePoints[i].id == p0.id) {
cp = ChargePoints[i]
}
}
}
private fun getCPsByCafMarker(p0: CafMarker) {
for (i in 0 until ChargePoints.size) {
if (ChargePoints[i].Guid == p0.GetId()) {
cp = ChargePoints[i]
}
}
}
private fun getChargePoints() {
viewLifecycleOwner.lifecycleScope.launchWhenCreated {
viewModel.map.collect {
when (it) {
is UiStateList.LOADING -> {
}
is UiStateList.SUCCESS -> {
Log.d("MapFragmentCharge", "getChargePoint: ${it.data}")
appCommon.setChargePoints(it.data)
setUpClusterer()
}
is UiStateList.ERROR -> {
Log.d(TAG, "getChargePoints: ${it.message}")
Toast.makeText(requireContext(), it.message, Toast.LENGTH_SHORT).show()
}
}
}
}
}
private fun setUpClusterer() {
val markersList = ArrayList<CafMarker>()
clusterManager = ClusterManager<CafMarker>(activityContext, map)
clusterManager.renderer = MapRenderer(activityContext, map, clusterManager)
Log.d(TAG, "setUpClusterer: ${clusterManager.markerCollection}")
map.setOnCameraIdleListener(clusterManager)
map.setOnMarkerClickListener(clusterManager)
map.setOnInfoWindowClickListener(clusterManager)
clusterManager.setOnClusterItemClickListener {
getCPsByCafMarker(it)
UseCpInfo()
CurrentChargePoint = cp
appCommon.CurrentChargePoint = CurrentChargePoint
appCommon.isAdhocBooking = CurrentChargePoint.hasType(ChargePointType.AdHoc)
if (!appCommon.CurrentChargePoint.hasType(ChargePointType.Manual) and !appCommon.CurrentChargePoint.hasType(ChargePointType.Calibrated)) {
Log.d("updateAccessProfileUIReserve", "addItems: ")
appCommon.CurrentChargePoint.hasType(ChargePointType.Calibrated)
}
// appCommon.isCalibrated = CurrentChargePoint.hasType(ChargePointType.Calibrated)
Log.d("TAGsetUpClusterer", "setUpClusterer: $cp")
Log.d(TAG, "setUpClusterer: $CurrentChargePoint")
if (sharedPref.token.length > 0) {
Log.d("@@@@@@@", ": $sharedPref")
// appCommon.isAdhocBooking = false
findNavController().navigate(R.id.navigation_reserve)
} else {
findNavController().navigate(R.id.navigation_settings_login)
}
true
}
clusterManager.setOnClusterClickListener { cluster ->
// Add ten cluster items in close proximity, for purposes of this example.
val items: List<ChargePoint> = appCommon.getChargePoints()
var available = ""
var tarif = ""
var kW = ""
for (i in cluster.items) {
for (k in 0 until items.size) {
val cp: ChargePoint = items[k]
if (cp.Guid == i.GetId()) {
if (cp.hasType(ChargePointType.AdHoc) == false) {
Log.d("ChargePointBall", "Tarif: ${cp.Tarif}")
available =
requireContext().getResources().getString(R.string.available) + ":"
tarif = cp.Tarif.toInt().toString() + " Ct/kWh"
kW = cp.Power.toString() + " kW"
} else {
available = requireContext().getResources()
.getString(R.string.not_reservable) + ":"
tarif = cp.Tarif.toInt().toString() + " Ct/kWh"
kW = cp.Power.toString() + " kW"
}
}
}
val markerModel = CafMarker(
i.position.latitude,
i.position.longitude,
i.GetId(),
i.title,
i.snippet,
null,
available,
tarif,
kW
)
markersList.add(markerModel)
}
markerAdapter.submitData(markersList)
if (markersList.size > 0) {
showProfessionsDialog()
markersList.clear()
markerAdapter.itemClickListener = {
getCPsByCafMarker(it)
UseCpInfo()
CurrentChargePoint = cp
appCommon.CurrentChargePoint = CurrentChargePoint
Log.d("TAGsetUpClusterer", "setUpClusterer: $cp")
Log.d(TAG, "setUpClusterer: $CurrentChargePoint")
dialogMarker.dismiss()
if (sharedPref.token.length > 0) {
Log.d("@@@@@@@", ": $sharedPref")
// appCommon.isAdhocBooking = false
findNavController().navigate(R.id.navigation_reserve)
} else {
findNavController().navigate(R.id.navigation_settings_login)
}
map.moveCamera(
CameraUpdateFactory.newLatLngZoom(
LatLng(
it.position.latitude, it.position.longitude
), DEFAULT_ZOOM.toFloat()
)
)
}
}
Log.d(TAG, "setUpClusterer: clicked")
map.animateCamera(
CameraUpdateFactory.newLatLngZoom(
cluster.getPosition(),
Math.floor((map.cameraPosition.zoom + 1).toDouble()).toFloat()
), 300, null
)
true
}
addItems()
getDeviceLocation()
}
private fun showProfessionsDialog() {
dialogMarker = Dialog(requireContext())
val binding = DialogMarkersBinding.inflate(layoutInflater)
dialogMarker.setContentView(binding.root)
dialogMarker.setCancelable(true)
dialogMarker.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
binding.rvMarkers.adapter = markerAdapter
dialogMarker.show()
}
override fun onInfoWindowClick(marker: Marker) {
onMarkerClick(marker);
}
private fun addItems() {
// Add ten cluster items in close proximity, for purposes of this example.
val items: List<ChargePoint> = appCommon.getChargePoints()
var isGood: Boolean = true
for (i in 0 until items.size) {
val cp: ChargePoint = items[i]
if (cp.Guid != null) {
Log.d("Available", "addItems: ${cp.hasType(ChargePointType.AdHoc)}")
var color: MarkerColor = MarkerColor.Green
if (cp.hasType(ChargePointType.AdHoc)) {
color = MarkerColor.Blue
}
else if (!cp.Available) {
color = MarkerColor.Red
}
val offsetItem = CafMarker(cp.Lat, cp.Lon, cp.Guid, cp.CpName, cp.Name, color, "", "", "")
clusterManager.addItem(offsetItem)
val defaultClusterRenderer = clusterManager.renderer as DefaultClusterRenderer
// defaultClusterRenderer.minClusterSize = 4
if (defaultClusterRenderer.minClusterSize >= 6) {
clusterManager.addItem(offsetItem)
}
cp.uuid = offsetItem.GetId()
ChargePoints.add(i, cp)
} else {
isGood = false
}
}
if (!isGood) {
}
}
private fun createChannel(channelId: String, channelName: String) {
// TODO: Step 1.6 START create a channel
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create channel to show notifications.
val notificationChannel = NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_HIGH
)
.apply {
setShowBadge(false)
}
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.RED
notificationChannel.enableVibration(true)
notificationChannel.description = getString(R.string.notification_channel_description)
val notificationManager = requireActivity().getSystemService(
NotificationManager::class.java
)
notificationManager.createNotificationChannel(notificationChannel)
}
}
}
Remove requireActivity()
, it gives this IllegalStateException
. See Explanation from official document.
locationResult.addOnCompleteListener {task ->
if (task.isSuccessful) {
// Your Code
}
}
Get Location, according to official documentation.