You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

地图不显示标记问题:Android定位Marker无显示求助

解决Android地图应用不显示用户位置Marker的问题

我仔细看了你的代码和遇到的问题,咱们一步步拆解并修复这些问题——毕竟你已经成功获取了GPS权限,但不管是模拟器还是真机都没正常显示用户位置标记,核心是几个细节没处理到位:


1. 只依赖GPS_PROVIDER导致真机定位失败

GPS在室内、地下或者信号弱的环境下很难快速获取到位置,甚至完全拿不到信号。你目前只监听了LocationManager.GPS_PROVIDER,这会导致真机在多数非户外场景下无法获取到位置,自然不会显示Marker。

修复方案

  • 同时监听NETWORK_PROVIDER(利用基站/WiFi进行网络定位,室内也能快速获取大致位置);
  • 更推荐使用Google官方的FusedLocationProviderClient,它会自动切换最优的定位源(GPS/网络),既省电又可靠(后面会给示例代码)。

2. getLastKnownLocation可能返回null,直接调用会崩溃或无效果

你在权限通过的else分支里直接使用lastLoc.getLatitude(),但如果设备从未获取过GPS位置,lastLoc就是null,直接调用会引发空指针异常,就算没崩溃也不会显示Marker。

修复代码

Location lastLoc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
// 必须先判空再使用
if (lastLoc != null) {
    LatLng loc = new LatLng(lastLoc.getLatitude(), lastLoc.getLongitude());
    mMap.clear();
    mMap.addMarker(new MarkerOptions().position(loc).title("person").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE)));
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(loc, 15));
}

3. 模拟器定位需要手动模拟位置

模拟器没有真实的GPS硬件,默认不会有定位数据,你需要手动设置模拟位置:

  • 打开模拟器的「Extended Controls」(右侧三个点的按钮);
  • 切换到「Location」选项卡,输入经纬度或选择预设地点,点击「Send」发送模拟位置;
  • 也可以在代码里加个默认位置作为 fallback,比如测试用的悉尼坐标,避免模拟器完全无显示。

4. 权限回调后未初始化Marker

onRequestPermissionsResult里,你只调用了locationManager.requestLocationUpdates,但如果此时还没有位置更新触发,地图上就不会有Marker。可以在权限通过后,也尝试获取一次lastKnownLocation并添加Marker,和else分支的逻辑一致:

修复后的onRequestPermissionsResult

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 1) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
                // 新增:尝试获取最后已知位置并添加Marker
                Location lastLoc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                if (lastLoc != null) {
                    LatLng loc = new LatLng(lastLoc.getLatitude(), lastLoc.getLongitude());
                    mMap.clear();
                    mMap.addMarker(new MarkerOptions().position(loc).title("person").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE)));
                    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(loc, 15));
                }
            }
        }
    }
}

推荐:使用FusedLocationProvider替代LocationManager

Google现在更推荐使用Fused Location Provider,它封装了复杂的定位逻辑,比直接用LocationManager更稳定。以下是简化的示例代码:

第一步:添加依赖

build.gradle(Module level)里添加:

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

第二步:替换定位逻辑

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
    private GoogleMap mMap;
    private FusedLocationProviderClient fusedLocationClient;
    private LocationCallback locationCallback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);

        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        // 处理权限和定位逻辑
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            // 获取最后已知位置
            getLastKnownLocation();
            // 请求实时位置更新
            requestLocationUpdates();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
        }
    }

    // 获取最后已知位置
    private void getLastKnownLocation() {
        fusedLocationClient.getLastLocation()
                .addOnSuccessListener(this, location -> {
                    if (location != null) {
                        updateUserMarker(location);
                    }
                });
    }

    // 请求实时位置更新
    private void requestLocationUpdates() {
        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setInterval(10000); // 10秒更新一次
        locationRequest.setFastestInterval(5000); // 最快5秒更新一次
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        locationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                if (locationResult == null) return;
                for (Location location : locationResult.getLocations()) {
                    updateUserMarker(location);
                }
            }
        };

        fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());
    }

    // 更新用户位置Marker
    private void updateUserMarker(Location location) {
        LatLng person = new LatLng(location.getLatitude(), location.getLongitude());
        mMap.clear();
        mMap.addMarker(new MarkerOptions().position(person).title("person").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE)));
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(person, 15));
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 1) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                    getLastKnownLocation();
                    requestLocationUpdates();
                }
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 销毁时停止位置更新,避免耗电
        if (locationCallback != null) {
            fusedLocationClient.removeLocationUpdates(locationCallback);
        }
    }
}

最后检查Manifest配置

确保AndroidManifest.xml里已经添加了必要的权限:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />

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

火山引擎 最新活动