android - Oreo:如何从后台捕捉位置更新?
问题描述
我将我的应用程序迁移到 oreo (因为它现在是 google play 所要求的),我现在在启动手机时出现错误:
不允许启动服务 Intent
我的应用程序正在后台侦听任何位置更新,并定期将这些抓取的位置发送到服务器。为此,我这样做:
在AndroidManifest.xml
<receiver android:name="com.myapp.StartServiceBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
在 StartServiceBroadcastReceiver 我做:
@Override
public void onReceive(Context context, Intent intent) {
try {
/* start the location service */
Intent startServiceIntent = new Intent(context, LocationService.class);
context.startService(startServiceIntent);
} catch (Throwable e){ Log.e(TAG, "Exception", e); }
}
和 LocationService 基本上做:
public void onCreate() {
mLocationServices.setListener(this);
mLocationServices.startLocationUpdates(true, // startWithLastKnownLocation,
150000, // interval => 2.5 min // Set the desired interval for active location updates, in milliseconds.
// The location client will actively try to obtain location updates for your
// application at this interval, so it has a direct influence on the amount
// of power used by your application. Choose your interval wisely.
30000, // fastestInterval => 30 s // Explicitly set the fastest interval for location updates, in milliseconds.
// This controls the fastest rate at which your application will receive location updates, which might be faster than setInterval(long)
// in some situations (for example, if other applications are triggering location updates).
// This allows your application to passively acquire locations at a rate faster than it actively acquires locations, saving power.
900000, // maxWaitTime => 15 min // Sets the maximum wait time in milliseconds for location updates.
// If you pass a value at least 2x larger than the interval specified with setInterval(long), then location
// delivery may be delayed and multiple locations can be delivered at once. Locations are determined at
// the setInterval(long) rate, but can be delivered in batch after the interval you set in this method.
// This can consume less battery and give more accurate locations, depending on the device's hardware
// capabilities. You should set this value to be as large as possible for your needs if you don't
// need immediate location delivery.
LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY, // priority => Block level accuracy is considered to be about 100 meter accuracy.
// Using a coarse accuracy such as this often consumes less power.
25); // smallestDisplacement => 25 meters // Set the minimum displacement between location updates in meters
}
@Override
public void onLocationChanged(Location location) {
....
}
在 pre-oreo 上一切都运行良好,但现在在 oreo+ 上失败了。我可以做些什么来使我的服务运行?
解决方案
从 Android Oreo 开始,您不能在应用处于后台时简单地启动后台服务。
您可以像这样(Kotlin,但在 Java 中类似)将您的服务作为前台服务启动:
val serviceIntent = Intent(context, LocationService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(serviceIntent)
} else {
context.startService(serviceIntent)
}
在您的服务中,请确保您尽快调用startForeground 。这还将发出通知,以便用户知道您的应用程序在后台处于活动状态。
正如Anis BEN NSIR在评论中指出的那样,您可能还会受到新的后台位置限制的影响。
有一篇关于奥利奥背景执行限制的好文章。
推荐阅读
- google-chrome-extension - background.js 中的 sendResponse() 不会将数据发送到内容脚本
- jquery-select2 - 使用带有 Select2 的初始数据集,并且仅在用户键入字符时发送 Ajax 搜索
- asp.net - 即使在服务器上也没有显示详细的 500 错误消息
- ruby-on-rails - sassc bundler 错误:Gem::Ext::BuildError: ERROR: Failed to build gem native extension
- c# - 无法在同一个 Web 服务中使用我的第二个 Web 方法
- c# - 为什么 FormClosed 事件处理程序会被调用两次?
- python - 有人可以给我看一个好的阶乘代码吗?
- push-notification - ionic3中的后台推送通知
- c# - 为什么我的 int 从 Azure 表存储中读取为 0,而不是存储值?
- python - 在 RobotFramework 中使用 Run Process 关键字的语法