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
相关产品推荐
相关产品推荐

