Android获取最后已知位置求助:对FusedLocationProviderClient存疑
搞定FusedLocationProviderClient,获取真实设备位置
别慌!我来一步步帮你把硬编码的经纬度换成真实的设备位置,用FusedLocationProviderClient其实没那么复杂,咱们一步步来:
第一步:修改存储经纬度的类
首先把你的latlang类改成可以动态更新的,变量名也更清晰一点:
class LatLang { // 默认值用你原来的硬编码,防止首次获取不到位置时地图没显示 public static double currentLat = 28.28; public static double currentLng = 84.0; }
第二步:完善MainActivity的位置权限和获取逻辑
你已经加了权限请求,但还需要处理权限回调,以及初始化FusedLocationProviderClient并获取位置。修改后的MainActivity代码如下:
public class MainActivity extends AppCompatActivity { private FusedLocationProviderClient mFusedLocationClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager()); ViewPager viewPager = findViewById(R.id.view_pager); viewPager.setAdapter(sectionsPagerAdapter); FloatingActionButton fab = findViewById(R.id.fab); FontDrawable drawable = new FontDrawable(this, R.string.fa_plus_solid, true, false); drawable.setTextColor(ContextCompat.getColor(this, android.R.color.white)); fab.setImageDrawable(drawable); fab.setOnClickListener(view -> Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show()); // 初始化FusedLocationProviderClient mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); // 检查位置权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 101); } else { // 已经授权,直接获取位置 getCurrentLocation(); } } // 处理权限请求的回调 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 101) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { getCurrentLocation(); } else { Toast.makeText(this, "需要位置权限才能显示当前位置哦", Toast.LENGTH_SHORT).show(); } } } // 获取当前位置 private void getCurrentLocation() { try { // 先尝试获取最后已知的位置(速度快,可能为空) mFusedLocationClient.getLastLocation() .addOnSuccessListener(location -> { if (location != null) { // 更新经纬度 LatLang.currentLat = location.getLatitude(); LatLang.currentLng = location.getLongitude(); // 通知MapFragment更新地图 updateMapLocation(); } else { // 最后已知位置为空,请求实时位置更新 requestLocationUpdates(); } }) .addOnFailureListener(e -> { e.printStackTrace(); Toast.makeText(this, "获取位置失败", Toast.LENGTH_SHORT).show(); }); } catch (SecurityException e) { e.printStackTrace(); } } // 请求实时位置更新 private void requestLocationUpdates() { try { LocationRequest locationRequest = LocationRequest.create(); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); locationRequest.setInterval(5000); // 5秒更新一次,可按需调整 mFusedLocationClient.requestLocationUpdates(locationRequest, new LocationCallback() { @Override public void onLocationResult(@NonNull LocationResult locationResult) { super.onLocationResult(locationResult); if (locationResult != null && !locationResult.getLocations().isEmpty()) { Location latestLocation = locationResult.getLocations().get(locationResult.getLocations().size() - 1); // 更新经纬度 LatLang.currentLat = latestLocation.getLatitude(); LatLang.currentLng = latestLocation.getLongitude(); updateMapLocation(); // 如果只需要一次位置,获取后就停止更新 mFusedLocationClient.removeLocationUpdates(this); } } }, Looper.getMainLooper()); } catch (SecurityException e) { e.printStackTrace(); } } // 通知MapFragment更新位置 private void updateMapLocation() { Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.view_pager); if (currentFragment instanceof MapFragment) { ((MapFragment) currentFragment).updateCurrentLocation(); } } }
第三步:修改MapFragment,支持动态更新位置
我们需要保存标记的引用,这样更新位置时不需要重新添加标记,直接修改位置即可:
public class MapFragment extends Fragment { private MapView mMapView; private GoogleMap googleMap; private Marker currentMarker; // 保存当前位置的标记 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_map, container, false); mMapView = rootView.findViewById(R.id.mapView); mMapView.onCreate(savedInstanceState); mMapView.onResume(); try { MapsInitializer.requireNonNull(getActivity()).getApplicationContext(); } catch (Exception e) { e.printStackTrace(); } mMapView.getMapAsync(mMap -> { googleMap = mMap; // 初始化标记和相机位置 LatLng initialLocation = new LatLng(LatLang.currentLat, LatLang.currentLng); currentMarker = googleMap.addMarker(new MarkerOptions() .position(initialLocation) .title("我的位置") .snippet("当前所在位置")); googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(initialLocation, 12)); }); return rootView; } // 新增方法:更新当前位置 public void updateCurrentLocation() { if (googleMap != null && currentMarker != null) { LatLng newLocation = new LatLng(LatLang.currentLat, LatLang.currentLng); currentMarker.setPosition(newLocation); googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(newLocation, 12)); } } @Override public void onResume() { super.onResume(); mMapView.onResume(); } @Override public void onPause() { super.onPause(); mMapView.onPause(); } @Override public void onDestroy() { super.onDestroy(); mMapView.onDestroy(); } @Override public void onLowMemory() { super.onLowMemory(); mMapView.onLowMemory(); } }
最后别忘了检查Manifest权限
确保你的AndroidManifest.xml里添加了这些权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 可选,用于网络辅助定位 -->
一些注意事项:
- 测试时尽量用真实设备,模拟器的位置需要手动设置(在模拟器的扩展控件里可以模拟位置)
- 确保设备上的Google Play服务是最新的,FusedLocationProviderClient依赖它
- 如果只需要一次位置,获取到后记得调用
removeLocationUpdates停止更新,避免耗电
内容的提问来源于stack exchange,提问作者BaRud
相关产品推荐
相关产品推荐

