【问题标题】:How can location updates from FusedLocationProviderClient be processed with Work Manager?工作管理器如何处理来自 FusedLocationProviderClient 的位置更新?
【发布时间】:2019-05-03 13:08:51
【问题描述】:

首先,我是一个完全的 Android 菜鸟。一段时间以来一直在寻找解决方案,但到目前为止找不到任何有用的提示。这通常可能是由问题本身的性质引起的,非常小众。

下面的工作代码基于https://codelabs.developers.google.com/codelabs/realtime-asset-tracking 的代码实验室。

不过我想知道,由于现在有几个资源中提到它是首选方式,你如何基于 Android 的工作管理器而不是具有持续通知的服务来做类似的事情?

public class TrackerService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
        requestLocationUpdates();
    }

    private void requestLocationUpdates() {
        LocationRequest request = new LocationRequest();
        request.setInterval(5 * 60 * 1000);
        request.setFastestInterval(30 * 1000);
        request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(this);
        int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
        if (permission == PackageManager.PERMISSION_GRANTED) {
            client.requestLocationUpdates(request, new LocationCallback() {
                @Override
                public void onLocationResult(LocationResult locationResult) {
                    Location location = locationResult.getLastLocation();
                    if (location != null) {
                        Log.d(TAG, "location update " + location);
                    }
                }
            }, null);
        }
    }
}

根据我在网络项目中的经验,上面的代码基于 FusedLocationProviderClient 建立了一个“监听器”。一旦有新的位置更新,它就会调用 onLocationResult 并提供相应的位置结果。

到目前为止,我对工作管理器的发现是,您可以一次或定期将具有工作管理器的 Worker 设置为 doWork()。实际上就像一个 cron 作业...

我不明白,如果后台没有正在运行的服务,那么 Worker 和位置更新请求会在哪里发起?他们将如何合作?

【问题讨论】:

  • 让我们明确一点,您将在从 Worker 类扩展的类中发起位置更新请求,并且您将运行自己的 doWork 函数。看这个例子——codelabs.developers.google.com/codelabs/android-workmanager/#3
  • Thx @VadimEksler - 该代码会进入我的默认活动吗?如果我定期运行一个工作器,它不会注册多个回调来更新位置吗?
  • 1) 扩展 Worker 的独立类 MyLocationWorker。你像PeriodicWorkRequest myWorkRequest = new PeriodicWorkRequest.Builder(MyLocationWorker.class, 30, TimeUnit.MINUTES) .build(); 一样开始它 2) 当你得到你的位置结果时,你需要删除回调。

标签: android android-service android-fusedlocation android-workmanager google-location-services


【解决方案1】:

我在这里创建了演示:LocationTracker-WorkManager

MyWorker.java

public class MyWorker extends Worker {

    private static final String TAG = "MyWorker";

    /**
     * The desired interval for location updates. Inexact. Updates may be more or less frequent.
     */
    private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;

    /**
     * The fastest rate for active location updates. Updates will never be more frequent
     * than this value.
     */
    private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
            UPDATE_INTERVAL_IN_MILLISECONDS / 2;
    /**
     * The current location.
     */
    private Location mLocation;

    /**
     * Provides access to the Fused Location Provider API.
     */
    private FusedLocationProviderClient mFusedLocationClient;

    private Context mContext;
    /**
     * Callback for changes in location.
     */
    private LocationCallback mLocationCallback;

    public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
        mContext = context;
    }

    @NonNull
    @Override
    public Result doWork() {
        Log.d(TAG, "doWork: Done");

                mFusedLocationClient = LocationServices.getFusedLocationProviderClient(mContext);
                mLocationCallback = new LocationCallback() {
                    @Override
                    public void onLocationResult(LocationResult locationResult) {
                        super.onLocationResult(locationResult);
                    }
                };

                LocationRequest mLocationRequest = new LocationRequest();
                mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
                mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
                mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

                try {
                    mFusedLocationClient
                            .getLastLocation()
                            .addOnCompleteListener(new OnCompleteListener<Location>() {
                                @Override
                                public void onComplete(@NonNull Task<Location> task) {
                                    if (task.isSuccessful() && task.getResult() != null) {
                                        mLocation = task.getResult();
                                        Log.d(TAG, "Location : " + mLocation);
                                        mFusedLocationClient.removeLocationUpdates(mLocationCallback);
                                    } else {
                                        Log.w(TAG, "Failed to get location.");
                                    }
                                }
                            });
                } catch (SecurityException unlikely) {
                    Log.e(TAG, "Lost location permission." + unlikely);
                }

                try {
                    mFusedLocationClient.requestLocationUpdates(mLocationRequest, null);
                } catch (SecurityException unlikely) {
                    //Utils.setRequestingLocationUpdates(this, false);
                    Log.e(TAG, "Lost location permission. Could not request updates. " + unlikely);
                }

        } catch (ParseException ignored) {

        }

        return Result.success();
    }
}

如何启动工人:

PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(MyWorker.class, 15, TimeUnit.MINUTES)
                            .addTag(TAG)
                            .build();
WorkManager.getInstance().enqueueUniquePeriodicWork("Location", ExistingPeriodicWorkPolicy.REPLACE, periodicWork);

希望对您有所帮助。如果您有任何问题,请告诉我。谢谢。

【讨论】:

  • 非常有趣。我看到它甚至在重新启动后也能正常工作。所以这似乎是要走的路。将不得不进一步发挥我的想法。感谢提供的解决方案。
  • 这回答了我的问题。谢谢。
  • 这个答案需要更多的支持,它解决了很多人的具体问题,包括我的。
  • @PratikButaniAndroidDev 目前正在研究一种方法来执行此操作,但为了提示新的位置更新,使用来自 workmanager 的 ListenableWorker 和 concurrent-futures
  • 您是否通过在doWork() 中打印一些日志进行检查?它将在后台调用。最短间隔为 15 分钟。
猜你喜欢
  • 1970-01-01
  • 2021-05-13
  • 2013-07-30
  • 2017-05-30
  • 1970-01-01
  • 2014-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多