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

Android LocationServices仅返回一次位置的问题求助

位置日志记录器仅获取一次位置的问题排查与修复

问题描述

实现一个位置日志记录器,要求在特定时间间隔(60秒)或位置移动至少50米时存储位置信息,但启动后仅能获取一次位置,修改模拟器位置后无响应。已授予ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION、WRITE_EXTERNAL_STORAGE权限,使用带Play Store的模拟器,测试过API 30-33版本,调整LocationRequest参数、替换Callback为监听器均无效。

问题代码

import android.annotation.SuppressLint;
import android.location.Location;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.Granularity;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.Priority;
import com.google.android.gms.tasks.OnCanceledListener;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;

import de.remi.locker.database.entities.Trip;
import de.remi.locker.util.MapsHelper;
import de.remi.locker.util.PermissionHelper;

public class AndroidLogger implements AutoLogger.ILoggerClient {
    private static final String TAG = "AndroidLogger";
    private final FragmentActivity activity;
    private FusedLocationProviderClient client;
    private LocationCallback callBack;

    public AndroidLogger(FragmentActivity activity) {
        this.activity = activity;
        init();
    }

    private void init() {
        client = LocationServices.getFusedLocationProviderClient(activity);
        callBack = new LocationCallback() {
            @Override
            public void onLocationResult(@NonNull LocationResult locationResult) {
                locationResult.getLocations().forEach(location -> handleLocation(location));
            }
        };
    }

    private void handleLocation(Location location) {
        Log.d(TAG, "handleLocation: " + location);
    }

    private LocationRequest getLocationRequest() {
        LocationRequest.Builder builder = new LocationRequest.Builder(10000);
        builder.setMinUpdateDistanceMeters(50);
        builder.setDurationMillis(60 * 1000);
        builder.setGranularity(Granularity.GRANULARITY_FINE);
        builder.setWaitForAccurateLocation(false);
        builder.setPriority(Priority.PRIORITY_HIGH_ACCURACY);
        return builder.build();
    }

    @SuppressLint("MissingPermission")
    @Override
    public void startLogging(Trip trip) {
        if (!PermissionHelper.hasPermissions(activity.getApplicationContext(), MapsHelper.OSM_PERMISSIONS))
            throw new UnsupportedOperationException("permissions missing ");

        client.requestLocationUpdates(getLocationRequest(), callBack, Looper.myLooper()).addOnCanceledListener(new OnCanceledListener() {
            @Override
            public void onCanceled() {
                Log.d(TAG, "onCanceled: ");
            }
        }).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                Log.d(TAG, "onComplete: ");
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.e(TAG, "onFailure: ", e);
            }
        }).addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void unused) {
                Log.d(TAG, "onSuccess: ");
            }
        });
    }

    @Override
    public void stopLogging() {
        client.removeLocationUpdates(callBack);
    }
}

排查与修复方案

1. 删除setDurationMillis配置

你的LocationRequest中调用了builder.setDurationMillis(60 * 1000),这个方法会限定位置更新的总时长,60秒后更新会自动停止,这是只能获取一次位置的核心原因。删除该配置,让更新持续运行直到手动调用stopLogging()。

2. 修正Looper参数

调用requestLocationUpdates时传入Looper.myLooper(),如果当前线程没有Looper(比如后台线程调用startLogging),会导致Callback无法接收回调。建议改为传入Looper.getMainLooper(),确保在主线程处理位置更新:

client.requestLocationUpdates(getLocationRequest(), callBack, Looper.getMainLooper())

3. 调整更新间隔参数

当前LocationRequest.Builder(10000)设置的是最快更新间隔10秒,但你预期的是60秒的常规间隔,应明确设置常规更新间隔,同时保留最快间隔避免频繁更新:

private LocationRequest getLocationRequest() {
    // 常规更新间隔60秒,最快10秒,移动50米触发更新
    LocationRequest.Builder builder = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 60000);
    builder.setMinUpdateDistanceMeters(50);
    builder.setMinUpdateIntervalMillis(10000);
    builder.setGranularity(Granularity.GRANULARITY_FINE);
    builder.setWaitForAccurateLocation(false);
    return builder.build();
}

4. 模拟器位置模拟注意事项

  • 开启模拟器开发者选项中的允许模拟位置权限;
  • 模拟位置时确保移动距离超过50米,或等待60秒以上,触发对应的更新条件;
  • 使用Android Studio的Extended Controls > Location功能,输入坐标后点击"Send"触发位置更新。

5. 补充Android 12+后台位置权限

Android 12(API 31)及以上版本,若App在后台需要记录位置,需额外申请ACCESS_BACKGROUND_LOCATION权限,并引导用户完成授权。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:47:51