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

Android Java Fragment获取当前位置功能异常问题求助

问题修复方案

你遇到的真机无法获取位置权限、模拟器弹出位置Toast但地图无标记的问题,全部来自代码逻辑错误,按以下内容修复即可。

核心错误点

  • 权限判断逻辑写反
    当前onCreateView中的逻辑为:两个位置权限都未授予时,直接调用需要权限的getCurrentLocation();只要有任意一个权限已授予,反而发起权限申请,直接导致真机权限流程完全错乱,无法正常弹出权限申请弹窗。
  • 地图实例从未初始化
    虽然实现了OnMapReadyCallback接口,但从未在布局加载完成后绑定SupportMapFragment、注册地图就绪回调,mMap变量始终为null。模拟器上能弹出位置Toast是因为位置获取逻辑独立运行,执行到mMap.addMarker时直接触发空指针,地图自然不会显示任何标记。
  • 权限回调逻辑错误
    用grantResults[0] + grantResults[1] == PackageManager.PERMISSION_GRANTED判断权限授予状态是完全错误的写法,同时给onRequestPermissionsResult加了MissingSuperCall抑制注解、不调用父类实现,会导致Fragment权限回调分发异常。
  • 缺少边界判断、重复调用位置逻辑
    多次在不同生命周期调用getCurrentLocation(),会重复注册位置监听造成内存泄漏;操作地图前没有判空,也没有检查设备位置服务开关,真机上极易出现位置返回null、操作崩溃的问题。
  • 线程使用错误
    注册位置更新时传入Looper.myLooper(),如果调用时不在主线程,位置回调会跑在子线程,无法正常操作UI。

前置检查

先确认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.INTERNET" />

同时确认布局文件中的SupportMapFragment设置了id,后续绑定地图实例需要用到。

修复后核心代码

public class HospitalFragmentMap extends Fragment implements OnMapReadyCallback {

    GoogleMap mMap;
    private double lat, lng;
    private static final int REQUEST_CODE = 101;
    private FusedLocationProviderClient client;
    private LocationCallback locationCallback;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_hospital_map, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        client = LocationServices.getFusedLocationProviderClient(requireActivity());
        
        // 绑定地图Fragment,注册回调,保证onMapReady能正常触发
        SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager()
                .findFragmentById(R.id.map); // 替换为你布局里MapFragment的实际id
        if (mapFragment != null) {
            mapFragment.getMapAsync(this);
        }

        // 修正权限判断:未授权时才申请权限
        if (ContextCompat.checkSelfPermission(requireActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(requireActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
        }
    }

    @SuppressLint("MissingPermission")
    private void getCurrentLocation(){
        // 先检查设备位置服务是否开启
        LocationManager lm = (LocationManager) requireContext().getSystemService(Context.LOCATION_SERVICE);
        boolean gpsEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        boolean networkEnabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        if (!gpsEnabled && !networkEnabled) {
            Toast.makeText(requireContext(), "请先开启设备位置服务", Toast.LENGTH_SHORT).show();
            startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
            return;
        }

        // 地图未初始化完成时直接返回,等onMapReady触发后再执行
        if (mMap == null) return;
        // 开启地图自带的当前位置图层
        mMap.setMyLocationEnabled(true);

        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setInterval(50000);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setFastestInterval(5000);

        locationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(@NonNull LocationResult locationResult) {
                if (locationResult == null) return;
                for (Location location : locationResult.getLocations()) {
                    if (location != null) {
                        lat = location.getLatitude();
                        lng = location.getLongitude();
                        LatLng latLng = new LatLng(lat, lng);
                        if (mMap != null) {
                            mMap.clear();
                            mMap.addMarker(new MarkerOptions().position(latLng).title("当前位置"));
                            mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));
                        }
                        // 拿到位置后停止更新,节省电量
                        client.removeLocationUpdates(locationCallback);
                        break;
                    }
                }
            }
        };
        // 传入主线程Looper,保证回调在主线程执行
        client.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        // 必须调用父类实现,不要加SuppressLint("MissingSuperCall")
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE) {
            boolean fineGranted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
            boolean coarseGranted = grantResults.length > 1 && grantResults[1] == PackageManager.PERMISSION_GRANTED;
            if (fineGranted || coarseGranted) {
                getCurrentLocation();
            } else {
                Toast.makeText(requireContext(), "位置权限被拒绝,无法获取当前位置", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public void onMapReady(@NonNull GoogleMap googleMap) {
        mMap = googleMap;
        // 地图初始化完成后,有权限再获取位置
        if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            getCurrentLocation();
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // 销毁时移除位置监听,避免内存泄漏
        if (client != null && locationCallback != null) {
            client.removeLocationUpdates(locationCallback);
        }
    }
}

内容的提问来源于stack exchange,提问作者Badr Ozgar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 06:51:22