can anyone tell me why when I call the function initPetrolStationList() in first if condition currentLocation is allways null but when I call te function addPetrolStation(v: View) is initilized? I would like that when the function initPetrolStationList()is called currentLocation will be not null.
class PetrolStationListActivity : AppCompatActivity() {
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
private lateinit var listView: RecyclerView
private var currentLocation: Location? = null
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
//some code
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.petrol_station_list_view)
requestLocationPermission()
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
getLastLocation()
initPetrolStationList()
}
fun addPetrolStation(v: View) {
if (currentLocation != null) {
val googleMapController = GoogleMapsController()
googleMapController.getPetrolStationFromGoogle(object : GoogleResponse {
override fun getLocation(): Location = currentLocation!!
override fun getResponse(body: GoogleMapResponse) {
if (body.status == "OK") {
val intent = Intent(applicationContext, PetrolStationActivity::class.java)
v.context.startActivity(intent)
} else {
Toast.makeText(applicationContext, "Petrol station not found", Toast.LENGTH_LONG).show()
}
}
})
}
}
#SuppressLint("MissingPermission")
private fun getLastLocation() {
fusedLocationProviderClient.lastLocation.addOnCompleteListener {
if (it.isSuccessful) {
currentLocation = it.result!!
Log.d("Current location: ", "Lat:${currentLocation!!.latitude}, Lng:${currentLocation!!.longitude}")
} else {
Log.d("Location exception: ", it.exception?.message)
Toast.makeText(this, "Location not found :( ", Toast.LENGTH_LONG).show()
}
}
}
private fun initPetrolStationList() {
if (currentLocation != null) {
val petrolStationController = PetrolStationController()
//some code
} else Toast.makeText(this, "Location not found", Toast.LENGTH_LONG).show()
}
}
If you call initPetrolStationList from inside getLastLocation after currentLocation = it.result!! then currentLocation will not be null.
Try to initialize petrolStationController immediately
Add fusedLocationProviderClient.lastLocation.addOnCompleteListener in onCreate
And update data of petrolStationController in this listener
Related
In my app my geofence does not update my firebase database when I enter the area. I made sure my code for updating the database works so that is not the problem. Also, when I enter the geofence my activity crashes. I’m going to add all my code for getting my location, the geofence and my broadcast.
Maps activity
class PricklyMapsActivity : AppCompatActivity(), OnMapReadyCallback {
lateinit var toggle: ActionBarDrawerToggle
//location
private lateinit var fusedLocatonClient: FusedLocationProviderClient
private lateinit var myLatlng: LatLng
private lateinit var currentLocation: Location
private val permissionId = 5
//Map
private lateinit var map: GoogleMap
private lateinit var binding: ActivityPricklyMapsBinding
//Goefence
private var gadgetQ = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q
private lateinit var geoClient: GeofencingClient
var geofenceList: MutableList<Geofence> = mutableListOf()
//firebase
private lateinit var database: DatabaseReference
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityPricklyMapsBinding.inflate(layoutInflater)
setContentView(binding.root)
// 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)
fusedLocatonClient = LocationServices.getFusedLocationProviderClient(this)
//drawer create and in actions
val drawerLayout: DrawerLayout = findViewById(R.id.draweLayout)
val navWiew: NavigationView = findViewById(R.id.nav_view)
toggle = ActionBarDrawerToggle(this#PricklyMapsActivity, drawerLayout, R.string.open, R.string.close)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
navWiew.setNavigationItemSelectedListener {
when (it.itemId){
R.id.Home -> showActivityHome()
R.id.Map -> Toast.makeText(applicationContext, "Alredy at the Map", Toast.LENGTH_SHORT).show()
}
true
}
//drawer create end
//Geofence
geoClient = LocationServices.getGeofencingClient(this)
//add geofences here
val latatude = -26.694340
val longatude = 27.083960
val radius = 10f
geofenceList.add(Geofence.Builder()
.setRequestId("Toets")
.setCircularRegion(latatude,longatude,radius)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
.build())
}
override fun onDestroy() {
super.onDestroy()
removeGeofence()
}
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
getCurrentLocation()
val placeName = arrayOf<String>("Texas")
val lataltude = arrayOf<Double>(-26.694340)
val longatude = arrayOf<Double>(27.083960)
for (i in 0..placeName.size-1){
val x = placeName[i]
val y = lataltude[i]
val z = longatude[i]
addCircle(x, y, z)
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if(toggle.onOptionsItemSelected(item)){
return true
}
return super.onOptionsItemSelected(item)
}
//go to the home activity
private fun showActivityHome(){
val intent1 = Intent(this#PricklyMapsActivity, MainActivity::class.java)
startActivity(intent1)
}
private fun addCircle(Name: String, latatude: Double, longatude: Double){
val radius = 10.00
val latLng = LatLng(latatude,longatude)
map.addCircle(
CircleOptions()
.radius(radius)
.center(latLng)
.strokeColor(Color.argb(150,173,216,230))
.fillColor(Color.argb(100, 173, 216, 230))
)
}
//Geofence pending intent
private val geofenceIntent: PendingIntent by lazy {
val intent = Intent(this, GeofenceBrodcastReceiver::class.java)
intent.action = ACTION_GEOFENCE_EVENT
PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
}
companion object{
internal const val ACTION_GEOFENCE_EVENT =
"PricklyMapsActivity.pricklypear.action.ACTION_GEOFENCE_EVENT"
}
//Specifies the geofence
private fun seekGeofencing(): GeofencingRequest {
return GeofencingRequest.Builder().apply {
setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
addGeofences(geofenceList)
}.build()
}
//adds the geofence or geofences
#SuppressLint("MissingPermission")
private fun addGeofence(){
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION
) != PERMISSION_GRANTED){
return
}
geoClient?.addGeofences(seekGeofencing(), geofenceIntent)?.run {
addOnSuccessListener {
Toast.makeText(this#PricklyMapsActivity, "Geofence(s) added", Toast.LENGTH_LONG).show()
}
addOnFailureListener {
Toast.makeText(this#PricklyMapsActivity, "Failed to add geofence(s)", Toast.LENGTH_LONG).show()
}
}
}
//Removing geofences
private fun removeGeofence(){
geoClient?.removeGeofences(geofenceIntent)?.run {
addOnSuccessListener {
Toast.makeText(this#PricklyMapsActivity, "Geofences removed", Toast.LENGTH_SHORT).show()
}
addOnFailureListener {
Toast.makeText(this#PricklyMapsActivity, "Failed to remove geofences", Toast.LENGTH_SHORT).show()
}
}
}
//From here and down it is getting location and permition
#SuppressLint("MissingPermission", "NewApi")
private fun getCurrentLocation(){
if (checkPermission()){
if (isLocationEnabled()){
map.isMyLocationEnabled = true
fusedLocatonClient.lastLocation.addOnCompleteListener(this){ task ->
val location: Location?=task.result
if (location==null){
Toast.makeText(this,
"Location may still be turning on pleas wate a while",
Toast.LENGTH_SHORT).show()
}else {
currentLocation = location
myLatlng = LatLng(location.latitude, location.longitude)
map.animateCamera(CameraUpdateFactory.newLatLngZoom(myLatlng, 18f))
addGeofence()
}
Looper.myLooper()
}
}else{
//open settings if location is not enabled
Toast.makeText(this, "Pleas turn on location", Toast.LENGTH_SHORT).show()
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
}
}else{
//requests permition if permition is not granted
requestPermissions()
}
}
//Checker for if the laocation is enabled return boolean
private fun isLocationEnabled(): Boolean{
val locationManager: LocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
return locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
}
//Checker for if the location permission is enabled return boolean
#TargetApi(29)
private fun checkPermission(): Boolean{
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_COARSE_LOCATION) ==
PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) ==
PERMISSION_GRANTED){
if (gadgetQ){
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_BACKGROUND_LOCATION) ==
PERMISSION_GRANTED) {
return true
}
}else {
return true
}
}
return false
}
private fun requestPermissions(){
ActivityCompat.requestPermissions(this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION), permissionId
//android.Manifest.permission.ACCESS_BACKGROUND_LOCATION), permissionId
)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == permissionId){
if (grantResults.isNotEmpty() && grantResults[0] == PERMISSION_GRANTED){
getCurrentLocation()
}else{
Toast.makeText(this, "location is not granted", Toast.LENGTH_SHORT).show()
}
}
}
}
Brodcast receiver Class
class GeofenceBrodcastReceiver: BroadcastReceiver() {
private lateinit var database: DatabaseReference
override fun onReceive(context: Context?, intent: Intent?) {
val geofencingEvent = GeofencingEvent.fromIntent(intent!!)
val geofencingTransition = geofencingEvent!!.geofenceTransition
if (geofencingTransition == Geofence.GEOFENCE_TRANSITION_ENTER) {
database = FirebaseDatabase.getInstance().getReference("Texas")
database.child("Count").get().addOnSuccessListener {
if (it.exists()) {
var number = it.getValue(Long::class.java)
if (number is Long){
number += 1
val post =mapOf<String, Long>("Count" to number)
database.updateChildren(post)
}
} else {
Log.e(TAG, "Invalid type transition")
}
}.addOnFailureListener {
Log.e(TAG, "Invalid type transition")
}
}
}
}
At the pending intent I tried changing the type, but it did not work. I have looked every ware and as far as I can tell there is no problem with my code, and it should work so if someone can help me it would be much appreciated.
Essentially my problem is in the title, where I get permissions for location and from there try to get an API response based on the location. Problem is that the thread seems to continue before getting the answer? Here are the relevant snippets of code (and apologies for any beginner mistakes)
class ApiViewModel : ViewModel() {
private val _listOfRegions = MutableLiveData<List<Region>>()
val listOfRegions: LiveData<List<Region>> = _listOfRegions
fun getRegionsData(country: String) {
viewModelScope.launch {
Log.d("Workflow", "We will try to fetch info for $country")
try {
val listResult = SpotApi.retrofitService.getRegions(country)
Log.d("Workflow", listResult.toString())
if (listResult.isSuccessful) {
_listOfRegions.postValue(listResult.body())
Log.d("Workflow", listResult.body().toString())
} else {
_listOfRegions.value = emptyList()
}
} catch (e: Exception) {
Log.d("Workflow", "Failure: ${e.message}")
_listOfRegions.value = emptyList()
}
}
}
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
private val retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(BASE_URL)
.build()
interface ApiService {
#GET("{country}")
suspend fun getRegions(#Path("country") country: String): Response<List<Region>>
}
object SpotApi {
val retrofitService: ApiService by lazy {
retrofit.create(ApiService::class.java)
}
}
object RegionsHelper {
fun getCurrentLocation(context: Context, lat: Double, long: Double): String {
val geocoder = Geocoder(context)
val locationResult = geocoder.getFromLocation(lat, long, 1)
val country = locationResult[0].countryCode
Log.d("Workflow", "Country is $country")
Log.d(
"Workflow",
locationResult[0].latitude.toString() + locationResult[0].longitude.toString()
)
return if (locationResult[0] != null) {
country
} else {
"Something Else"
}
}
}
class MainActivity : AppCompatActivity() {
private lateinit var fusedLocationClient: FusedLocationProviderClient
val viewModel: ApiViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
// TODO: If LastLocation available use that to trigger result, else use default value
getLastLocation()
}
private fun getLastLocation() {
if (checkLocationPermission()) {
if (isLocationEnabled()) {
fusedLocationClient.lastLocation.addOnCompleteListener(this) { task ->
val location: Location? = task.result
if (location == null) {
requestNewLocationData()
} else {
Log.d("Workflow", "Permission Granted")
Log.d("Workflow", "Location is $location")
val retrievedCurrentCountry = getCurrentLocation(this#MainActivity, location.latitude, location.longitude)
Log.d("Workflow", "Current country is $retrievedCurrentCountry")
viewModel.getRegionsData(retrievedCurrentCountry)
//Log.d("Workflow", listOfRegions.toString())
}
}
}
}
}
}
Logs result are:
D/Workflow: Country is PT
D/Workflow: 38.7211345-9.139605
D/Workflow: Current country is PT
D/Workflow: We will try to fetch info for PT
D/Workflow: null
D/Workflow: Response{protocol=http/1.0, code=200, message=OK, url=http://192.168.1.181:5000/PT/}
D/Workflow: [Region(region=cascais, country=PT, long=-9.4207, lat=38.6968), Region(region=sintra, country=PT, long=-9.3817, lat=38.8029), Region(region=caparica, country=PT, long=-9.2334, lat=38.6446), Region(region=ericeira, country=PT, long=-9.4176, lat=38.9665)]*
Even though getting last location using fused location provider is very quick, sometimes it may take some time (upto 1000ms).
In your code, your API is called before getting last location. you can achieve this by using observer for your retrievedCurrentLocation.
class MainActivity : AppCompatActivity() {
private lateinit var fusedLocationClient: FusedLocationProviderClient
val viewModel: ApiViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
// TODO: If LastLocation available use that to trigger result, else use default value
getLastLocation()
observeRetrievedLocation()
}
private fun observeRetrievedLocation() {
viewModel.retrievedLocation.observe(this) {
if (it.isNotEmpty) {
viewModel.getRegionsData(it)
}
}
}
private fun getLastLocation() {
if (checkLocationPermission()) {
if (isLocationEnabled()) {
fusedLocationClient.lastLocation.addOnCompleteListener(this) { task ->
val location: Location? = task.result
if (location == null) {
requestNewLocationData()
} else {
Log.d("Workflow", "Permission Granted")
Log.d("Workflow", "Location is $location")
val retrievedCurrentCountry = getCurrentLocation(this#MainActivity, location.latitude, location.longitude)
Log.d("Workflow", "Current country is $retrievedCurrentCountry")
viewModel.loadRetrievedLocation(retrievedCurrentCountry)
}
}
}
}
}
}
And your viewModel,
class ApiViewModel : ViewModel() {
private val _listOfRegions = MutableLiveData<List<Region>>()
val listOfRegions: LiveData<List<Region>> = _listOfRegions
private val _retrievedLocation = MutableLiveData<String>()
val retrievedLocation: LiveData<String> = _retrievedLocation
fun loadRetrievedLocation(retrievedLocation: String) {
_retrievedLocation.value = retrievedLocation
}
fun getRegionsData(country: String) {
viewModelScope.launch {
Log.d("Workflow", "We will try to fetch info for $country")
try {
val listResult = SpotApi.retrofitService.getRegions(country)
Log.d("Workflow", listResult.toString())
if (listResult.isSuccessful) {
_listOfRegions.postValue(listResult.body())
Log.d("Workflow", listResult.body().toString())
} else {
_listOfRegions.value = emptyList()
}
} catch (e: Exception) {
Log.d("Workflow", "Failure: ${e.message}")
_listOfRegions.value = emptyList()
}
}
}
so your API will be called only when the value of retrievedCurrentLocation Livedata changes and not null.
I am getting a NullPointerException when I try to access an element in the layout from a DialogFragment. I have checked that, if I call getView() inside the same DialogFragment the result is 'null'.
Thank you in advance!
This is the Activity that calls commits the FragmentDialog "NewPOIDialog"
class MainActivity : AppCompatActivity() {
//Variables for Location service
private var hasGps: Boolean = false
private var hasNetwork: Boolean = false
private var locationGps: Location? = null
private var locationNetwork: Location? = null
private companion object {
private const val TAG = "MainActivity"
}
private lateinit var auth: FirebaseAuth
private lateinit var permissionsRequestor: PermissionsRequestor
private lateinit var mapView: MapView
private lateinit var mapActivity: MapActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
//Get the authorisation from Firebase
auth = Firebase.auth
Log.d("", "HERE SDK version: " + SDKBuildInformation.sdkVersion().versionName)
// Get a MapView instance from layout.
mapView = findViewById(R.id.map_view)
mapView.onCreate(savedInstanceState)
location()
handleAndroidPermissions()
}
fun searchInMap(view: View?) {
NewPOIDialog().show(supportFragmentManager, "test")
}
fun clearRouteButtonClicked(view: View?) {
mapActivity.clearMap()
}
fun clearWaypoints(view: View?) {
mapActivity.clearWaypoints()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true //we provided the menu that needs to be inflated
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.miLogout) {
Log.i(TAG, "Logout")
//Logout the user
auth.signOut()
LoginManager.getInstance().logOut()
val logoutIntent = Intent(this, LoginActivity::class.java)
logoutIntent.flags =
Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK //Clear the backstack
startActivity(logoutIntent)
}
return super.onOptionsItemSelected(item)
}
private fun handleAndroidPermissions() {
permissionsRequestor = PermissionsRequestor(this)
permissionsRequestor.request(object : PermissionsRequestor.ResultListener {
override fun permissionsGranted() {
loadMapScene()
}
override fun permissionsDenied() {
Log.e(TAG, "Permissions denied by user.")
}
})
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
permissionsRequestor.onRequestPermissionsResult(requestCode, grantResults)
}
private fun loadMapScene() {
mapView.mapScene.loadScene(MapScheme.NORMAL_DAY, object : MapScene.LoadSceneCallback {
override fun onLoadScene(p0: MapError?) {
if (p0 == null) {
mapActivity = MapActivity(this#MainActivity, mapView, supportFragmentManager)
mapView.camera.lookAt(
GeoCoordinates(53.57407651646072, -1.525012498490556),
100000.0
)
} else {
Log.d("TAG", "onLoadScene failed: $p0")
}
}
})
}
fun location() {
var locationManager: LocationManager = getSystemService(LOCATION_SERVICE) as LocationManager
hasGps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
hasNetwork = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
if (hasGps || hasNetwork) {
if (hasGps) {
Log.d(TAG, "hasGPS")
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
//return
handleAndroidPermissions()
}
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
1000,
0f,
object :
LocationListener {
override fun onLocationChanged(p0: Location?) {
if (p0 != null) {
locationNetwork = p0
}
}
override fun onStatusChanged(p0: String?, p1: Int, p2: Bundle?) {
}
override fun onProviderEnabled(p0: String?) {
}
override fun onProviderDisabled(p0: String?) {
}
})
val localGpsLocation =
locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
if (localGpsLocation != null) {
locationGps = localGpsLocation
}
}
///////////////////////////////////////////////////////////////////////////
if (hasNetwork) {
Log.d(TAG, "hasGPS")
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
1000,
0f,
object :
LocationListener {
override fun onLocationChanged(p0: Location?) {
if (p0 != null) {
locationNetwork = p0
}
}
override fun onStatusChanged(p0: String?, p1: Int, p2: Bundle?) {
}
override fun onProviderEnabled(p0: String?) {
}
override fun onProviderDisabled(p0: String?) {
}
})
val localGpsLocation =
locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
if (localGpsLocation != null) {
locationGps = localGpsLocation
}
val localNetworkLocation =
locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
if (localNetworkLocation != null) {
locationNetwork = localNetworkLocation
}
if (locationGps != null && locationNetwork != null) {
if (locationGps!!.accuracy!! > locationNetwork!!.accuracy!!) { //The lower number is the accurate location
Log.d(TAG, "Network Latitude : ${locationNetwork!!.latitude}")
Log.d(TAG, "Network Longitude : ${locationNetwork!!.longitude}")
latitude_txt.text = "Latitude : ${locationNetwork!!.latitude} - Network"
longitude_txt.text = "Longitude : ${locationNetwork!!.longitude} - Network"
latitude_txt.text = "Latitude : ${locationGps!!.latitude} - Gps"
longitude_txt.text = "Longitude : ${locationGps!!.longitude} - Gps"
} else {
Log.d(TAG, "Gps Latitude : ${locationGps!!.latitude}")
Log.d(TAG, "Gps Longitude : ${locationGps!!.longitude}")
latitude_txt.text = "Latitude : ${locationGps!!.latitude} - Gps"
longitude_txt.text = "Longitude : ${locationGps!!.longitude} - Gps"
}
}
}
// if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) &&
// this.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS)
// ) {
// locationManager.requestLocationUpdates(
// LocationManager.GPS_PROVIDER,
// LOCATION_UPDATE_INTERVAL_IN_MS,
// 1,
// this
// );
// } else if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
// locationManager.requestLocationUpdates(
// LocationManager.NETWORK_PROVIDER,
// LOCATION_UPDATE_INTERVAL_IN_MS,
// 1,
// this
// );
// } else {
// Log.d(TAG, "Positioning not possible.");
// // ...
// }
}
}
}
NewPOIDialog
The view was initially called as below, I changed it as I was receiving a StackOverFlowError:
var view = layoutInflater.inflate(R.layout.activity_new_poi_dialog,null)
class NewPOIDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
var view = LayoutInflater.from(context).inflate(R.layout.activity_new_poi_dialog, null)
var dialog = AlertDialog.Builder(requireContext())
.setMessage("TITLE")
.setView(view)
.setPositiveButton("ok") { _, _ -> }
.setNegativeButton("Cancel") { _, _ -> }
.create()
//THIS LINE WORKS FINE
var coordinatesvalue = view.findViewById<TextView>(R.id.coordinates_value)
coordinatesvalue.text =
"${arguments?.getDouble("latitude")}\n, ${arguments?.getDouble("longitude")}"
//THIS CAUSES A NULL POINTER EXCEPTION
coordinates_value.text = "TEST"
return dialog
}
}
The exception I am getting:
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.robin.socialparking, PID: 19187
java.lang.NullPointerException: coordinates_value must not be null
at com.robin.socialparking.dialog.NewPOIDialog.onCreateDialog(NewPOIDialog.kt:54)
at androidx.fragment.app.DialogFragment.onGetLayoutInflater(DialogFragment.java:380)
at androidx.fragment.app.Fragment.performGetLayoutInflater(Fragment.java:1412)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:881)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7050)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
I/Process: Sending signal. PID: 19187 SIG: 9
I put a Map Fragment inside dashboard fragment shown in image below:
To view the image clearly https://i.stack.imgur.com/NcxLB.jpg
whenever i am on home fragment and click on dashboard fragment it takes 3-4 sec (at the first time) and 1-2 sec
here is the code of dashboard fragment
class DashboardFragment :
BaseFragment<DashboardViewModel, FragmentDashboardBinding, WeatherRepository>(),
GoogleMap.OnMapClickListener,
GoogleMap.OnMapLongClickListener,
GoogleMap.OnCameraIdleListener,
OnMapReadyCallback {
private var map: GoogleMap? = null
private var cameraPosition: CameraPosition? = null
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
private val defaultLocation = LatLng(-33.8523341, 151.2106085)
private var locationPermissionGranted = false
private var lastKnownLocation: Location? = null
private var weatherData: WeatherData? = null
private lateinit var bottomSheetBehavior: BottomSheetBehavior<NestedScrollView>
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (savedInstanceState != null) {
lastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION)
cameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION)
weatherData = savedInstanceState.getParcelable(KEY_WEATHER_DATA)
}
Log.e("Weather Data", weatherData.toString())
fusedLocationProviderClient =
LocationServices.getFusedLocationProviderClient(requireActivity())
val mapFragment =
childFragmentManager.findFragmentById(R.id.myMap) as SupportMapFragment?
mapFragment?.getMapAsync(this#DashboardFragment)
bottomSheetBehavior = BottomSheetBehavior.from(binding.root.bottomSheet)
bottomSheetBehavior.addBottomSheetCallback(object :
BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) { /*handle onSlide*/ }
override fun onStateChanged(bottomSheet: View, newState: Int) {
when (newState) {
BottomSheetBehavior.STATE_COLLAPSED -> {
binding.root.bottomSheet.background =
(ContextCompat.getDrawable(requireContext(), R.drawable.round))
}
BottomSheetBehavior.STATE_EXPANDED -> {
binding.root.bottomSheet.background =
(ContextCompat.getDrawable(requireContext(), R.drawable.edge))
}
BottomSheetBehavior.STATE_DRAGGING -> {
}
BottomSheetBehavior.STATE_SETTLING -> {
}
BottomSheetBehavior.STATE_HIDDEN -> {
}
else -> {
}
}
}
})
viewModel.weatherResponse.observe(viewLifecycleOwner, {
when (it) {
is Resource.Success -> {
updateUi(binding.root, it.value)
weatherData = it.value
}
is Resource.Failure -> {
Toast.makeText(
requireContext(),
"Damn, Failed To Load Data",
Toast.LENGTH_SHORT
).show()
}
}
})
}
override fun onSaveInstanceState(outState: Bundle) {
map?.let { map ->
outState.putParcelable(KEY_CAMERA_POSITION, map.cameraPosition)
outState.putParcelable(KEY_LOCATION, lastKnownLocation)
}
super.onSaveInstanceState(outState)
}
override fun onMapReady(map: GoogleMap) {
this.map = map
map.setOnMapClickListener(this)
map.setOnMapLongClickListener(this)
map.setOnCameraIdleListener(this)
getLocationPermission()
updateLocationUI()
getDeviceLocation()
}
var marker: Marker? = null
override fun onMapClick(point: LatLng) {
if (marker == null){
marker = map?.addMarker(
MarkerOptions()
.position(point)
.title("${point.latitude.toString()},${point.longitude.toString()} is the location")
)
} else {
marker!!.position = point
marker!!.title = "${point.latitude.toString()},${point.longitude.toString()} is the location"
}
viewModel.getWeather(
point.latitude.toString(),
point.longitude.toString(),
app_id
)
if (bottomSheetBehavior.state == BottomSheetBehavior.STATE_EXPANDED)
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
else
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
Toast.makeText(this.context, "click $point", Toast.LENGTH_SHORT).show()
}
override fun onMapLongClick(point: LatLng) {
try {
val manager: FragmentManager =
(this.context as AppCompatActivity).supportFragmentManager
CustomBottomSheetDialogFragment().show(manager, CustomBottomSheetDialogFragment.TAG)
} catch (e: Exception) {
Log.e("❤", e.printStackTrace().toString())
}
Toast.makeText(this.context, "long click", Toast.LENGTH_SHORT).show()
}
override fun onCameraIdle() {
//if(!::map.isInitialized) return
//cameraTextView.text = map.cameraPosition.toString()
//Toast.makeText(this.context, "camera idle", Toast.LENGTH_SHORT).show()
}
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 getDeviceLocation() {
try {
if (locationPermissionGranted) {
val locationResult = fusedLocationProviderClient.lastLocation
locationResult.addOnCompleteListener { task ->
if (task.isSuccessful) {
lastKnownLocation = task.result
if (lastKnownLocation != null) {
map?.moveCamera(
CameraUpdateFactory.newLatLngZoom(
LatLng(
lastKnownLocation!!.latitude,
lastKnownLocation!!.longitude
), DEFAULT_ZOOM.toFloat()
)
)
viewModel.getWeather(
lastKnownLocation!!.latitude.toString(),
lastKnownLocation!!.longitude.toString(),
app_id
)
}
} else {
Log.d(TAG, "Current location is null. Using defaults.")
Log.e(TAG, "Exception: %s", task.exception)
map?.moveCamera(
CameraUpdateFactory
.newLatLngZoom(defaultLocation, DEFAULT_ZOOM.toFloat())
)
map?.uiSettings?.isMyLocationButtonEnabled = false
}
}
}
} catch (e: SecurityException) {
Log.e("Exception: %s", e.message, e)
Toast.makeText(this.context, "Some exception occurred", Toast.LENGTH_SHORT).show()
}
}
private fun getLocationPermission() {
if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
)
== PackageManager.PERMISSION_GRANTED
) {
locationPermissionGranted = true
} else {
requestPermissions(
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION
)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
locationPermissionGranted = false
when (requestCode) {
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION -> {
if (grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
locationPermissionGranted = true
}
}
}
updateLocationUI()
}
override fun getViewModal() = DashboardViewModel::class.java
override fun getFragmentBinding(
inflater: LayoutInflater,
container: ViewGroup?
) = FragmentDashboardBinding.inflate(inflater, container, false)
override fun getFragmentRepository() =
WeatherRepository(remoteDataSource.buildApi(WeatherApi::class.java))
companion object {
private val TAG = DashboardFragment::class.java.simpleName
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 KEY_WEATHER_DATA = "weather_data"
const val app_id = "*******api********"
}
}
even if i comment the whole code it the onActivityCreated() method still the lag occurs.
I used the code from the official Google Maps Platform Documentation, still the example app they use don't lags like my app.
Any help will be appreciated.
Guys, I am trying to get a user location but there is something wrong, when I run my app there is no player icon and the location is wrong - it still shows lat = 0.0, lon = 0.0. I don't use an emulator, I test app on my mobile phone (Android 4.4.2 if it matters). Please take a look at my code maybe I just can't see a mistake. Thank you in advance!
class MapsActivity : FragmentActivity(), OnMapReadyCallback {
private var mMap: GoogleMap? = null
private val USER_LOCATION_REQUEST_CODE = 1000
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
// 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)
requestLocationPermission()
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
}
//ask permission
private fun requestLocationPermission() {
if (Build.VERSION.SDK_INT >= 23) {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED) {
requestPermissions(
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
USER_LOCATION_REQUEST_CODE
)
}
}
}
fun GetPlayerLocation() {
Toast.makeText(this, "User location access on", Toast.LENGTH_LONG).show()
var playerLocation = PlayerLocationListener()
var locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3, 3f, playerLocation)
var mythread = myThread()
mythread.start()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
when (requestCode) {
USER_LOCATION_REQUEST_CODE -> {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
GetPlayerLocation()
} else {
Toast.makeText(this, "We cannot access to your location", Toast.LENGTH_LONG).show()
}
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
var location: Location? = null
// Get player location
inner class PlayerLocationListener : LocationListener {
constructor() {
location = Location("Start")
location!!.latitude = 0.0
location!!.longitude = 0.0
}
override fun onStatusChanged(p0: String?, p1: Int, p2: Bundle?) {
}
override fun onProviderEnabled(p0: String?) {
}
override fun onProviderDisabled(p0: String?) {
}
override fun onLocationChanged(p0: Location?) {
location = p0
}
}
inner class myThread : Thread {
constructor() : super(){
}
override fun run() {
while (true) {
try {
runOnUiThread {
mMap!!.clear()
val sydney = LatLng(location!!.latitude, location!!.longitude)
mMap!!.addMarker(
MarkerOptions().position(sydney).title("Hi!")
.snippet("Let's go!")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.player)))
mMap!!.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 14f))
}
Thread.sleep(1000)
} catch (ex: Exception) {
}
}
}
}
}
`
try this way
implement in gradle these dependency
implementation 'com.google.android.gms:play-services:11.4.0'
implementation 'com.google.android.gms:play-services-maps:11.4.0'
uses permission in your AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
create a locationListener interface
interface locationListener {
fun locationResponse(locationResult: LocationResult)
}
then create a Location.kt class
class Location (var activity: AppCompatActivity, locationListener: locationListener){
private val permissionFineLocation=android.Manifest.permission.ACCESS_FINE_LOCATION
private val permissionCoarseLocation=android.Manifest.permission.ACCESS_COARSE_LOCATION
private val REQUEST_CODE_LOCATION=100
private var fusedLocationClient: FusedLocationProviderClient?=null
private var locationRequest: LocationRequest?=null
private var callbabck: LocationCallback?=null
init {
fusedLocationClient= FusedLocationProviderClient(activity.applicationContext)
inicializeLocationRequest()
callbabck=object: LocationCallback(){
override fun onLocationResult(p0: LocationResult?) {
super.onLocationResult(p0)
locationListener.locationResponse(p0!!)
}
}
}
private fun inicializeLocationRequest() {
locationRequest= LocationRequest()
locationRequest?.interval=50000
locationRequest?.fastestInterval=5000
locationRequest?.priority=LocationRequest.PRIORITY_HIGH_ACCURACY
}
private fun validatePermissionsLocation():Boolean{
val fineLocationAvailable= ActivityCompat.checkSelfPermission(activity.applicationContext, permissionFineLocation)== PackageManager.PERMISSION_GRANTED
val coarseLocationAvailable=ActivityCompat.checkSelfPermission(activity.applicationContext, permissionCoarseLocation)==PackageManager.PERMISSION_GRANTED
return fineLocationAvailable && coarseLocationAvailable
}
private fun requestPermissions(){
val contextProvider=ActivityCompat.shouldShowRequestPermissionRationale(activity, permissionFineLocation)
if(contextProvider){
Toast.makeText(activity.applicationContext, "Permission is required to obtain location", Toast.LENGTH_SHORT).show()
}
permissionRequest()
}
private fun permissionRequest(){
ActivityCompat.requestPermissions(activity, arrayOf(permissionFineLocation, permissionCoarseLocation), REQUEST_CODE_LOCATION)
}
fun onRequestPermissionsResult(requestCode:Int, permissions:Array<out String>, grantResults:IntArray){
when(requestCode){
REQUEST_CODE_LOCATION->{
if(grantResults.size>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
getLocation()
}else{
Toast.makeText(activity.applicationContext, "You did not give permissions to get location", Toast.LENGTH_SHORT).show()
}
}
}
}
fun stopUpdateLocation(){
this.fusedLocationClient?.removeLocationUpdates(callbabck)
}
fun inicializeLocation(){
if (validatePermissionsLocation()){
getLocation()
}else{
requestPermissions()
}
}
#SuppressLint("MissingPermission")
private fun getLocation() {
validatePermissionsLocation()
fusedLocationClient?.requestLocationUpdates(locationRequest, callbabck, null)
}
}
usage
class MapsActivity : AppCompatActivity(), OnMapReadyCallback {
var location: Location?=null
private var mMap: GoogleMap? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
// 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)
location= Location(this, object :locationListener{
override fun locationResponse(locationResult: LocationResult) {
mMap?.clear()
val sydney = LatLng(locationResult.lastLocation.latitude, locationResult.lastLocation.longitude)
mMap?.addMarker(MarkerOptions().position(sydney).title("Hi").snippet("Let's go!"))
mMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 14f))
}
})
}
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
location?.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
override fun onStart() {
super.onStart()
location?.inicializeLocation()
}
override fun onPause() {
super.onPause()
location?.stopUpdateLocation()
}
}
I hope this help you