Android Studio中Google Map无法缩放至当前位置问题求助
修复getLastLocation返回null及地图无法缩放至当前位置的问题
问题根源
getLastLocation()仅返回设备上缓存的最后一次位置信息,如果是应用首次启动、设备刚重启或之前位置服务被关闭,缓存位置会不存在,导致返回null,进而无法执行地图缩放逻辑。
修复方案
我们需要添加实时位置请求逻辑,并检查位置服务是否启用,确保能获取到有效位置信息。以下是完整修复后的代码:
import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Looper; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; import androidx.fragment.app.FragmentActivity; import com.google.android.gms.common.api.ResolvableApiException; import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.LocationCallback; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationResult; import com.google.android.gms.location.LocationServices; import com.google.android.gms.location.LocationSettingsRequest; import com.google.android.gms.location.LocationSettingsResponse; import com.google.android.gms.location.SettingsClient; 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.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; public class Game_Activity extends FragmentActivity implements OnMapReadyCallback { private Location currentLocation; private FusedLocationProviderClient fusedClient; private static final int REQUEST_CODE = 101; private static final int REQUEST_CHECK_SETTINGS = 102; private FrameLayout map; private GoogleMap mMap; private LocationCallback locationCallback; private LocationRequest locationRequest; private boolean isLocationRequestInProgress = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_game); map = findViewById(R.id.map); fusedClient = LocationServices.getFusedLocationProviderClient(this); initializeLocationRequest(); initializeMap(); checkLocationSettings(); } private void initializeLocationRequest() { // 配置位置请求参数:高优先级、更新间隔 locationRequest = LocationRequest.create(); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); locationRequest.setInterval(5000); // 5秒更新一次 locationRequest.setFastestInterval(2000); // 最快2秒更新一次 // 位置回调:获取到实时位置后更新地图 locationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { if (locationResult == null) return; for (Location location : locationResult.getLocations()) { if (location != null) { currentLocation = location; if (mMap != null) { updateMap(); } // 获取到初始位置后停止实时更新 if (isLocationRequestInProgress) { fusedClient.removeLocationUpdates(locationCallback); isLocationRequestInProgress = false; } } } } }; } private void initializeMap() { // 提前初始化地图,避免等待位置时地图未加载 SupportMapFragment supportMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); if (supportMapFragment != null) { supportMapFragment.getMapAsync(this); } } private void checkLocationSettings() { // 检查设备位置服务是否启用 LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder() .addLocationRequest(locationRequest); SettingsClient client = LocationServices.getSettingsClient(this); client.checkLocationSettings(builder.build()) .addOnSuccessListener(locationSettingsResponse -> getLocation()) .addOnFailureListener(e -> { if (e instanceof ResolvableApiException) { // 位置服务未启用,弹出提示框引导用户开启 try { ResolvableApiException resolvable = (ResolvableApiException) e; resolvable.startResolutionForResult(Game_Activity.this, REQUEST_CHECK_SETTINGS); } catch (IntentSender.SendIntentException sendEx) { sendEx.printStackTrace(); } } }); } private void getLocation() { if (ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE); return; } // 先尝试获取缓存位置 fusedClient.getLastLocation() .addOnSuccessListener(location -> { if (location != null) { currentLocation = location; if (mMap != null) { updateMap(); } } else { // 无缓存位置时请求实时位置更新 if (!isLocationRequestInProgress) { isLocationRequestInProgress = true; fusedClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()); } } }) .addOnFailureListener(e -> { // 获取缓存位置失败时,直接请求实时更新 if (!isLocationRequestInProgress) { isLocationRequestInProgress = true; fusedClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()); } }); } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; mMap.getUiSettings().setScrollGesturesEnabled(false); // 如果位置已提前获取到,直接更新地图 if (currentLocation != null) { updateMap(); } } private void updateMap() { LatLng latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()); MarkerOptions markerOptions = new MarkerOptions().position(latLng).title("Player"); // 直接使用zoom动画,无需先移动再缩放 mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15)); mMap.addMarker(markerOptions); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { getLocation(); } else { Toast.makeText(this, "位置权限未授予,无法获取当前位置", Toast.LENGTH_SHORT).show(); } } } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CHECK_SETTINGS) { if (resultCode == RESULT_OK) { // 用户开启位置服务后重新获取位置 getLocation(); } else { Toast.makeText(this, "需要启用位置服务才能使用该功能", Toast.LENGTH_SHORT).show(); } } } }
关键修复点
- 添加实时位置请求:当
getLastLocation()返回null时,通过LocationRequest和LocationCallback获取实时位置更新 - 位置设置检查:通过
SettingsClient检查位置服务是否启用,引导用户开启 - 提前初始化地图:在启动时就加载地图,避免等待位置时地图未就绪
- 统一地图更新逻辑:将地图缩放和标记添加逻辑封装到
updateMap()方法,确保位置就绪时能立即更新 - 停止不必要的更新:获取到初始位置后停止实时位置更新,节省资源
内容的提问来源于stack exchange,提问作者Jonathan Kalush
相关产品推荐
相关产品推荐

