For an app I'm making, I need to get the users' location which will then be displayed on the map.
To achieve this, I am using LocationServices.getFusedLocationProviderClient() in the code below.
When I get the location value in addOnSuccessListener, the latitude and longtitude values are null for some reason, so I'm getting a NullPointerException:
import android.Manifest
import android.annotation.SuppressLint
import android.location.Location
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.app.ActivityCompat
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
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
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.realtomjoney.mapsapp.databinding.ActivityMainBinding
import java.lang.NullPointerException
class MainActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var binding: ActivityMainBinding
lateinit var myMap: GoogleMap
lateinit var fusedLocation: FusedLocationProviderClient
@SuppressLint("MissingPermission")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
ActivityCompat.requestPermissions(this, arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION) , 100)
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
binding.button2.setOnClickListener {
fusedLocation = LocationServices.getFusedLocationProviderClient(this)
fusedLocation.lastLocation.addOnSuccessListener { location: Location? ->
val latLong = LatLng(location!!.latitude, location.longitude)
myMap.addMarker(MarkerOptions().position(latLong).title("Found Location"))
myMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLong, 10f))
}
}
}
override fun onMapReady(p0: GoogleMap) {
myMap = p0
}
}
When I run the app, I get the following exception:
2021-10-19 16:46:09.859 8556-8556/com.realtomjoney.mapsapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.realtomjoney.mapsapp, PID: 8556
java.lang.NullPointerException
at com.realtomjoney.mapsapp.MainActivity.onCreate$lambda-1$lambda-0(MainActivity.kt:46)
at com.realtomjoney.mapsapp.MainActivity.$r8$lambda$wwcxhtPyugLtHLn65vCEt3JY33Q(Unknown Source:0)
at com.realtomjoney.mapsapp.MainActivity$$ExternalSyntheticLambda1.onSuccess(Unknown Source:4)
at com.google.android.gms.tasks.zzn.run(com.google.android.gms:play-services-tasks@@17.2.0:4)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7842)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
And yes, I have said yes to all permissions when I ran the app for the first time.
If this question is poorly written or a duplicate, please let me know as I strive to create good and well-structured questions.
Cheers, Tom
Edit: If you're gonna be downvoting questions at least explain why or else it's useless.
CodePudding user response:
lastLocation can be null for several reasons. They are listed here https://developer.android.com/training/location/retrieve-current#last-known
CodePudding user response:
First of all, the correct procedure not to get null when initializing user coordinates to map is to initialize the map on onConnected() callback instead of onCreate() in an activity or fragment, lastLocation can be null.
You can use REQUEST_CODE_ASK_PERMISSIONS
to handle the callback if not using location observer, the location observer basically would look something like this
if (location.provider == LocationManager.GPS_PROVIDER) {
getData()
}
I had the same case back in the days, my code was something like this on permission callback :
if (isGranted()) {
try {
fusedLocationProviderClient.lastLocation.addOnCompleteListener {
if (it.isSuccessful) {
if (it.result != null) {
setLocationData(it.result)
}
}
}
} catch (e: Exception) {
}
Basically on Permission granted, it will get your location and you can choose it whether you wanna use it to addMarker or anything else.