1

I am using Gimbal SDK for geofence functionality in my android application. The sample code provided by them make me surprise. The sample code is as below package com.gimbal.hello_gimbal_android;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.gimbal.android.CommunicationManager;
import com.gimbal.android.Gimbal;
import com.gimbal.android.PlaceEventListener;
import com.gimbal.android.PlaceManager;
import com.gimbal.android.Visit;


public class MainActivity extends ActionBarActivity {

    private PlaceManager placeManager;
    private PlaceEventListener placeEventListener;
    private ArrayAdapter<String> listAdapter;
    private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1);
        listView = (ListView) findViewById(R.id.list);
        listView.setAdapter(listAdapter);

        listAdapter.add("Setting Gimbal API Key");
        listAdapter.notifyDataSetChanged();
        Gimbal.setApiKey(this.getApplication(), "YOUR_API_KEY_HERE");

        placeEventListener = new PlaceEventListener() {
            @Override
            public void onVisitStart(Visit visit) {
                listAdapter.add(String.format("Start Visit for %s", visit.getPlace().getName()));
                listAdapter.notifyDataSetChanged();
            }

            @Override
            public void onVisitEnd(Visit visit) {
                listAdapter.add(String.format("End Visit for %s", visit.getPlace().getName()));
                listAdapter.notifyDataSetChanged();
            }
        };

        placeManager = PlaceManager.getInstance();
        placeManager.addListener(placeEventListener);
        placeManager.startMonitoring();

        CommunicationManager.getInstance().startReceivingCommunications();
    }

}

Their sample App github link.

Now their place events listener implementation make me surprise. I am expecting a pending intent for service or some kind of broadcasting of intent for listening these place events, as most of such libraries used to notify application. Which is fine for obvious. Because such events should be triggered even if app is in killed state. But here PlaceEventListener is a just an abstract class and we are making an instance of it using new Operator and providing the incomplete functionality of abstract methods.

So, when my activity will destroy, their SDK does not suppose to able give callback in onVisitStart() and PlaceEventListener () method, as placeEventListener instance should be destroyed or null.

My concern is

  1. Gimabl SDK prevent destroying the main activity class instance from Garbage collector just for keeping the placeEventListner
    instance reference? If so, I think this is a bad design as If we can use new placeEventListner from so many activities and all of these will prevent GC.
  2. Also Running a background service just to listen to these event does not seems fine to me. Their SDK should make some component of my android application take birth (example like firing some service or invoking a broadcast receiver by broadcasting a place event).

*Edit: One possible way is implementing the listener interface in Application class of Android application, but I am trying to avoid it due to some other reasons. So, where I suppose to implement it?

Mahendra Chhimwal
  • 1,810
  • 5
  • 21
  • 33
  • 1
    Yeah, that's just a bad API. Consider using the [Google Play services Geofencing API](http://developer.android.com/training/location/geofencing.html), which does this and works well in the background. – ianhanniballake Apr 13 '16 at 09:17
  • Thanks @ianhanniballake , I know this is bad design , it might be possible that they are using Google play services geofence API inside their sdk for the core logic of geofencing, but their callback mechanism to client classes is bad from android prospective. This even I can sense with not much experience in programming and Android framework. But how they are able to provide callback even in killed state. – Mahendra Chhimwal Apr 13 '16 at 09:24

1 Answers1

1

Why don't you put your listener directly into a Service and notify your Activity when it's visible about incoming events?

and_dev
  • 3,723
  • 1
  • 20
  • 28
  • Yup from my side, I can do few more things to optimize system resources , But I am just curious about How one can design that bad api for production sdk of product, may be I am wrong. That's possible. – Mahendra Chhimwal Apr 13 '16 at 09:34
  • Why is it a bad API? this is just an example how to add the listener - if its working within a Service you are fine.. – and_dev Apr 13 '16 at 12:49
  • 1
    Its bad because geofence events should trigger in from background even if android application is in killed state. For that it must invoke some component of application like service from pending intent or broadcasting some local app event. I should not prevent my activities from GC just because of one Listener which I am never know when it will be triggered. According to their API , I can use it in As many Activities as I can, So all of them will be prevented by Android OS if possible. Totally misuse of resources. – Mahendra Chhimwal Apr 18 '16 at 05:03
  • 1
    One more important thing, application will never get the PlaceEvent when in killed state, I think which is one of the main use of Geofencing. And also client app should not run a service contineousely in background just to wait for PlaceEvent. Event should start service or something like that. What you say? – Mahendra Chhimwal Apr 18 '16 at 05:04
  • Use a service and return START_STICKY when initializing it and your service is running as long as you want it to. So you don't need an Activity to handle it. – and_dev Apr 18 '16 at 06:19
  • That's what I do not want. Running a service just to get events is bad way IMHO. It should be like the event should start my service whenever it occurs. – Mahendra Chhimwal Apr 18 '16 at 07:38
  • TBH I don't get your actual question on that topic: the purpose of a Service is to handle long running operations (like you want to do?!), Activities can be destroyed at every time when there is memory pressure on the system. – and_dev Apr 18 '16 at 08:53
  • @MahendraChhimwal I'm experiencing the same problem with Gimbal. I am starting the PlaceManager monitoring in a background service. It works while the app is open or in the background but once the app is killed via the task manager I never receive a PlaceEvent. Did you ever find a solution? – koga73 Sep 23 '16 at 19:04
  • @koga73 You can use a sticky service for that purpose. Even if the application process is killed by OS , sticky service will be started again and you will have almost 0 probability of missing an event.It takes very less time by OS to fire your sticky service again once process killed. But still I think Gimbal should have broadcast the event or start a IntentService using a PendingIntent. – Mahendra Chhimwal Sep 24 '16 at 08:49
  • @MahendraChhimwal I am returning START_STICKY from onCommandStart. The service does restart but the place enter event never fires. Even in the sample application bundled with the SDK if you put a log in onVisitStart it never logs out after the service restarts. – koga73 Sep 26 '16 at 14:48