Android jetpack compose get updated value from class property

121 views Asked by At

I am very beginner in android compose and kotlin, I have this code using FusedLocationProviderClient, to get the user permission and enable locations, however I can't set the Lat and long values to the compose text fields in the HomeScreen(). how to achieve this in compose way

Thank you

    class MainActivity : ComponentActivity() {

    private var longitude: Double = 0.0
    private var latitude: Double = 0.0

    private lateinit var fusedLocationProviderClient: FusedLocationProviderClient

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            DistanceCalculatorTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    HomeScreen()
                }
            }
        }

        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

        getCurrentLocation()
    }

    private fun getCurrentLocation(): Unit {
        if (checkPermissions()) {
            //Permission granted
            if (isLocationEnabled()) {

                getLatLong()


            } else {

                Toast.makeText(this, "Tur on  Location", Toast.LENGTH_SHORT).show()
                openLocationSettings()

            }
        } else {
            //request permission
            requestPermission()
        }
    }

    @SuppressLint("MissingPermission")
    private fun getLatLong() {
        fusedLocationProviderClient.lastLocation.addOnCompleteListener(this) { task ->
            val loc: Location? = task.result
            if (loc == null) {
                Toast.makeText(this, "Location not received", Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(this, "Location received", Toast.LENGTH_SHORT).show()
                latitude = loc.latitude
                longitude = loc.longitude

               here How to set latitude, longitude to my compose text
            }
        }
    }

    private fun openLocationSettings() {
        val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
        startActivity(intent)
    }

    private fun isLocationEnabled(): Boolean {
        val locationManager: LocationManager =
            getSystemService(Context.LOCATION_SERVICE) as LocationManager
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
                ||
                locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
    }

    private fun requestPermission() {
        ActivityCompat.requestPermissions(
            this,
            arrayOf(
                android.Manifest.permission.ACCESS_COARSE_LOCATION,
                android.Manifest.permission.ACCESS_FINE_LOCATION
            ),
            PERMISSION_REQUEST_ACCESS_LOCATION
        )
    }

    companion object {
        private const val PERMISSION_REQUEST_ACCESS_LOCATION = 100
    }

    fun checkPermissions(): Boolean {

        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
        ) {
            return true
        }
        return false
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == PERMISSION_REQUEST_ACCESS_LOCATION) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(
                    applicationContext,
                    "Permission granted", Toast.LENGTH_SHORT
                ).show()
            } else {
                Toast.makeText(
                    applicationContext,
                    "Permission denied", Toast.LENGTH_SHORT
                ).show()
            }
        }
    }
}


@Composable
private fun HomeScreen( ) {
    val context = LocalContext.current
    Column {
        Button(onClick = {

        }) {
            Text(text = "Button 1")
        }
        // How to get the latlong from the class property valus here ?
        Text(text = latitude.toString())
        Text(text = longitude.toString())
    }
}
1

There are 1 answers

0
rashidnk On

As suggsted by @chirag,

created a viewModel class holding the StateFlow<> lat,long

created a funcion updateLoc() to update the state

access and update the values from my composable

reference https://medium.com/@chiragthummar16/jetpack-compose-viewmodel-update-ui-using-flow-9ea7870a3072

class LocationViewModel : ViewModel() {

    private val _longitude = MutableStateFlow(0.0)
    val longitude: StateFlow<Double> = _longitude

    private val _latitude = MutableStateFlow(0.0)
    val latitude: StateFlow<Double> = _latitude

    fun updateLoc(lat: Double, long: Double) {
        _latitude.value = lat
        _longitude.value = long
    }
}

class MainActivity : ComponentActivity() {

    private var longitude: Double = 0.0
    private var latitude: Double = 0.0

    private lateinit var fusedLocationProviderClient: FusedLocationProviderClient

    private val locationViewModel: LocationViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            DistanceCalculatorTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    HomeScreen(locationViewModel)
                }
            }
        }

        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

        getCurrentLocation()
    }

    private fun getCurrentLocation(): Unit {
        if (checkPermissions()) {
            //Permission granted
            if (isLocationEnabled()) {

                getLatLong()


            } else {

                Toast.makeText(this, "Tur on  Location", Toast.LENGTH_SHORT).show()
                openLocationSettings()

            }
        } else {
            //request permission
            requestPermission()
        }
    }

    @SuppressLint("MissingPermission")
    private fun getLatLong() {
        fusedLocationProviderClient.lastLocation.addOnCompleteListener(this) { task ->
            val loc: Location? = task.result
            if (loc == null) {
                Toast.makeText(this, "Location not received", Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(this, "Location received", Toast.LENGTH_SHORT).show()
                latitude = loc.latitude
                longitude = loc.longitude

                locationViewModel.updateLoc(loc.latitude, loc.longitude)

                // here How to set latitude, longitude to my compose text
            }
        }
    }

    private fun openLocationSettings() {
        val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
        startActivity(intent)
    }

    private fun isLocationEnabled(): Boolean {
        val locationManager: LocationManager =
            getSystemService(Context.LOCATION_SERVICE) as LocationManager
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
                ||
                locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
    }

    private fun requestPermission() {
        ActivityCompat.requestPermissions(
            this,
            arrayOf(
                android.Manifest.permission.ACCESS_COARSE_LOCATION,
                android.Manifest.permission.ACCESS_FINE_LOCATION
            ),
            PERMISSION_REQUEST_ACCESS_LOCATION
        )
    }

    companion object {
        private const val PERMISSION_REQUEST_ACCESS_LOCATION = 100
    }

    fun checkPermissions(): Boolean {

        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
        ) {
            return true
        }
        return false
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == PERMISSION_REQUEST_ACCESS_LOCATION) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(
                    applicationContext,
                    "Permission granted", Toast.LENGTH_SHORT
                ).show()
            } else {
                Toast.makeText(
                    applicationContext,
                    "Permission denied", Toast.LENGTH_SHORT
                ).show()
            }
        }
    }
}


@Composable
private fun HomeScreen(locationViewModel: LocationViewModel) {
    val context = LocalContext.current
    val lat = locationViewModel.latitude.collectAsState()
    val long = locationViewModel.longitude.collectAsState()
    Column {
        Button(onClick = {
        }) {
            Text(text = "Get Location")
        }
        // How to get the latlong from the class property valus here ?
        Text(text = lat.value.toString())
        Text(text = long.value.toString())
    }
}