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

Android Studio中如何实现每次启动应用都正常获取当前位置及地址

Android 稳定获取当前位置及完整地址解决方案

你遇到的问题核心有两个:getLastLocation()依赖系统缓存极易返回空、Geocoder 同步方法直接在主线程调用容易超时失败。可按以下方案修改:


1. 核心问题说明

  • getLastLocation() 只会读取系统缓存的位置信息,当缓存过期、设备从未记录过位置、定位开关刚打开时,大概率返回null,无法满足启动必获取的需求
  • Geocoder.getFromLocation() 是网络/IO 同步操作,Android 9及以上系统禁止在主线程调用该接口,直接执行会触发ANR、超时、返回空等问题

2. 具体修改方案

2.1 替换缓存位置请求为实时位置请求

使用FusedLocationProviderClient主动请求实时位置,不要依赖缓存,同时提前检查权限和定位开关状态:

private FusedLocationProviderClient fusedLocationClient;
private LocationRequest locationRequest;
private LocationCallback locationCallback;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.your_layout, container, false);
    userLocation = root.findViewById(R.id.user_location_tv);
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext());
    
    // 配置位置请求参数
    locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(10000);
    locationRequest.setFastestInterval(5000);
    locationRequest.setNumUpdates(1); // 仅获取1次位置就停止更新,降低功耗

    // 位置结果回调
    locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(@NonNull LocationResult locationResult) {
            super.onLocationResult(locationResult);
            Location location = locationResult.getLastLocation();
            if (location != null) {
                Log.e("Getting Lat", String.valueOf(location.getLatitude()));
                Log.e("Getting Long", String.valueOf(location.getLongitude()));
                // 子线程执行逆地理编码,避免阻塞主线程
                new Thread(() -> {
                    String address = getCompleteAddressString(location.getLatitude(), location.getLongitude());
                    // 切回主线程更新UI
                    requireActivity().runOnUiThread(() -> {
                        userLocation.setText(address.trim());
                    });
                }).start();
                // 拿到位置后主动移除回调,避免持续耗电
                fusedLocationClient.removeLocationUpdates(locationCallback);
            }
        }
    };

    // 先检查定位服务是否开启
    LocationManager locationManager = (LocationManager) requireContext().getSystemService(Context.LOCATION_SERVICE);
    boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    if (!isGpsEnabled && !isNetworkEnabled) {
        Toast.makeText(requireContext(), "请先开启定位服务", Toast.LENGTH_SHORT).show();
        // 可选:跳转到系统定位设置页
        startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
        return root;
    }

    // 检查位置权限
    if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());
    } else {
        // 申请位置权限,权限申请通过回调中重新执行上述位置请求逻辑即可
        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1001);
    }
    return root;
}

2.2 优化逆地理编码逻辑

getCompleteAddressString 本身逻辑不需要大改,增加默认值和空判断即可,确保在子线程调用:

private String getCompleteAddressString(double LATITUDE, double LONGITUDE) {
    String strAdd = "暂无地址信息"; // 增加默认返回值,避免空展示
    Geocoder geocoder = new Geocoder(requireContext(), Locale.getDefault());
    try {
        List<Address> addresses = geocoder.getFromLocation(LATITUDE, LONGITUDE, 1);
        if (addresses != null && !addresses.isEmpty()) {
            Address returnedAddress = addresses.get(0);
            StringBuilder strReturnedAddress = new StringBuilder();
            for (int i = 0; i <= returnedAddress.getMaxAddressLineIndex(); i++) {
                strReturnedAddress.append(returnedAddress.getAddressLine(i)).append("\n");
            }
            strAdd = strReturnedAddress.toString().trim();
            Log.e("My location address", strAdd);
        } else {
            Log.e("My Current location address", "No Address returned!");
        }
    } catch (IOException e) {
        e.printStackTrace();
        Log.e("My Current location address", "Cannot get Address!");
    }
    return strAdd;
}

3. 补充优化建议

  • 国内无Google服务的设备可替换为系统原生LocationManager请求位置,稳定性更高
  • 若Geocoder频繁返回空,可接入高德、百度等国内地图服务商的逆地理编码接口,适配性更好
  • 可增加3次以内的重试机制,每次间隔1s,进一步提升成功率

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 01:36:03