android / location-samples

Multiple samples showing the best practices in location APIs on Android.
Apache License 2.0
2.71k stars 2.77k forks source link

Geofencing #147

Open ashbash0697 opened 6 years ago

ashbash0697 commented 6 years ago

Hi, I am using the example code of geofencing, it does not seem to work the broadcast receiver is not being called, I've tried many solutions nothing seems to work

RonaldSalazarH commented 6 years ago

Hi, I have the same problem and change the Lines: 233 and 236 in MainActivity.java:

Intent intent = new Intent(getApplicationContext(), GeofenceBroadcastRutaReceiver.class); // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling // addGeofences() and removeGeofences(). mGeofencePendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

========== Context mContext; @Override protected void onCreate(Bundle savedInstanceState) { mContext = this; }

pramodit commented 6 years ago

Please tell me the best solution for Geofencing. I use a ForeGroundService with a notification on Top instead of the IntentService as it wasnt working. and have a PendingIntent to receive the entry/exit events . But still My geofencing solution doesnt work at all.

DevEddy commented 6 years ago

Same thing here, geofencing doesn't trigger when the app is closed. Geofencing only works with foreground service.

Would be great it someone at google could make a statement.

@pramodit do you use the BroadcastReceiver like in the sample?

pramodit commented 6 years ago

Now it works fine for me . I used a JobScheduler and scheduling the job every now and then as this background thread gets killed in Android Oreo due to Background Execution Limits . @DevEddy Please try with the JobService . It worked like a charm to me

DevEddy commented 6 years ago

Hi @pramodit I am glad that it works for you now.

Could you provide some snippets how you're doing this? I would be very thankful.

pramodit commented 5 years ago

Sure @DevEddy This is how i am doing it . I use this JobService and reschedule it every 1 secs in Android O to make sure the OS dont kill my service. /**

@TargetApi(21) public class OreoJobService extends JobService {

private JobParameters mParams;

//Assuming it takes maximum 5 seconds for
private String TAG = "OreoJobService";

public boolean onStartJob(JobParameters params) {

    this.mParams = params;

    String command = params.getExtras().getString("command");

    if (command != null && command.equals("stop")) {

        this.endJob();
        return false;
    } else {

        if (MyApplication.getInstance().geoFencePendingIntent == null) {

            if (params.getExtras().containsKey("fromJobScheduler")) {

                String geoFences = MyApplication.getInstance().fetchGeoFences();

                if (geoFences != null) {

                    List<Fence> fencesList = new Gson().fromJson(geoFences, new TypeToken<List<Fence>>() {
                    }.getType());
                    MyApplication.getInstance().createGeoFences(fencesList);

                }

            }
        } else {

            Log.e(TAG, "onStartJob: scheduling job ");
            this.scheduleJob(10000);
        }

        return true;
    }
}

void endJob() {
    this.jobFinished(this.mParams, false);
}

void scheduleJob(long interval) {

    ComponentName serviceName = new ComponentName(this.getPackageName(), OreoJobService.class.getName());

    PersistableBundle extras = new PersistableBundle();
    extras.putString("command", "start");
    extras.putInt("fromJobScheduler", 1);
    JobInfo jobInfo = (new JobInfo.Builder(VariableConstants_Fortees.GEOFENCE_JOB_ID, serviceName))
            .setExtras(extras).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
            .setMinimumLatency(interval)
            .setOverrideDeadline(interval)
            .build();

    JobScheduler jobScheduler = (JobScheduler) this.getSystemService(Context.JOB_SCHEDULER_SERVICE);
    assert jobScheduler != null;
    jobScheduler.schedule(jobInfo);
    this.endJob();
}

public boolean onStopJob(JobParameters params) {

    return false;
}

}

###################### And here's my logic for scheduling ##########################

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

        ComponentName serviceName = new ComponentName(this, OreoJobService.class.getName());
        PersistableBundle extras = new PersistableBundle();
        extras.putString("command", "start");

        JobInfo jobInfo = (new JobInfo.Builder(VariableConstants_Fortees.GEOFENCE_JOB_ID, serviceName))
                .setExtras(extras).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                .setMinimumLatency(1L)
                .setOverrideDeadline(1L)
                .build();

        JobScheduler jobScheduler = (JobScheduler) this.getSystemService(Context.JOB_SCHEDULER_SERVICE);

        try {
            jobScheduler.schedule(jobInfo);
        } catch (IllegalArgumentException errorMessage) {
            errorMessage.printStackTrace();
        }

    }
rameshsambu-dev commented 5 years ago

Can you share the working sample if its possible?I am trying for this solution last one week

kraghu commented 5 years ago

@pramodit Does your solution still work ? I have tried everything at this point

pramodit commented 5 years ago

Yes it still works like a charm for me @kraghu

pramodit commented 5 years ago

If you want it to make it optimised for every other locations , you could use a WorkManager which is compatabile for all regions such as for china, where there are no GooglePlayServices , it uses FirebaseDispatcher, AlarmManager for some devices and JobScheduler wherever necessary @kraghu :)

Ulsacom commented 5 years ago

JobService for Geofences project

Ulsacom commented 5 years ago

please send me geofence project

kanxoramesh commented 5 years ago

Sure @DevEddy This is how i am doing it . I use this JobService and reschedule it every 1 secs in Android O to make sure the OS dont kill my service. /**

  • JobService for Geofences above Android Oreo
  • @author Pramod
  • @SInCE 16-Sept-2018. */

