I am trying to find the location using FusedLocation Library - android

I am trying to find the location using fused location library. However when I try to set text longitude and latitude in my textView, i keep on getting error. Please look into the code.
Code
private fun fetchLocation() {
val task = fusedLocationProviderClient.lastLocation
if(ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), 101)
return
}
task.addOnSuccessListener {
if(it!=null){
val longitude = findViewById<TextView>(R.id.longitude)
val latitude = findViewById<TextView>(R.id.latitude)
longitude.setText(it.longitude)
latitude.setText(it.latitude)
}
}
}
Error
<html>None of the following functions can be called with the arguments supplied:<br/>public final fun setText(text: CharSequence!): Unit defined in android.widget.TextView<br/>public final fun setText(resid: Int): Unit defined in android.widget.TextView

Because the type of longitude/latitude is Double. And the type of the parameter of setText is either Int(resId) or CharSequence.
You could convert Double to String which implements CharSequence.
longitude.setText(it.longitude.toString())
latitude.setText(it.latitude.toString())

Related

How to get location using "fusedLocationClient.getCurrentLocation" method in Kotlin?

To request the last known location of the user's device, we can use the fused location provider to retrieve the device's last known location using getLastLocation(), but using getCurrentLocation() gets a refresher, and more accurate location.
so, how to use the fusedLocationClient.getCurrentLocation() in Kotlin as there is no example illustrated in the documentation?
According to the documentation, the getCurrentLocation() takes two parameters.
The 1st parameter it takes is the priority (e.g. PRIORITY_HIGH_ACCURACY) to request the most accurate locations available, or any other priority that can be found here.
The 2nd parameter it takes is a cancellation token that can be used to cancel the current location request.
From the Google play services reference, a CancellationToken can only be created by creating a new instance of CancellationTokenSource.
so here is the code you need to use when using getCurrentLocation()
class YourActivity : AppCompatActivity() {
private lateinit var fusedLocationClient: FusedLocationProviderClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.your_layout)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
fusedLocationClient.getCurrentLocation(LocationRequest.PRIORITY_HIGH_ACCURACY, object : CancellationToken() {
override fun onCanceledRequested(p0: OnTokenCanceledListener) = CancellationTokenSource().token
override fun isCancellationRequested() = false
})
.addOnSuccessListener { location: Location? ->
if (location == null)
Toast.makeText(this, "Cannot get location.", Toast.LENGTH_SHORT).show()
else {
val lat = location.latitude
val lon = location.longitude
}
}
}
}
fusedLocationClient.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, object : CancellationToken() {
override fun onCanceledRequested(listener: OnTokenCanceledListener) = CancellationTokenSource().token
override fun isCancellationRequested() = false
})
.addOnSuccessListener {
if (it == null)
Toast.makeText(this, "Cannot get location.", Toast.LENGTH_SHORT).show()
else {
val lat = it.latitude
val lon = it.longitude
}
}
I know the questio is about Kotlin but I want to add for those searching for Java :
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
fusedLocationClient.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, cancellationTokenSource.getToken())
.addOnSuccessListener(MyActivity.this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
//do your thing
}
Log.w(TAG, "No current location could be found");
}
});

Android Studio Emulator Returning Null Location Data

I'm learning Kotlin, and I'm trying to make a simple app that displays the users long/lat. Everything seems like it should be working, but the location data keeps throwing the 'null else{}' case. Below is what my code looks like.
class MainActivity : AppCompatActivity() {
val RequestPermissionCode = 1
var mLocation: Location? = null
private lateinit var fusedLocationClient: FusedLocationProviderClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
getLastLocation()
}
fun getLastLocation(){
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermission()
}
else{
fusedLocationClient.lastLocation
.addOnSuccessListener {location: Location? ->
mLocation = location
if(location != null){
latitude.text = location.latitude.toString()
longitude.text = location.longitude.toString()
}
else{
latitude.text = "LOCATION_DENIED"
longitude.text = "LOCATION_DENIED"
}
}
}
}
private fun requestPermission(){
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), RequestPermissionCode)
this.recreate()
}
}
Any help would be greatly appreciated! I'm about to start pulling my hair out, and can't find the answers on Google ):
Emulators I have noticed have issues with Location data, plus lastLocation is not making a location request, so there is good chance there is no location data. What you need is requestLocationUpdate method, so that it can retrieve active location of the user. Also you will have better luck on a physical device for last Location.

ForYouFragment Fragment doesn't update

