奥利奥(Oreo):如何从后台捕获位置更新?

时间:2018-09-24 12:46:11

标签: android android-service android-location android-8.0-oreo android-fusedlocation

我将我的应用迁移到oreo(因为Google Play现在需要它),并且在启动手机时出现错误:

  

不允许启动服务意图

我的应用程序正在后台侦听任何位置更新,并定期将这些获取的位置发送到服务器。为此,我做到了:

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 +上却失败了。我该怎么做才能使服务运行?

1 个答案:

答案 0 :(得分:4)

从Android Oreo开始,您不能简单地start a background service while the app is in the background

您可以像这样启动前台服务(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在评论中指出的那样,您可能也会受到new background location limits的影响。

nice article关于奥利奥(Oreo)的背景排泄极限。