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+ это не получилось. Что я могу сделать, чтобы мой сервис работал?

1 ответ

Начиная с 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, вы, вероятно, также будете подвержены влиянию новых пределов расположения фона.

Есть хорошая статья о пределе возможностей Oreo.

Другие вопросы по тегам