Android Google Maps首次请求定位权限触发SecurityException崩溃
崩溃根因
@SuppressLint("MissingPermission")注解仅用于屏蔽编译阶段的Lint权限警告,不会在运行时自动做权限校验,你的代码存在两个核心问题:
- 执行时序错误:
onViewCreated中直接调用getMapAsync加载地图,地图加载完成后会立刻触发onMapReady回调,这个回调时机早于你的权限申请、授权流程。首次启动时位置权限还未授予,onMapReady中没有做权限判断就直接调用gMap.setMyLocationEnabled(true)——该方法必须持有位置权限才能调用,直接触发SecurityException崩溃,此时权限弹窗刚弹出,应用已经闪退。 - 逻辑遗漏:你写的
checkLocationPermission()仅在onResume中调用,权限申请成功的回调里没有同步开启地图的位置图层、也没有触发地图位置更新;同时onMapReady里先添加标记再调用gMap.clear(),刚添加的标记会被直接清空,属于顺序写反的逻辑错误。
修复方案
按以下步骤修改代码即可解决问题:
- 修改
onMapReady逻辑,调用位置相关API前先做运行时权限校验,同时修正标记添加、清除的顺序:
@Override public void onMapReady(@NonNull GoogleMap googleMap) { gMap = googleMap; // 有权限才开启我的位置图层 if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) { gMap.setMyLocationEnabled(true); } gMap.clear(); // 先清空旧标记,再添加新标记 // 未拿到位置前使用默认坐标,避免0,0经纬度定位到大西洋 LatLng currentPos = new LatLng(39.9042, 116.4074); if (latitude != 0 && longitude != 0) { currentPos = new LatLng(latitude, longitude); } gMap.addMarker(new MarkerOptions().position(currentPos).title("当前位置")); gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentPos, 15f)); }
- 补全权限申请成功回调的逻辑,拿到权限后同步开启地图位置图层、启动位置更新:
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case MY_PERMISSION_REQUEST_ACCESS_FINE_LOCATION: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Log.d("Location", "Now the permission is granted"); fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity()); // 权限授予后再开启地图位置图层 if (gMap != null) { gMap.setMyLocationEnabled(true); } startLocationUpdates(); getLastKnownLocation(); } else { Log.d("Location", "Permission still not granted"); } break; } } }
- 在位置更新回调里同步刷新地图标记和视角,确保拿到新位置后地图能自动跟进:
@Override public void onLocationResult(LocationResult locationResult) { if (locationResult == null) { Log.d("main_activiyt_maps", "location request is null"); return; } for (Location location : locationResult.getLocations()) { Log.d("Location", "New Location received: " + location.toString()); latitude = location.getLatitude(); longitude = location.getLongitude(); Log.d("main_activiyt_maps", String.valueOf(latitude)); Log.d("main_activiyt_maps", String.valueOf(longitude)); // 拿到新位置后刷新地图 if (gMap != null) { gMap.clear(); LatLng currentPos = new LatLng(latitude, longitude); gMap.addMarker(new MarkerOptions().position(currentPos).title("当前位置")); gMap.animateCamera(CameraUpdateFactory.newLatLngZoom(currentPos, 15f)); } } }
内容的提问来源于stack exchange,提问作者Elly
相关产品推荐
相关产品推荐

