此代码属于显示用户当前位置的片段。获取位置后,当我想返回到上一个片段时应用程序崩溃。Logcat 表示此处发生错误: “val geocoder = Geocoder(requireContext(), Locale.getDefault())” 如果有人可以帮助我,我将不胜感激
class LocationFragment : DialogFragment(), OnMapReadyCallback {
lateinit var binding: FragmentLocationBinding
private lateinit var map: GoogleMap
private val REQUEST_LOCATION_PERMISSION = 1
var lat: Double = 0.0
var long: Double = 0.0
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentLocationBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()
StrictMode.setThreadPolicy(policy)
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(requireContext())
enableMyLocation()
binding.apply {
prgBar.visibility=View.VISIBLE
btnSaveLocation.setOnClickListener {
dismiss()
}
val mapFragment = childFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this@LocationFragment)
}
}
override fun onStart() {
super.onStart()
val dialog: Dialog? = dialog
if (dialog != null) {
dialog.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
//dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}
}
override fun onMapReady(p0: GoogleMap) {
map = p0
}
private fun isPermissionGranted(): Boolean {
return ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
}
@SuppressLint("VisibleForTests")
private fun checkDeviceLocationSettings(resolve: Boolean = true) {
val locationRequest = LocationRequest.create().apply {
priority = LocationRequest.PRIORITY_LOW_POWER
}
val requestBuilder = LocationSettingsRequest.Builder().addLocationRequest(locationRequest)
val settingsClient = LocationServices.getSettingsClient(requireActivity())
val locationSettingsResponseTask =
settingsClient.checkLocationSettings(requestBuilder.build())
locationSettingsResponseTask.addOnFailureListener { exception ->
if (exception is ResolvableApiException && resolve) {
try {
exception.startResolutionForResult(
requireActivity(),
REQUEST_TURN_DEVICE_LOCATION_ON
)
} catch (sendEx: IntentSender.SendIntentException) {
Log.d(TAG, "Error getting location settings resolution: " + sendEx.message)
}
} else {
Snackbar.make(
binding.root,
R.string.location_required_error, Snackbar.LENGTH_INDEFINITE
).setAction(android.R.string.ok) {
checkDeviceLocationSettings()
}.show()
}
}
}
@TargetApi(Build.VERSION_CODES.Q)
private fun requestQPermission() {
val hasForegroundPermission = ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
if (hasForegroundPermission) {
val hasBackgroundPermission = ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_BACKGROUND_LOCATION
) == PackageManager.PERMISSION_GRANTED
if (hasBackgroundPermission) {
checkDeviceLocationSettings()
} else {
ActivityCompat.requestPermissions(
requireActivity(),
arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
REQUEST_CODE_BACKGROUND
)
}
}
}
private fun enableMyLocation() {
if (isPermissionGranted()) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
checkDeviceLocationSettings()
} else {
requestQPermission()
}
updateLocation()
} else {
ActivityCompat.requestPermissions(
context as Activity,
arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION
)
}
}
private fun updateLocation() {
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission
(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
) {
return
}
fusedLocationProviderClient.requestLocationUpdates(
locationRequest(), locationCallback,
Looper.myLooper()
)
}
private fun locationRequest(): LocationRequest {
return LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 3000)
.setWaitForAccurateLocation(false)
.setMinUpdateIntervalMillis(5000)
.setMaxUpdateDelayMillis(5000)
.build()
}
private var locationCallback = object : LocationCallback() {
override fun onLocationResult(p0: LocationResult) {
val location: Location? = p0.lastLocation
if (location != null) {
updateAddressUI(location)
}
}
}
@SuppressLint("MissingPermission")
fun updateAddressUI(location: Location) {
map.isMyLocationEnabled = true
val addressList: ArrayList<Address>
val geocoder = Geocoder(requireContext(), Locale.getDefault()) //Getting error here
addressList = geocoder.getFromLocation(
location.latitude,
location.longitude,
1
) as ArrayList<Address>
lat = addressList[0].latitude
long = addressList[0].longitude
binding.prgBar.visibility=View.INVISIBLE
Toast.makeText(requireContext(), "$lat \n $long", Toast.LENGTH_SHORT).show()
val latLng = LatLng(lat, long)
val markerOptions = MarkerOptions().position(latLng).title("I am here!")
map.animateCamera(CameraUpdateFactory.newLatLng(latLng))
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f))
map.addMarker(markerOptions)?.setIcon(bitmapFromVector(requireContext(),R.drawable.baseline_emoji_people_24))
}
private fun bitmapFromVector(context: Context, vectorResId: Int): BitmapDescriptor? {
val vectorDrawable = ContextCompat.getDrawable(context, vectorResId)
vectorDrawable!!.setBounds(0, 0, vectorDrawable.intrinsicWidth, vectorDrawable.intrinsicHeight)
val bitmap = Bitmap.createBitmap(vectorDrawable.intrinsicWidth, vectorDrawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
vectorDrawable.draw(canvas)
return BitmapDescriptorFactory.fromBitmap(bitmap)
}
override fun onResume() {
super.onResume()
enableMyLocation()
}
}
我使用了“requireActivity”而不是“requireContext”,但没有用
我这样更改了代码:
val geocoder = context?.let { Geocoder(it, Locale.getDefault()) }
在此方法中:
fun updateAddressUI(location: Location) {
map.isMyLocationEnabled = true
val addressList: ArrayList<Address>
val geocoder = context?.let { Geocoder(it, Locale.getDefault()) }
if (geocoder != null) {
addressList = geocoder.getFromLocation(
location.latitude,
location.longitude,
1
) as ArrayList<Address>
lat = addressList[0].latitude
long = addressList[0].longitude
}
正如您所说,因为当您返回到上一个片段时会发生崩溃,所以当当前片段与活动分离时,可能会调用 locationCallback。在 updateAddressUI 内部,您将在视图分离时获取上下文。
如果您的逻辑没问题,您可以将上下文引用保留在回调对象内并使用它。
尝试将 locationCallback 更改为并将上下文传递给 updateAddressUI 函数。
private var locationCallback = object : LocationCallback() {
val context = requireContext()
override fun onLocationResult(p0: LocationResult) {
val location: Location? = p0.lastLocation
if (location != null) {
updateAddressUI(location, context)
}
}
}
也像这样更改 updateAddressUI 函数。
@SuppressLint("MissingPermission")
fun updateAddressUI(location: Location, context: Context) {
map.isMyLocationEnabled = true
val addressList: ArrayList<Address>
val geocoder = Geocoder(context, Locale.getDefault()) //Getting error here
addressList = geocoder.getFromLocation(
location.latitude,
location.longitude,
1
) as ArrayList<Address>
lat = addressList[0].latitude
long = addressList[0].longitude
binding.prgBar.visibility=View.INVISIBLE
Toast.makeText(context, "$lat \n $long", Toast.LENGTH_SHORT).show()
val latLng = LatLng(lat, long)
val markerOptions = MarkerOptions().position(latLng).title("I am here!")
map.animateCamera(CameraUpdateFactory.newLatLng(latLng))
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f))
map.addMarker(markerOptions)?.setIcon(bitmapFromVector(context,R.drawable.baseline_emoji_people_24))
}