【问题标题】:Setting mock location in FusedLocationProviderApi在 FusedLocationProviderApi 中设置模拟位置
【发布时间】:2015-11-25 19:25:47
【问题描述】:

我正在尝试从FusedLocationProviderApi 获取模拟更新,但我似乎无法让它工作。这是我在 android 仪器测试中的设置方法:

locationProvider = new LocationProvider(InstrumentationRegistry.getTargetContext().getApplicationContext(), settings);

// Connect first, so that we don't receive 'true' location
locationProvider.googleApiClient.blockingConnect();
// Set mock mode, to receive only mock locations
LocationServices.FusedLocationApi.setMockMode(locationProvider.googleApiClient, true);

InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
    @Override
    public void run() {
        // Start receiving locations; this call will connect api client, and if it's already connected (or after it connects) it will register for location updates
        locationProvider.start();
    }
});
// wait until we can request location updates
while (!locationProvider.isReceivingLocationUpdates) {
    Thread.sleep(10);
}

在这一点之后,我希望任何对LocationServices.fusedLocationApi.setMockLocation(apiClient, location) 的调用都会设置我的听众将收到的模拟位置。不幸的是,情况并非如此,听众保持沉默。

我设置模拟位置的万无一失(或者我认为)方法如下所示:

private void setMockLocation(final Location location) throws Exception {
    assertTrue(locationProvider.googleApiClient.isConnected());
    assertTrue(locationProvider.isReceivingLocationUpdates);

    final CountDownLatch countDownLatch = new CountDownLatch(1);
    LocationServices.FusedLocationApi.setMockMode(locationProvider.googleApiClient, true)
            .setResultCallback(new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    assertTrue(status.isSuccess());
                    LocationServices.FusedLocationApi.setMockLocation(locationProvider.googleApiClient, location)
                            .setResultCallback(new ResultCallback<Status>() {
                                @Override
                                public void onResult(Status status) {
                                    assertTrue(status.isSuccess());
                                    countDownLatch.countDown();
                                }
                            });
                }
            });
    assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
}

方法成功返回,但监听器没有收到任何位置。我在这里真的很茫然。最糟糕的部分是有时测试会通过,但非常随机(有时执行多次的相同代码会在后续调用中通过并失败)。为了完整起见,我的调试清单具有以下权限:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />

我已在设置中允许模拟位置。

【问题讨论】:

  • This tutorial 提供了有关如何在 Android 中使用模拟位置数据进行测试的详细信息。此外,locationProvider 已被弃用,您应该改用GoogleApiClient,您可以查看此github page 以获取示例 GoogleApiClient 实现。
  • 我可能还不清楚 - locationProvider 是我自己的班级。我使用GoogleApiClientFusedLocationProviderApi 来获取位置
  • @wasyl 我没试过这个。但是您是否检查过开发人员选项下是否启用了允许模拟位置选项?
  • 虽然这是一个非常古老的问题,但您能找到解决方案吗?我遇到了同样的问题@wasyl
  • @Anuj 据我记得设置了一次模拟位置,然后再次起作用(第一个被忽略),尽管我可能记错了。我还打开了一个问题,该问题已经被方便地忽略了一段时间 - 请随时联系维护者github.com/googlesamples/android-play-location/issues/21

标签: android testing google-play-services fusedlocationproviderapi android-fusedlocation


【解决方案1】:

这是我们更新的 kotlin 版本。请注意,您需要在开发选项中选择应用程序作为模拟位置提供程序,并有权在调试清单文件中进行设置。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"
    tools:ignore="ProtectedPermissions" />
</manifest>

一个活动会在 onCreate 中有一个带有初始化器的 val

  private lateinit var fusedLocationClient: FusedLocationProviderClient

在 oncreate() 中

  fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)


  fusedLocationClient.setMockMode(BuildConfig.DEBUG)

  fusedLocationClient.lastLocation
        .addOnSuccessListener { location : android.location.Location? ->
            // Got last known location. In some rare situations this can be null.
            Toast.makeText(this, location.toString(), Toast.LENGTH_SHORT).show()

        }
        .addOnFailureListener {  Toast.makeText(this, "failed", Toast.LENGTH_SHORT).show() }

最后是模拟位置的方法

 private fun setMockLocation(location: android.location.Location) {
    fusedLocationClient.setMockLocation(location)
        .addOnSuccessListener { Log.d(TAG, "location mocked") }
        .addOnFailureListener { Log.d(TAG, "mock failed") }
}

【讨论】:

    猜你喜欢
    • 2010-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-14
    • 2013-11-12
    相关资源
    最近更新 更多