So i'm trying to return a value from a function to use inside the mainActivity class, but I get an error when I try to return the variable stating that the 'variable must be initialized' even though I have given a value to it. Any thoughts on this?
private fun getCLocation() : LocationClass {
var loc: LocationClass
if(checkPermission()){
if(isLocationEnabled()){
locationVariable.lastLocation.addOnCompleteListener(this) { task->
val location:Location? = task.result
if(location == null){
Toast.makeText(this,"NULL",Toast.LENGTH_LONG).show()
}
else{
loc = LocationClass(location.latitude.toString(),location.longitude.toString())
}
}
} else {
// location not enabled,open settings
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
}
} else {
//Permission Not Enabled
requestPermission()
}
return loc
}
Error is: Variable 'loc' must be initialized
The two problems with your code:
else
block, where the function requests a permission, but doesn't do anything to set the initial location value. The function couldn't possibly return a valid location in this circumstance.Here's a basic strategy for what to do. The function that gets a location takes a callback parameter instead of returning the LocationClass directly since it is asynchronous. You need a higher-level logic that can be retried after location or permissions become available.
private var triedPromptingLocationSetting = false
private var locationWorkflowInitiated = false // SET THIS BACK TO FALSE IN onViewDestroyed() IF IN FRAGMENT
private fun fetchCLocation(onReceived: (LocationClass?)->Unit) {
if (!checkPermission() || isLocationEnabled()) {
Log.e("Do not call getCLocation() before permission is granted and location is turned on! Ignoring.")
return
}
locationVariable.lastLocation.addOnCompleteListener(this) { task->
val location:Location? = task.result
if (location == null) {
onReceived(null)
}
else {
var loc = LocationClass(location.latitude.toString(),location.longitude.toString())
onReceived(loc)
}
}
}
// This is where the logic is for whatever you wanted to do with this location.
// In this example, it's assumed it would be called in onResume()
private fun doMyLocationWorkflow() {
if (!checkPermission()) {
requestPermission()
return
}
if (!isLocationEnabled()) {
if (triedPromptingLocationSetting) {
// can't infinitely loop back to settings.
showSomeUiRequestingUserToManuallyEnableLocation()
} else {
triedPromptingLocationSetting = true
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
}
return
}
locationWorkflowInitiated = true
fetchCLocation { location ->
if (location == null) {
Toast.makeText(this,"NULL",Toast.LENGTH_LONG).show()
//...
return@fetchCLocation
}
// Do something with the LocationClass
}
}
override fun onResume() {
super.onResume()
if (!locationWorkflowInitiated) {
doMyLocationWorkflow()
}
}
private val locationPermissionRequest = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
when {
permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
doMyLocationWorkflow() // go back to original workflow
}
permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
doMyLocationWorkflow() // go back to original workflow
} else -> {
showSomeUiTellingUserPermissionMustBeGranted()
}
}
}
private fun requestPermission() {
locationPermissionRequest.launch(arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION))
}