You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:53:38