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

解决GoogleMaps.setMyLocationEnabled缺失权限及定位不显示问题

解决Google Maps Fragment中setMyLocationEnabled标红及位置不显示问题

我来帮你一步步拆解并解决这两个问题,先从代码标红的问题入手,再搞定位置不显示的问题~

一、先解决map.setMyLocationEnabled(true);标红的问题

这个红色下划线本质是编译器检测到权限逻辑不完整——你现在的代码只判断了权限未授权就直接return,但没有处理"引导用户授权"的流程,而且Android 6.0+系统要求危险权限必须动态申请。

1. 先在AndroidManifest.xml中声明必要权限

打开你的清单文件,在<manifest>标签内添加以下内容:

<!-- 基础位置权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Android 10+ 后台定位需要(如果你的应用需要后台获取位置) -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

<!-- 声明依赖GPS硬件(可选) -->
<uses-feature
    android:name="android.hardware.location.gps"
    android:required="false" />
<!-- 配置Google Maps API Key -->
<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="你的Google Maps API Key" />

记得把你的Google Maps API Key替换成你在Google Cloud平台申请的有效Key。

2. 补充动态权限申请逻辑

修改onMapReady方法,当权限未授权时发起请求,而不是直接return:

@Override
public void onMapReady(GoogleMap googleMap) {
    map = googleMap;
    
    // 检查位置权限
    if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // 发起权限请求,自定义请求码1001
        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1001);
        return;
    }
    
    // 权限已授权,启用我的位置
    map.setMyLocationEnabled(true);
    map.animateCamera(CameraUpdateFactory.zoomTo(15));
}

3. 处理权限请求结果

在Fragment中重写onRequestPermissionsResult方法,处理用户授权后的逻辑:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 1001) {
        // 判断权限是否授权成功
        boolean fineLocationGranted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
        boolean coarseLocationGranted = grantResults.length > 1 && grantResults[1] == PackageManager.PERMISSION_GRANTED;
        
        if (fineLocationGranted || coarseLocationGranted) {
            // 权限授权成功,重新启用我的位置
            if (map != null) {
                try {
                    map.setMyLocationEnabled(true);
                    map.animateCamera(CameraUpdateFactory.zoomTo(15));
                } catch (SecurityException e) {
                    e.printStackTrace();
                }
            }
        } else {
            // 用户拒绝权限,弹出提示说明必要性
            Toast.makeText(mContext, "需要位置权限才能显示你的位置", Toast.LENGTH_SHORT).show();
        }
    }
}

做完这三步,setMyLocationEnabled的红色下划线应该就消失了——因为我们保证了只有在权限授权后才会调用该方法,编译器不会再提示权限风险。

二、解决位置未标记/不显示的问题

你代码里有updateCurrentLocationMarker方法,但没有触发它的逻辑:也就是没有主动获取设备当前位置的代码。我们用Google推荐的FusedLocationProviderClient来实现位置获取。

1. 添加位置服务依赖

在build.gradle(Module level)的dependencies中添加:

implementation 'com.google.android.gms:play-services-location:21.0.1'

版本号可以用最新的稳定版。

2. 初始化位置客户端并获取当前位置

在Fragment中添加相关变量和方法:

private FusedLocationProviderClient fusedLocationClient;

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mContext = getActivity();
    
    // 初始化FusedLocationProviderClient
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(mContext);
    
    FragmentManager fm = getActivity().getSupportFragmentManager();
    supportMapFragment = (SupportMapFragment) fm.findFragmentById(R.id.map_container);
    if (supportMapFragment == null) {
        supportMapFragment = SupportMapFragment.newInstance();
        fm.beginTransaction().replace(R.id.map_container, supportMapFragment).commit();
    }
    supportMapFragment.getMapAsync(this);
}

// 获取当前位置
private void getCurrentLocation() {
    if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    fusedLocationClient.getLastLocation()
            .addOnSuccessListener(location -> {
                // 获取位置成功,更新标记
                if (location != null) {
                    updateCurrentLocationMarker(location);
                } else {
                    // 如果获取不到历史位置,请求实时位置更新
                    requestLocationUpdates();
                }
            })
            .addOnFailureListener(e -> {
                e.printStackTrace();
                Toast.makeText(mContext, "获取位置失败", Toast.LENGTH_SHORT).show();
            });
}

// 请求实时位置更新
private void requestLocationUpdates() {
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setInterval(10000); // 10秒更新一次
    locationRequest.setFastestInterval(5000); // 最快5秒更新一次
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    
    if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());
}

// 位置更新回调
private final LocationCallback locationCallback = new LocationCallback() {
    @Override
    public void onLocationResult(LocationResult locationResult) {
        super.onLocationResult(locationResult);
        if (locationResult != null && locationResult.getLocations().size() > 0) {
            int latestIndex = locationResult.getLocations().size() - 1;
            Location location = locationResult.getLocations().get(latestIndex);
            // 更新标记
            updateCurrentLocationMarker(location);
            // 如果只需要一次位置,可以停止更新
            fusedLocationClient.removeLocationUpdates(locationCallback);
        }
    }
};

3. 触发位置获取逻辑

修改onRequestPermissionsResult和onMapReady方法,在权限授权成功后调用getCurrentLocation():

// 修改onRequestPermissionsResult
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 1001) {
        boolean fineLocationGranted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
        boolean coarseLocationGranted = grantResults.length > 1 && grantResults[1] == PackageManager.PERMISSION_GRANTED;
        
        if (fineLocationGranted || coarseLocationGranted) {
            if (map != null) {
                try {
                    map.setMyLocationEnabled(true);
                    map.animateCamera(CameraUpdateFactory.zoomTo(15));
                    // 获取当前位置并更新标记
                    getCurrentLocation();
                } catch (SecurityException e) {
                    e.printStackTrace();
                }
            }
        } else {
            Toast.makeText(mContext, "需要位置权限才能显示你的位置", Toast.LENGTH_SHORT).show();
        }
    }
}

// 修改onMapReady
@Override
public void onMapReady(GoogleMap googleMap) {
    map = googleMap;
    
    if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1001);
        return;
    }
    
    map.setMyLocationEnabled(true);
    map.animateCamera(CameraUpdateFactory.zoomTo(15));
    // 直接获取当前位置
    getCurrentLocation();
}

三、额外注意事项

  • 确保你的Google Maps API Key已经启用了Maps SDK for Android和Location Services,否则会无法加载地图或获取位置。
  • 测试时请打开设备的位置服务(GPS或网络定位)。
  • 针对Android 12+的应用,需要额外处理权限申请的弹窗逻辑,确保用户授予位置权限。

这样修改后,你的地图应该能正常显示你的位置标记,setMyLocationEnabled的红色下划线也会消失啦。

内容的提问来源于stack exchange,提问作者BlueYeti81

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:27:58