获取当前用户位置时App崩溃(Kotlin)求助
问题分析与修复方案
你的代码可编译但App无法启动,且无法获取用户当前位置,仅显示地图正常。核心问题和修复方式如下:
一、依赖冲突问题
你的build.gradle中重复引入了两个版本的play-services-location,版本不一致会导致依赖冲突,这是App启动崩溃的主要原因之一:
// 重复引入的冲突依赖,删除旧版本 implementation 'com.google.android.gms:play-services-location:11.0.2' implementation 'com.google.android.gms:play-services-location:21.0.1'
修复后仅保留最新版本的定位服务依赖:
dependencies { implementation 'androidx.preference:preference:1.0.0-rc02' implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.6.0' implementation 'com.google.android.gms:play-services-maps:18.1.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' implementation 'androidx.navigation:navigation-fragment-ktx:2.4.2' implementation 'androidx.navigation:navigation-ui-ktx:2.4.2' // 仅保留最新版本定位服务 implementation 'com.google.android.gms:play-services-location:21.0.1' implementation 'androidx.preference:preference-ktx:1.2.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' }
二、View Binding未初始化问题
你声明了_binding但未在onCreateView中初始化,虽当前未使用,但后续易引发空指针异常,修正为View Binding初始化:
override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentBuyBinding.inflate(inflater, container, false) val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext()) return binding.root } override fun onDestroyView() { super.onDestroyView() _binding = null // 避免内存泄漏 }
三、定位逻辑不完善问题
lastLocation可能返回null(如设备首次启动、无缓存位置),需添加主动请求位置更新的逻辑,同时完善权限处理和空安全:
修复后的完整BuyFragment代码:
class BuyFragment : Fragment(), OnMapReadyCallback { private var _binding: FragmentBuyBinding? = null private val binding get() = _binding!! private lateinit var map: GoogleMap private lateinit var fusedLocationClient: FusedLocationProviderClient private val locationPermissionCode = 1 // 位置请求参数配置 private val locationRequest = LocationRequest.create().apply { interval = 10000 fastestInterval = 5000 priority = LocationRequest.PRIORITY_HIGH_ACCURACY } private var locationCallback: LocationCallback? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentBuyBinding.inflate(inflater, container, false) val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext()) return binding.root } override fun onMapReady(googleMap: GoogleMap) { map = googleMap checkLocationPermission() } private fun checkLocationPermission() { if (ContextCompat.checkSelfPermission( requireContext(), Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions( requireActivity(), arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION // 补充粗略定位权限 ), locationPermissionCode ) } else { enableLocationFeatures() } } private fun enableLocationFeatures() { map.isMyLocationEnabled = true getCurrentLocation() } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == locationPermissionCode) { if (grantResults.all { it == PackageManager.PERMISSION_GRANTED }) { enableLocationFeatures() } else { Toast.makeText(requireContext(), "需要定位权限才能显示当前位置", Toast.LENGTH_SHORT).show() } } } private fun getCurrentLocation() { // 先尝试获取缓存位置 fusedLocationClient.lastLocation .addOnSuccessListener { location: Location? -> location?.let { updateMapLocation(it) } ?: requestLocationUpdate() } .addOnFailureListener { requestLocationUpdate() } } private fun requestLocationUpdate() { locationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult) { locationResult.lastLocation?.let { location -> updateMapLocation(location) // 获取到位置后停止更新 fusedLocationClient.removeLocationUpdates(this) } } } fusedLocationClient.requestLocationUpdates( locationRequest, locationCallback!!, Looper.getMainLooper() ) } private fun updateMapLocation(location: Location) { val currentLocation = LatLng(location.latitude, location.longitude) map.addMarker(MarkerOptions().position(currentLocation).title("当前位置")) map.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLocation, 15.0f)) } override fun onDestroyView() { super.onDestroyView() _binding = null // 停止位置更新,避免内存泄漏 locationCallback?.let { fusedLocationClient.removeLocationUpdates(it) } } }
四、清单文件配置补充
确保AndroidManifest.xml中添加必要权限和配置:
<!-- 定位权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- Google Maps API Key(替换为你的密钥) --> <meta-data android:name="com.google.android.geo.API_KEY" android:value="你的Google Maps API Key" /> <!-- 可选:声明GPS硬件特性 --> <uses-feature android:name="android.hardware.location.gps" android:required="false" />
内容的提问来源于stack exchange,提问作者user21119390
相关产品推荐
相关产品推荐

