You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取当前用户位置时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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:10:16