Monitoring Location Settings in a Library
Asked Answered
P

2

9

I'm working on a library that can be used to monitor geofences on Android devices. I've noticed that the geofences I register with Google Play Location Services GeofencingApi class are lost after I turn Location Services off and back on in the device settings.

I have seen folks suggesting that I need to register for the android.location.PROVIDERS_CHANGED broadcast receiver in my AndroidManifest.xml file. I've done that -- but this broadcast receiver only gets called when I add and remove test providers in my test application. I don't receive it at all when toggling Location Services in the device settings.

Am I doing something wrong? Does anyone know how to reliably determine when the user toggles Location Services in the device settings? I'd like to be able to see these events in the background -- even if my app is not running.

I figure I could set up an repeating task that runs in the background and periodically checks to see if Location Services has been toggled, but it sounds gross and inefficient.

If it helps, I'm testing on an Moto G running Android 4.4.2. Everything I have done with geofences has worked fine until now.

EDIT: After doing more research I have found that the behaviour of the PROVIDERS_CHANGED broadcast is highly variable depending on phone version and model. My Nexus 5 running Android 5.1 seems to work fine actually - I am able to get the PROVIDERS_CHANGED broadcast very regularly. I also have a Moto G and Moto X phone running 4.4.x and they never produced the PROVIDERS_CHANGED broadcast for me. A Samsung Galaxy S3 on Android 4.2 would produce the broadcast for me but stop doing it after I used my Map Activity with test location providers.

Anyways, I have decide to stop pursuing this problem for now. I think Android is just being buggy.

Peat answered 26/5, 2015 at 20:3 Comment(3)
this may be helpful #10312334 Also did you try maybe saving the geofence data locally or somewhere else to prevent it from being deleted?Dosage
I do already save the geofences locally so I'm not going to lose them forever (unless the user clears the cache). That's not my problem. My problem is that I don't get the event the notifies me that the location provider settings have changed. (i.e.: I'm not getting told that they have been deleted by the OS and I'm not getting told when it's safe for me to reload the).Peat
#25157477 I register for the providers_changed in code You actually need some code to get a decent answer. IDK with 4.4.2 maybe it doesn't work. I haven't fired up my android dev environment in several months.Jessen
M
8

It's hard to tell without seeing your code if you are doing anything wrong, but I just got a simple example working and tested by using the code from here as a guide, and adapting it to have the BroadcastReceiver in a library.

One thing to note: The app using the library will need to have the receiver in its AndroidManifest.xml. See here and here, both contain information from @CommonsWare.

Adding quote here just in case the link goes bad:

Is there any way for a library project to independently register for a receiver in it's own manifest file?

Not at the present time.

So, any app that uses your library will need to have the receiveradded in its AndroidManifest.xml.

Note that this was tested on Android 4.4.4 on a Samsung S4.

I got this working using a BroadcastReceiver in a library project compiled to a aar.

Using a receiver element set up in the AndroidManifest.xml of the main app that links to the BroadcastReceiver in the library, I was able to receive the event when any change is made to the Location settings:

  • Location toggle on
  • Location toggle off
  • Change Location Mode to High Accuracy
  • Change Location Mode to Power Saving
  • Change Location Mode to GPS only

Every time a change is made in the location settings, the BroadcastReceiver in the library is triggered, even if the app is not running.

I used a simple test where the BroadcastReceiver in the library shows a Toast message every time the location settings are changed.

Here is LocationProviderChangedReceiver.java in the library project:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.util.Log;
import android.widget.Toast;

public class LocationProviderChangedReceiver extends BroadcastReceiver {
    private final static String TAG = "LocationProviderChanged";

    boolean isGpsEnabled;
    boolean isNetworkEnabled;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().matches("android.location.PROVIDERS_CHANGED"))
        {
            Log.i(TAG, "Location Providers changed");

            LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            Toast.makeText(context, "GPS Enabled: " + isGpsEnabled + " Network Location Enabled: " + isNetworkEnabled, Toast.LENGTH_LONG).show();
        }
    }

}

Then, in the main app, I put the compiled myLibrary.aar in the libs folder, and set up the build.gradle to compile the aar:

 repositories{
        flatDir{
            dirs 'libs'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile "com.android.support:appcompat-v7:22.1.1"
    compile "com.google.android.gms:play-services:7.3.0"

    compile 'com.mylibrary.daniel:mylibrary:1.0@aar'

}

Set up the receiver in the AndroidManifest.xml of the main app:

    <receiver
        android:name="com.mylibrary.daniel.mylibrary.LocationProviderChangedReceiver"
        android:exported="false" >
        <intent-filter>
            <action android:name="android.location.PROVIDERS_CHANGED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

Then, installed the app, and modified location settings in a few different ways. The BroadcastReceiver in the library was triggered every time:

enter image description here

enter image description here

enter image description here

enter image description here

Map answered 1/6, 2015 at 18:44 Comment(2)
Thank you for your answer. My code was basically the same as yours. I tried putting my BroadcastReceiver in both my main application and my library and the behaviour is the same. I can regularly receive the broadcast on my Nexus 5 regardless if the BroadcastReceiver is in the library or the app. I think that, as long as I declare my BroadcastReceiver in my library's AndroidManifest.xml file and I used Gradle to do my builds it doesn't matter where the BroadcastReceiver is. Other phones are much less reliable. I think Android is just buggy and I've stopped working on this problem now.Peat
Yes, it works when app is around, but when the is killed/closed from task manager it doesn't work for me. I am using Android version 4.4.4 Kitkat on MI3 device.Tutankhamen
C
0

Actually, you can use location.MODE_CHANGED and then register your receiver to receive the broadcast from it

<receiver android:name=".Receivers.LocationModeReceiver">
    <intent-filter>
        <action android:name="android.location.MODE_CHANGED" />
    </intent-filter>
</receiver>
Contagion answered 6/1, 2016 at 15:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.