我的 Android 项目在启动时需要用户的最后/当前位置,但由于某种原因我没有获得有效的位置。
我的主要活动检查权限如下:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
permissionHelper = PermissionHelper(this)
val drawerLayout: DrawerLayout = binding.drawerLayout
val navView: NavigationView = binding.navView
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment_content_home) as NavHostFragment
val navController = navHostFragment.navController
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.nav_home,
R.id.nav_account, R.id.nav_pictures, R.id.nav_settings
), drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
NavigationUI.setupWithNavController(binding.navView, navController)
navController.addOnDestinationChangedListener { _, destination, _ ->
isCurrentLocationFragmentVisible = destination.id == R.id.nav_home
if (isCurrentLocationFragmentVisible) {
invalidateOptionsMenu()
}
}
handleLocationAndWeather()
currentLocationViewModel.weather.observe(this){
currentLocation = LocationDto(it.location.cityName, it.location.locationIndex)
}
}
private fun handleLocationAndWeather() {
// Check if location permission is granted
if (permissionHelper.isPermissionGranted(Manifest.permission.ACCESS_COARSE_LOCATION)) {
// Permission is granted, load weather data
viewModel.updatePermissionState(LocationPermissionState.Granted)
viewModel.loadCurrentLocationWeather()
} else {
// Permission not granted, request it
permissionHelper.requestPermission(
Manifest.permission.ACCESS_COARSE_LOCATION,
"Location permission is required to get weather data for your current location.",
LOCATION_PERMISSION_REQUEST_CODE
)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
LOCATION_PERMISSION_REQUEST_CODE -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted, update state and load weather data
viewModel.updatePermissionState(LocationPermissionState.Granted)
viewModel.loadCurrentLocationWeather()
} else {
// Permission denied, update state and handle accordingly
viewModel.updatePermissionState(LocationPermissionState.Denied)
viewModel.loadCurrentLocationWeather()
//TODO show toast here
}
}
}
}
它使用此类来处理与权限相关的内容:
class PermissionHelper(private val activity: Activity) {
fun isPermissionGranted(permission: String): Boolean {
return ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED
}
fun requestPermission(permission: String, rationale: String, requestCode: Int) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
showRationaleDialog(rationale) { _, _ ->
ActivityCompat.requestPermissions(
activity,
arrayOf(permission),
requestCode
)
}
} else {
ActivityCompat.requestPermissions(
activity,
arrayOf(permission),
requestCode
)
}
}
private fun showRationaleDialog(message: String, onPositiveClick: (DialogInterface, Int) -> Unit) {
AlertDialog.Builder(activity)
.setTitle("Location permission Required")
.setMessage(message)
.setPositiveButton("OK", onPositiveClick)
.setNegativeButton("Cancel", null)
.show()
}
}
主 Activity 调用视图模型根据位置获取数据:
private val _locationPermissionState = MutableStateFlow<LocationPermissionState>(LocationPermissionState.Granted)
val locationPermissionState: StateFlow<LocationPermissionState> = _locationPermissionState
fun updatePermissionState(state : LocationPermissionState){
_locationPermissionState.value = state
}
@SuppressLint("MissingPermission")
fun loadCurrentLocationWeather() {
viewModelScope.launch {
when (locationPermissionState.value) {
LocationPermissionState.Granted -> {
Log.d(TAG, "permission granted")
locationGetter.client.lastLocation
.addOnSuccessListener { location ->
// Check if the location is not null before proceeding
if (location != null) {
Log.d(TAG, "location not null")
viewModelScope.launch {
weatherRepository.getWeather(
location.latitude,
location.longitude
)
.map { locationWithWeatherDataDto ->
val weatherData =
convertWeatherDtoToWeatherModel(
locationWithWeatherDataDto.weather
)
val locationData = LocationModel(
locationWithWeatherDataDto.location.cityName,
locationWithWeatherDataDto.location.locationIndex
)
LocationWeatherModel(
location = locationData,
weather = weatherData
)
}
.collect {
_weather.value = it
Log.d(TAG, it.weather.cityName)
}
}
} else {
// location is null show seattle
Log.d(TAG, "location is null")
viewModelScope.launch {
weatherRepository.getWeather("Chicago")
.map { locationWithWeatherDataDto ->
val weatherData =
convertWeatherDtoToWeatherModel(locationWithWeatherDataDto.weather)
val locationData = LocationModel(
locationWithWeatherDataDto.location.cityName,
locationWithWeatherDataDto.location.locationIndex
)
LocationWeatherModel(location = locationData, weather = weatherData)
}
.collect {
_weather.value = it
Log.d(TAG, it.weather.cityName)
}
}
}
}
}
else -> {
//location permission is denied
viewModelScope.launch {
weatherRepository.getWeather("Seattle")
.map { locationWithWeatherDataDto ->
val weatherData =
convertWeatherDtoToWeatherModel(locationWithWeatherDataDto.weather)
val locationData = LocationModel(
locationWithWeatherDataDto.location.cityName,
locationWithWeatherDataDto.location.locationIndex
)
LocationWeatherModel(location = locationData, weather = weatherData)
}
}
}
}
}
}
我已经明白了
locationGetter.client.lastLocation
.addOnSuccessListener { location ->
// Check if the location is not null before proceeding
if (location != null) {
始终为空,这让我相信我没有获得有效的位置。我已经在模拟器中设置了一个位置,所以我怀疑它没有最后一个位置。 任何反馈将不胜感激!
Lastlocation 不会打开定位子系统。仅当操作系统已知该位置时,它才会返回结果。 99% 以上的时间它都会返回 null。这是一种优化,并且添加它可能是操作系统的设计错误。使用 requestLocationUpdates 或 requestSingleLocation 在操作系统中实际打开位置检测。