我正在使用信标库来扫描具有前台服务和持久通知的信标。我已经在Android 9.0和7.0上测试了这个,并且应用程序按预期工作,并且每隔30秒将扫描的信标发送到服务器。现在,我正在尝试将位置扫描添加到应用程序,以便它每30秒检索一次位置更新。我正在使用Google Play API,并设置间隔为30秒的位置请求。然后,我在我的应用程序类中创建了一个FusedLocationProvider客户端,所以我给了它我的应用程序(不是活动的)上下文。然后,我向客户提出了我的请求和以下回调:
locationCallback = new LocationCallback()
{
@Override
public void onLocationResult(LocationResult locationResult)
{
if ( locationResult != null )
{
Log.d(TAG, "location acquired: " + locationResult.getLastLocation());
beaconContainer.setLocation(locationResult.getLastLocation());
}
}
};
beaconContainer对象包含信标列表和最新位置(以及使用LocalTime.now()获取最新位置的时间戳),并每隔30秒将这些信息发送到服务器。首先,应用程序似乎工作,位置时间戳在发送服务器请求的30秒内。但是,经过一段时间后(屏幕已关闭一段时间),似乎没有调用回调中的onLocationResult方法,并且没有更新位置。例如,服务器请求是在12:34进行的,但位置在10:21更新。请注意,信标扫描仍按预期正确执行。
我想知道这是因为我测试过的手机是静止的,还是因为我没有使用服务进行位置更新。对我来说,它似乎是前者,因为我的应用程序有一个前台服务(ble扫描程序)和持久通知,所以根据文档,它是在前台,它不应受到背景限制。如果是后者,我如何将信标库的前台服务与我的位置扫描融合,以便它们都按预期运行。
谢谢。
编辑:
FusedLocationProviderClient
的文档表明,在Android 8+上,如果应用程序不在前台,您只能获得“每小时几次”的更新。见here。这可能是因为Google Play服务中的实施使用Android 8+上的JobScheduler来克服后台服务限制,并且作业仅限于在后台运行每15分钟+/- 5分钟。由于Google Play Services API是封闭源代码和专有API,因此很难详细说明其内部实现,但它不太可能考虑到您的应用程序具有前台服务。 (相比之下,Android Beacon Library明确设计为在使用Foreground Service配置时表现不同,因此您可以获得更频繁的更新。)
目前还不清楚FusedLocationProviderClient
在Android 7的后台运行方式有何不同。它可能根本无法有所不同,并且如果您的应用程序针对SDK 26或更高版本,可能会在后台中遵循上述模式。您必须进行测试以确保 - 有效地逆向设计Google Play服务。即使您确定了这一点,行为也可能会在下一个Google Play服务版本中发生变化,除非您再次对其进行反向工程,否则您将永远不会知道它。这是使用闭源SDK的危险。
另一种方法是使用Android提供的开源位置API。
LocationManager locationManager = (LocationManager)
this.getSystemService(Context.LOCATION_SERVICE);
try {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 400l, (float) 1000.0, this); //You can also use LocationManager.GPS_PROVIDER and LocationManager.PASSIVE_PROVIDER
}
catch (SecurityException e) {
Log.d(TAG, "Can't get location -- permission denied");
}
当然,您需要调整准确度和更新间隔以满足您的需求并节省电池电量。当您的手机进入Doze模式时,您肯定会在回调中找到辍学者。但是,您应该能够在问题中描述的Application类中使用上述内容,而不会在Google Play服务中添加令人烦恼的不透明行为。