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

Android应用中onLocationChanged未触发,无法获取定位求助

解决Android定位onLocationChanged未触发的问题

我仔细看了你的代码,几个关键问题导致onLocationChanged始终没有被调用,下面逐个分析并给出可落地的修复方案:

1. 地图初始化异步导致的时序问题

你在onCreate里直接发起位置更新请求,但mMap是在onMapReady异步回调中才完成赋值的——这不仅会导致onLocationChanged里操作mMap时触发空指针异常,更关键的是,如果在地图初始化完成前就发起位置请求,系统可能会延迟甚至拒绝回调位置更新。

修复方案:把位置监听的逻辑移到onMapReady方法中,确保mMap初始化完成后再启动定位:

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    // 先移除默认的悉尼测试标记
    mMap.clear();
    // 在这里初始化位置监听逻辑
    setupLocationUpdates();
}

// 把原来onCreate里的定位逻辑抽成独立方法,方便复用
private void setupLocationUpdates() {
    locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
    // 权限检查与请求
    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) {
        // 主动发起权限请求,而不是只提示就返回
        ActivityCompat.requestPermissions(this,
                new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION},
                1001); // 自定义请求码,后续回调用
        return;
    }

    // 不要用else if,同时监听两种定位源(如果可用)
    if(locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
    }
    if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
    }

    // 处理两种定位源都不可用的情况
    if(!locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) 
       && !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
        Toast.makeText(this, "请启用GPS或网络定位", Toast.LENGTH_LONG).show();
        // 可选:直接跳转到系统定位设置页面
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        startActivity(intent);
    }
}

// 把匿名LocationListener抽成成员变量,方便后续移除监听避免内存泄漏
private LocationListener locationListener = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        LatLng latLng=new LatLng(latitude,longitude);
        // 清除旧标记,避免地图上出现多个重复标记
        mMap.clear();
        mMap.addMarker(new MarkerOptions().position(latLng).title("Bus Location"));
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,17.0f));
    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {}

    @Override
    public void onProviderEnabled(String s) {}

    @Override
    public void onProviderDisabled(String s) {
        Toast.makeText(MapsActivity2.this, "请启用GPS和网络", Toast.LENGTH_SHORT).show();
    }
};

2. 权限处理不完整

你的代码只做了权限检查,但没有处理"权限未授予"的情况——如果用户第一次打开应用,权限默认是未授予的,代码直接return,根本不会进入定位监听逻辑。

需要添加权限请求的回调处理:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode == 1001) {
        boolean allPermissionsGranted = true;
        for(int result : grantResults) {
            if(result != PackageManager.PERMISSION_GRANTED) {
                allPermissionsGranted = false;
                break;
            }
        }
        if(allPermissionsGranted) {
            // 权限授予后,重新启动定位监听
            setupLocationUpdates();
        } else {
            Toast.makeText(this, "需要定位权限才能获取当前位置", Toast.LENGTH_LONG).show();
        }
    }
}

3. 清单文件缺少必要权限声明

你必须在AndroidManifest.xml中添加定位相关权限,否则就算代码里请求权限也无法正常获取位置:

<!-- 精确定位权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 粗略定位权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Android 12及以上需要额外添加的权限 -->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<!-- 网络定位依赖的网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />

4. 其他需要检查的细节

  • 测试环境:如果用模拟器,需要在模拟器设置中手动模拟位置(输入经纬度);如果是真机,尽量在室外或GPS信号良好的环境测试,室内GPS定位可能很慢甚至无法获取。
  • 内存泄漏防护:在Activity销毁时记得移除位置监听:
@Override
protected void onDestroy() {
    super.onDestroy();
    if(locationManager != null && locationListener != null) {
        locationManager.removeUpdates(locationListener);
    }
}
  • Google Play Services版本:确保设备上的Google Play Services是最新版本,旧版本可能存在定位兼容性问题。

按照上面的步骤修改后,onLocationChanged应该能正常触发并更新地图位置了。

内容的提问来源于stack exchange,提问作者Mathews P Mathew

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:28:28