首页 > 解决方案 > 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+ 上失败了。我可以做些什么来使我的服务运行?

标签: androidandroid-serviceandroid-locationandroid-8.0-oreoandroid-fusedlocation

解决方案


从 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在评论中指出的那样,您可能还会受到新的后台位置限制的影响。

有一篇关于奥利奥背景执行限制的好文章。


推荐阅读