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

Google Map获取设备位置时崩溃问题求助

问题分析与解决方案

你的地图崩溃主要有三个核心问题:权限判断逻辑错误、同步获取异步位置结果导致空指针、缺失权限申请流程。我来一步步帮你修正:

问题拆解

  1. 权限判断逻辑错误:原代码用&&判断两个权限是否都未授予,但实际上只要有一个权限未授予就无法获取位置,应该用||。而且当权限未授予时,你没有发起权限申请,直接跳过导致后续位置获取失败。
  2. 错误同步获取位置结果:fusedLocationClient.getLastLocation()是异步任务,直接调用getResult()会在任务未完成时拿到null,触发空指针异常,这是崩溃的主要原因。
  3. 未处理位置为空的场景:即使权限正常,getLastLocation()也可能返回null(比如设备从未定位过),需要做空值判断。

修正后的完整代码

package com.example.myapplication;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.location.Location;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.tasks.OnSuccessListener;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
    private GoogleMap mMap;
    private FusedLocationProviderClient fusedLocationClient;
    // 权限请求码,自定义即可
    private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        // 先添加默认的悉尼标记
        LatLng sydney = new LatLng(-34, 151);
        mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));

        // 检查定位权限
        checkLocationPermission();
    }

    // 封装权限检查逻辑
    private void checkLocationPermission() {
        if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                || checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // 权限未授予,发起申请
            requestPermissions(
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
                    LOCATION_PERMISSION_REQUEST_CODE
            );
        } else {
            // 权限已授予,获取当前位置
            getCurrentLocation();
        }
    }

    // 异步获取当前位置并添加标记
    private void getCurrentLocation() {
        fusedLocationClient.getLastLocation()
                .addOnSuccessListener(this, new OnSuccessListener<Location>() {
                    @Override
                    public void onSuccess(Location location) {
                        // 位置不为空才处理
                        if (location != null) {
                            LatLng currentLatLng = new LatLng(location.getLatitude(), location.getLongitude());
                            mMap.addMarker(new MarkerOptions().position(currentLatLng).title("Marker in Home"));
                            // 可选:将地图镜头移动到当前位置
                            mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15));
                        } else {
                            // 位置为空的处理,比如提示用户开启定位
                            // Toast.makeText(MapsActivity.this, "无法获取当前位置,请检查定位设置", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }

    // 处理权限申请结果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
            // 检查所有申请的权限是否都被授予
            boolean allGranted = true;
            for (int result : grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    allGranted = false;
                    break;
                }
            }
            if (allGranted) {
                // 权限授予成功,获取当前位置
                getCurrentLocation();
            } else {
                // 权限被拒绝,可以提示用户需要权限才能显示当前位置
                // Toast.makeText(this, "需要定位权限才能显示当前位置", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

关键修正点说明

  • 权限逻辑优化:把权限检查封装成独立方法,用||判断是否有未授予的权限,未授予时主动发起权限申请。
  • 异步获取位置:使用addOnSuccessListener监听位置获取结果,避免同步调用导致的空指针。
  • 权限回调处理:重写onRequestPermissionsResult,在用户授予权限后再去获取位置,保证流程完整。
  • 空值处理:添加位置为空的判断,避免因设备未定位导致的崩溃。

另外,别忘了在AndroidManifest.xml中添加权限声明:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:18:21