如何修改MapsActivity实现位置随用户移动自动更新?
实现位置自动更新的修改方案
看起来你已经搭建好了基础的位置获取框架,但目前需要手动点击图标触发更新。要实现位置随用户移动自动更新,我们需要让应用持续监听位置变化,而不是仅在手动触发时获取一次位置。下面是具体的修改步骤和完整代码:
核心修改点
- 在GoogleApiClient连接成功后,主动发起持续位置更新请求
- 完善
LocationRequest配置,确保位置变化能被及时捕获 - 修复原代码中
onLocationChanged方法的未完成错误 - 优化生命周期管理,避免不必要的耗电
步骤1:配置LocationRequest参数
添加一个方法来初始化位置请求的规则,比如更新间隔、精度优先级等,平衡更新频率和耗电:
private void createLocationRequest() { locationRequest = LocationRequest.create(); // 设置位置更新的间隔(毫秒),这里设为5秒 locationRequest.setInterval(5000); // 设置最快更新间隔,避免系统频繁唤醒设备 locationRequest.setFastestInterval(2000); // 设置高精度优先级,确保获取准确的位置数据 locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); }
步骤2:在连接成功后启动位置监听
当GoogleApiClient连接完成时,调用requestLocationUpdates开始持续监听位置变化,同时初始化当前位置标记:
@Override public void onConnected(@Nullable Bundle bundle) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { // 先获取一次当前位置作为初始值 lastLocation = LocationServices.FusedLocationApi.getLastLocation(client); if (lastLocation != null) { updateLocationMarker(lastLocation); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude()), 15)); } // 启动持续位置更新监听 LocationServices.FusedLocationApi.requestLocationUpdates(client, locationRequest, this); } }
步骤3:修复并优化onLocationChanged方法
移除原代码中未完成的语句,提取标记更新逻辑为复用方法,避免重复代码:
@Override public void onLocationChanged(Location location) { lastLocation = location; // 更新当前位置标记 updateLocationMarker(location); // 可选:让地图跟随位置移动,不需要的话可以注释掉 mMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(), location.getLongitude()))); } // 单独提取标记更新方法,代码更整洁 private void updateLocationMarker(Location location) { if(currentLocationMarker != null){ currentLocationMarker.remove(); } LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(latLng); markerOptions.title("Current Location"); markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)); currentLocationMarker = mMap.addMarker(markerOptions); }
步骤4:优化生命周期管理(推荐)
在Activity暂停时停止位置更新,恢复时重新启动,减少后台耗电:
@Override protected void onPause() { super.onPause(); if (client != null) { LocationServices.FusedLocationApi.removeLocationUpdates(client, this); } } @Override protected void onResume() { super.onResume(); if (client != null && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { LocationServices.FusedLocationApi.requestLocationUpdates(client, locationRequest, this); } }
步骤5:在构建GoogleApiClient时初始化请求
确保在创建GoogleApiClient实例前初始化LocationRequest:
protected synchronized void buildGoogleApiClient(){ createLocationRequest(); // 新增这行,初始化位置请求 client = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); client.connect(); }
完整修改后的代码
import android.Manifest; import android.content.pm.PackageManager; import android.location.Location; import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentActivity; import android.os.Bundle; import android.support.v4.content.ContextCompat; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationListener; import com.google.android.gms.location.LocationRequest; 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.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { private GoogleMap mMap; private GoogleApiClient client; private LocationRequest locationRequest; private Location lastLocation; private Marker currentLocationMarker; public static final int REQUEST_LOCATION_CODE = 99; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ checkLocationPermission(); } // 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); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch(requestCode) { case REQUEST_LOCATION_CODE: if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //permission is granted if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if(client == null){ buildGoogleApiClient(); } mMap.setMyLocationEnabled(true); } } else { Toast.makeText(this, "Permission Denied!", Toast.LENGTH_LONG).show(); //Permission is denied } return; } } @Override public void onMapReady(GoogleMap googleMap) { Toast.makeText(this, "位置将自动跟随更新", Toast.LENGTH_LONG).show(); mMap = googleMap; LatLng Phoenix = new LatLng(33.6056711, -112.4052378); mMap.addMarker(new MarkerOptions().position(Phoenix).title("Default Location: Phoenix, AZ")); mMap.moveCamera(CameraUpdateFactory.newLatLng(Phoenix)); if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { buildGoogleApiClient(); mMap.setMyLocationEnabled(true); } } protected synchronized void buildGoogleApiClient(){ createLocationRequest(); client = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); client.connect(); } private void createLocationRequest() { locationRequest = LocationRequest.create(); locationRequest.setInterval(5000); // 5秒更新一次 locationRequest.setFastestInterval(2000); // 最快2秒更新一次 locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); } @Override public void onConnected(@Nullable Bundle bundle) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { lastLocation = LocationServices.FusedLocationApi.getLastLocation(client); if (lastLocation != null) { updateLocationMarker(lastLocation); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude()), 15)); } LocationServices.FusedLocationApi.requestLocationUpdates(client, locationRequest, this); } } @Override public void onConnectionSuspended(int i) { // 连接暂停时重新尝试连接 client.connect(); } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { Toast.makeText(this, "Google Play Services连接失败", Toast.LENGTH_SHORT).show(); } @Override public void onLocationChanged(Location location) { lastLocation = location; updateLocationMarker(location); // 可选:取消注释可以让地图跟随位置移动 mMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(), location.getLongitude()))); } private void updateLocationMarker(Location location) { if(currentLocationMarker != null){ currentLocationMarker.remove(); } LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(latLng); markerOptions.title("Current Location"); markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)); currentLocationMarker = mMap.addMarker(markerOptions); } public boolean checkLocationPermission(){ if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_CODE); return false; } return true; } @Override protected void onPause() { super.onPause(); if (client != null) { LocationServices.FusedLocationApi.removeLocationUpdates(client, this); } } @Override protected void onResume() { super.onResume(); if (client != null && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { LocationServices.FusedLocationApi.requestLocationUpdates(client, locationRequest, this); } } }
额外说明
- 现在应用启动后会自动连接GoogleApiClient,并持续监听位置变化,新位置获取后标记会自动更新
- 你可以调整
locationRequest.setInterval和setFastestInterval的数值,根据需求平衡更新频率与耗电 - 如果不需要地图自动跟随移动,注释掉
onLocationChanged中的mMap.moveCamera语句即可
内容的提问来源于stack exchange,提问作者Tanner Tattini
相关产品推荐
相关产品推荐