Hi i have permission check on my forYou fragment when the app starts start and you give the permission and it makes a api call and get the weather for you current location the problem is I must switch the fragment for getting the call and switch again for showing it in the reclyerview the problem is when I give the permission for the location it doesn't do the api after that, I must refresh the fragment
fusedLocationClient.lastLocation.addOnSuccessListener(requireActivity()) { location ->
if (location != null) {
currentLocation = location
val currentLatLng = LatLng(location.latitude, location.longitude)
val currentAddress = getAddress(location.latitude, location.longitude)
Log.d("TAG", "klagenfurt : ${currentAddress}")
retrofitOneCallResponse(location.latitude, location.longitude, currentAddress)
dataService.getFavorites(this)
}
}
if (ActivityCompat.checkSelfPermission(
requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(
requireActivity(),
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
MapViewFragment.LOCATION_PERMISSION_REQUEST_CODE
)
return
}
enter image description here
HERE it says and you write the code without ActivityCompat on the requestpermisson line it doesn't work etiher
Create one method like this.
private fun getLocation(){
fusedLocationClient.lastLocation.addOnSuccessListener(requireActivity()) { location ->
if (location != null) {
currentLocation = location
val currentLatLng = LatLng(location.latitude, location.longitude)
val currentAddress = getAddress(location.latitude, location.longitude)
Log.d("TAG", "klagenfurt : ${currentAddress}")
retrofitOneCallResponse(location.latitude, location.longitude, currentAddress)
dataService.getFavorites(this)
}else{
getLocation()
}
}
}
then from here
if (ActivityCompat.checkSelfPermission(
requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
requestPermissions(
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
MapViewFragment.LOCATION_PERMISSION_REQUEST_CODE
)
}else{
getLocation()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray): Unit {
if(requestCode==MapViewFragment.LOCATION_PERMISSION_REQUEST_CODE){
if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
getLocation();
}
}
}
Also, override the onRequestPermissionsResult in the fragment. and check if permission granted the call getLocation().

Getting more precise location

In my Android Application I am targeting the device ranging from,
Minimum Android Version - 7.1 (API 25)
Target Android Version - 10.0 (API 29)
I am using the below logic to get the location Information
Permissions Using
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Code Logic
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED) {
return;
}
try {
gps_loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
network_loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
} catch (Exception e) {
e.printStackTrace();
}
if (gps_loc != null) {
final_loc = gps_loc;
latitude = final_loc.getLatitude();
longitude = final_loc.getLongitude();
}
else if (network_loc != null) {
final_loc = network_loc;
latitude = final_loc.getLatitude();
longitude = final_loc.getLongitude();
}
else {
latitude = 0.0;
longitude = 0.0;
}
}
But most of the time I am not getting accurate location with API call. But If enable the below option in device level (in Phone), I am getting the most accurate location
Is there any way I can configure the above settings in application level through code. The client which I am working is not satisfied with changing the configuration manually.
I am wondering how I can achieve the same through code. Someone please help.
Somethings you should know about getLastKnownLocation(...) [From Document]
Gets the last known location from the given provider, or null if there is no last known location. The returned location may be quite old in some circumstances, so the age of the location should always be checked.
This will never activate sensors to compute a new location, and will only ever return a cached location.
Please try locationManager.requestSingleUpdate(...), this method will request user current location.
if(locationManager.allProviders.contains(LocationManager.GPS_PROVIDER)) {
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, locListener)
} else if(locationManager.allProviders.contains(LocationManager.NETWORK_PROVIDER)){
locationManager.rerequestSingleUpdate(LocationManager.NETWORK_PROVIDER, locListener)
}
And this is listener.
val locListener = object: LocationListener {
override fun onLocationChanged(location: Location?) {
// do something with updated location here.
}
override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onProviderEnabled(provider: String?) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onProviderDisabled(provider: String?) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}

Code works outside of lambda expression, but not from within

I have the follow code:
override fun onCreate(savedInstanceState: Bundle?) {
...
fab_action.setOnClickListener(actionSetMyLocationEnable) //passing my lambda
}
private val actionSetMyLocationEnable: (View) -> Unit = { it as FloatingActionButton
it.isSelected = !it.isSelected
setMyLocationEnable(it.isSelected) //this call work fine
}
private fun setMyLocationEnable(enable: Boolean) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSION_REQUEST_ACCESS_FINE_LOCATION)
return //and this return work nice too
}
mMap.isMyLocationEnabled = enable
}
But, when I apply it as follows:
private val actionSetMyLocationEnable: (View) -> Unit = { it as FloatingActionButton
it.isSelected = !it.isSelected
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSION_REQUEST_ACCESS_FINE_LOCATION)
return //error 1
}
mMap.isMyLocationEnabled = it.isSelected //error 2
}
I'm facing these two errors:
error 1.
'return' is not allowed here
error 2.
Call requires permission which may be rejected by user: code should
explicitly check to see if permission is available (with
checkPermission) or explicitly handle a potential SecurityException
I know what each error means, but
My question is: why does my code work outside of the lambda expression and does not work when inside? And how do I solve this?
UPDATED
The #Rene Ferrari's solution solve the error 1. Thanks a lot #Rene Ferrari
Based of mTak answer my solution is the following:
private val actionSetMyLocationEnable: (View) -> Unit = returnHere#{ it as FloatingActionButton
it.isSelected = !it.isSelected
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSION_REQUEST_ACCESS_FINE_LOCATION)
return#returnHere //error 1
}
mMap.isMyLocationEnabled = it.isSelected //error 2
}
You can basically define a label to which you want to return. This label can be named anything except keywords ofcourse. In this example I named it returnHere

Categories

Resources