20

I am using following code to get location on/off event.

<receiver
    android:name=".receivers.GpsReceiver"
    android:enabled="true">
    <intent-filter>
        <action android:name="android.location.PROVIDERS_CHANGED" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</receiver>

I am developing geofence based app. Based on Re-register geofences only when required we have to re register the geofences after the app has received a GEOFENCE_NOT_AVAILABLE alert. This typically happens after NLP (Android's Network Location Provider) is disabled.

By using this broadcast receiver I re-registered the geofences when Android's Network Location Provider is enabled.

But from API level 26 this broadcast receiver will never work. See Background Execution Limits.

So how can I achieve the same task in API 26 and higher?

Note : I need to re-register the geofences even when app is in the background.

halfer
  • 19,824
  • 17
  • 99
  • 186
Gunaseelan
  • 14,415
  • 11
  • 80
  • 128

3 Answers3

6

You could switch to registering you receivers dynamically by Context.registerReceiver(), but IMHO there is no reliable way to get them registered "forever", because the system is going to terminate your process anyway on certain conditions.

Sure, you could re-register them by using e.g. white listed broadcast receivers, AlarmManager, JobScheduler etc. But this is not the best way in terms of battery and other resource consumption. Actually this is the reason, why Google disabled the implicit broadcasts.

The point is: By disabling implicit broadcasts in Oreo Google forces you to use some kind of recurring job to to do things like this. As the result, you don't need to listen for the NLP state updates, you just set your geofences with GeofencingClient.addGeofences (if NLP is enabled) in your recurring job over and over again.

artkoenig
  • 7,117
  • 2
  • 40
  • 61
  • I know this is not the best solution, But its close to the solution. So I will add bounty to this solution. Thanks. – Gunaseelan Feb 21 '18 at 08:05
3

as mentioned in the article you've linked, there's no way on Android API 26 to listen to implicit broadcasts like

<action android:name="android.location.PROVIDERS_CHANGED" />

if the app is killed or isn't currently running in background. The only thing what you can do is to register the broadcast receiver on runtime, as stated in the migration guide.

What I did is calling registerReceiver in the application class in onCreate and unregister it in onTerminate.

class MyApplication : Application() {
  private val gpsReceiver = MyBroadcastReceiver()

  override fun onCreate() {
    super.onCreate()
    registerReceiver(gpsReceiver, IntentFilter("android.location.PROVIDERS_CHANGED"))
  }

  override fun onTerminate() {
    super.onTerminate()
    unregisterReceiver(gpsReceiver)
  }
}

Hopefully, this could help you!

mlo
  • 31
  • 2
  • 1
    But this will work only in foreground. I need to check even app is in background also. – Gunaseelan Feb 13 '18 at 10:26
  • This works also if the app is in background. Only if it's closed (swipping out of recent apps list) you cannot listen to `PROVIDERS_CHANGED` anymore – mlo Feb 14 '18 at 10:10
  • 1
    Only if it's closed (swipping out of recent apps list), the app considered as background my dear friend. Otherwise the app still in foreground. – Gunaseelan Feb 14 '18 at 10:12
  • 1
    @Gunaseelan you will find the right definition of the foreground process [here](https://developer.android.com/guide/components/activities/process-lifecycle.html) – artkoenig Feb 15 '18 at 11:11
  • onTerminate() This method is for use in emulated process environments. – Yvgen Mar 14 '18 at 14:53
0

maybe you should try use background service and wakelock for long-running in the background when app closed/killed or screen off. it's works for me :)

sirinan jirinsa
  • 161
  • 1
  • 1
  • 10