Android Geofencing BroadcastReceiver not Triggered
Asked Answered
B

2

11

I am currently making a Geofencing app for android, and I followed their tutorial but I cant seem to get the BroadcastReceiver to trigger correctly.

The onAddGeofencesResult is called, but the BroadcastReceiver is not ever called. And idea why? I have it so that it should be sending a broadcast if a person is in the geofence for more than 5 ms, as well as exits or enters the geofence. I made geofences based on coordinates right near my office, but don't get any result when walking through them (or standing in them).

ReceiveTransitionsBroadcastReceiver.java:

import com.parse.ParseObject;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;


/**
 * This class receives geofence transition events from Location Services, in the
 * form of an Intent containing the transition type and geofence id(s) that triggered
 * the event.
 */
public class ReceiveTransitionsBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context arg0, Intent arg1) {

        System.out.println("Hello");

        ParseObject gameScore = new ParseObject("EventTest");
        gameScore.put("Student", "Josh");
        gameScore.put("Entered", true);
        gameScore.put("Class", "AndroidTest");
        gameScore.saveInBackground();

    }
}

Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.spotter"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="19" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.spotter.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name="com.example.spotter.ReceiveTransitionsBroadcastReceiver" android:exported="false"/>
        <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
    </application>
</manifest>

MainActivity where I set up the geofences:

@Override
public void onConnected(Bundle bundle) {
    System.out.println("Connected to LocationServices");
    Geofence.Builder builder = new Geofence.Builder();
    builder.setCircularRegion(41.909858, -87.649038, 100.0f)
        .setExpirationDuration(Geofence.NEVER_EXPIRE)
        .setRequestId("1")
        .setLoiteringDelay(5)
        .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT | Geofence.GEOFENCE_TRANSITION_DWELL);
    Geofence fence1 = builder.build();
    builder.setCircularRegion(41.910359, -87.651444, 100.0f)
        .setExpirationDuration(Geofence.NEVER_EXPIRE)
        .setRequestId("2")
        .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT);
    Geofence fence2 = builder.build();



    Intent intent = new Intent(this, ReceiveTransitionsBroadcastReceiver.class);
    PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    locationClient.addGeofences(Arrays.asList(fence1,fence2), pi, this);
}

Thanks for checking this out, I appreciate the help.

EDIT: The radius of the geofence is 1000 meters. I drive about a mile away and back but nothing, so I assume it's not the accuracy that's an issue. Note that the device is not activated, so I am only using wifi, but there are dozens of wifi spots around each geofence, which I connect to.

Bullwhip answered 30/5, 2014 at 15:49 Comment(1)
Did you ever get this working correctly?Bowlder
L
11

An important note on the Google Play GeoFencing API. I've found that the GeoFencing never intelligently retrieves locations from the GPS hardware. The GeoFence API will observe the most accurate location available from the OS or if no recent location reading is available, it will cause a location to be calculated from Wifi / Cellular. (which sucks because cellular is v inaccurate and wifi is often unavailable)

So to get at responsive or accurate results out of the Geofencing API you have to set up your Geofences and then poll the GPS hardware on some interval, not even doing anything with the result received, so that under the surface worthwhile data is provided to the OS and Geofence API.

This is probably at the core of why you're not seeing any results. The geofence events won't trigger until the OS is 100% confident of the action. So if a location reading has an accuracy of 500 meters (not improbable when using cellular geolocation) and your fence has a radius of 50m, you'd never be able to produce an entrance event, and you'd have to be at least ~550m from your fence point to produce an exit event.

TLDR; Poll the GPS hardware on an interval without doing anything with the result and you'll start getting more accurate geofences.

Leathern answered 31/5, 2014 at 17:17 Comment(4)
What is the best way to poll the GPS hardware without affecting battery life severly?Gretchen
"poll the GPS hardware on some interval, not even doing anything with the result" ... And then your app burns down the battery and user wonders why their phone is hot when they aren't using it... they look in the battery section and see your app is the worst offender and listed as highest battery usage... and then they give you a 1-star rating and uninstall your app. So yes, problem solved... I guess.Wheatear
my application is deployed in an environment where accuracy is paramount and power consumption is insignificant because the device is plugged in. so yeah my problem was solved. it's not my fault the Android GPS accuracy is unbearable unless you do this. you have to develop for your own constraints. increase your interval and implement some back-off logic into the interval timing when you're still a great distance from the geofence if you're really dedicated to accuracy and battery life.Leathern
Could you provide a code example please?Catherincatherina
V
0

stealthwang is right, you cannot rely on the geofencing API because the reported location is sometimes wildly off. You will want to perform location filtering to ensure sane reporting.

Also, be aware that the timeout value is only an advisory. Many platforms simply ignore this value so if your design requires reliable periodic updates then you will need to implement this yourself.

Good luck w/your project.

Voracious answered 5/6, 2014 at 2:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.