Google Map获取设备位置时崩溃问题求助
问题分析与解决方案
你的地图崩溃主要有三个核心问题:权限判断逻辑错误、同步获取异步位置结果导致空指针、缺失权限申请流程。我来一步步帮你修正:
问题拆解
- 权限判断逻辑错误:原代码用
&&判断两个权限是否都未授予,但实际上只要有一个权限未授予就无法获取位置,应该用||。而且当权限未授予时,你没有发起权限申请,直接跳过导致后续位置获取失败。 - 错误同步获取位置结果:
fusedLocationClient.getLastLocation()是异步任务,直接调用getResult()会在任务未完成时拿到null,触发空指针异常,这是崩溃的主要原因。 - 未处理位置为空的场景:即使权限正常,
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
相关产品推荐
相关产品推荐