@TargetApi(21) public class OreoJobService extends JobService {

private JobParameters mParams;

//Assuming it takes maximum 5 seconds for
private String TAG = "OreoJobService";

public boolean onStartJob(JobParameters params) {

    this.mParams = params;

    String command = params.getExtras().getString("command");

    if (command != null && command.equals("stop")) {

        this.endJob();
        return false;
    } else {

        if (MyApplication.getInstance().geoFencePendingIntent == null) {

            if (params.getExtras().containsKey("fromJobScheduler")) {

                String geoFences = MyApplication.getInstance().fetchGeoFences();

                if (geoFences != null) {

                    List<Fence> fencesList = new Gson().fromJson(geoFences, new TypeToken<List<Fence>>() {
                    }.getType());
                    MyApplication.getInstance().createGeoFences(fencesList);

                }

            }
        } else {

            Log.e(TAG, "onStartJob: scheduling job ");
            this.scheduleJob(10000);
        }

        return true;
    }
}

void endJob() {
    this.jobFinished(this.mParams, false);
}

void scheduleJob(long interval) {

    ComponentName serviceName = new ComponentName(this.getPackageName(), OreoJobService.class.getName());

    PersistableBundle extras = new PersistableBundle();
    extras.putString("command", "start");
    extras.putInt("fromJobScheduler", 1);
    JobInfo jobInfo = (new JobInfo.Builder(VariableConstants_Fortees.GEOFENCE_JOB_ID, serviceName))
            .setExtras(extras).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
            .setMinimumLatency(interval)
            .setOverrideDeadline(interval)
            .build();

    JobScheduler jobScheduler = (JobScheduler) this.getSystemService(Context.JOB_SCHEDULER_SERVICE);
    assert jobScheduler != null;
    jobScheduler.schedule(jobInfo);
    this.endJob();
}

public boolean onStopJob(JobParameters params) {

    return false;
}

}

###################### And here's my logic for scheduling ##########################

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

        ComponentName serviceName = new ComponentName(this, OreoJobService.class.getName());
        PersistableBundle extras = new PersistableBundle();
        extras.putString("command", "start");

        JobInfo jobInfo = (new JobInfo.Builder(VariableConstants_Fortees.GEOFENCE_JOB_ID, serviceName))
                .setExtras(extras).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                .setMinimumLatency(1L)
                .setOverrideDeadline(1L)
                .build();

        JobScheduler jobScheduler = (JobScheduler) this.getSystemService(Context.JOB_SCHEDULER_SERVICE);

        try {
            jobScheduler.schedule(jobInfo);
        } catch (IllegalArgumentException errorMessage) {
            errorMessage.printStackTrace();
        }

    }

@pramodit why you create geofences every time in service MyApplication.getInstance().createGeoFences(fencesList); Because Android Oreo and above doesn't provide frequent location update, Don't we need to call location update service in the background? I am confused :(

pramodit commented 5 years ago

@RameshPokharel Hey am not creating the fences its just named that way. i am just registering them once for all . i get the fences from an API call and then i use them. if it's already created then i don't recreate the fences