0

I have an app in which the activity(MainActivity.java) creates the object of a Java class(Algo.java) which is supposed to do some DataBase entries and then this class has to be bounded with the service(ActionService.java) to pass an object.

For this in the constructor of the Algo I call the context.bindService(), but the onBind of the service is not called immediately, however bindService() returns true, the Algo does it's DB entries and when it's work is done and it is ready to call the service method, it still has the mBound variable as null(in the method publishToActionService), but after this it calls the onBound() method and the subsequent onServiceConnected(), now I looked around and found that it is an asynchronous call, but is there a way to ensure that onBound is called before any other execution in the code.

A code description is below:

public Algo(Context context){
    this.context = context;
    this.dbh = DBHelper.getInstance(context);
    Intent intent = new Intent(context, ActionService.class);           
    boolean b = context.getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);     
}

//method to make DB calls
//---

private void publishToActionService(HackBotEvent hackBotEvent){             
    if((hackBotEvent != null) && (hackBotEvent.getIsLearned() != -1) && (mBound))
    {
            mService.fillListenedEventList(hackBotEvent);
    }
}

private static ServiceConnection mConnection = new ServiceConnection() {

    @Override 
    public void onServiceConnected(ComponentName className, IBinder service) {
        // We've bound to LocalService, cast the IBinder and get LocalService instance
        Log.d(LOG,"in onServiceConnected, setting mBound true");
        ActionService.LocalBinder binder = (ActionService.LocalBinder) service; 
        mService = binder.getService(); 
        mBound = true; 
    } 

    @Override 
    public void onServiceDisconnected(ComponentName arg0) {
        Log.d(LOG,"in onServiceDisconnected, setting mBound false");
        mBound = false;
    } 
};  

MainActivity.java, this is the Algo call:

Algo algo = new Algo(this);

The entire code of the Algo.java class can be seen here.

rd22
  • 1,032
  • 1
  • 18
  • 34

2 Answers2

2

You should bind your service in the onStart() Method of your activity and unbind it in onStop(). You can have a flag like serviceBound(boolean) which you can set true or false in your onServiceConnected and onServiceDisconnected callback methods.

EDIT

You should not bind your service form the broadcast receivers, Please have a look on the links this and this

You should pass the intent on startService method form the BroadcastReceiver and perform your task from onStartCommand method of the service.

Community
  • 1
  • 1
Sanjeet A
  • 5,171
  • 3
  • 23
  • 40
  • Yes, but Algo is a new java class and not an activity, so I don't have the onStart and onStop methods, it is designed this way because I needed to call the Algo methods from BroadCastReceivers. – rd22 Jul 23 '15 at 18:03
  • okay, so this helps, I didn't know that this should not be done. However this is what I intended to do, and right now I am mocking this behaviour by making some dummy calls, form the MainActivity. To the problem remains the same, insure that `onBind` is called before any code executes. – rd22 Jul 23 '15 at 18:32
  • Can you ensure your service is returning right IBinder's instance in onBind method of service? – Sanjeet A Jul 23 '15 at 18:39
  • Yes I am sure it is, I can see it in the logs, the issue is that the call to `onBind` is delayed, when I run the entire process again everything works correctly as now it is already binded. – rd22 Jul 23 '15 at 18:44
1

Couple of options,

  1. In Algo, add a callback, like onReady(),

    protected abstract void onReady();

You call this when you bind to the service. In whatever uses Algo, implement that method, and don't call back into Algo to initiate any DB operation until you get the onReady() callback.

  1. Bind outside of Algo, in whatever is hosting that class (be it an Activity, a Service, or an Application). Once bound, pass in the service binder into Algo's constructor so it can use it right away.
Jeffrey Blattman
  • 22,176
  • 9
  • 79
  • 134
  • I understand the 2nd option, still analysing if it is feasible in my case. Would you mind being a little more descriptive about point 1, I didn't get that completely. – rd22 Jul 23 '15 at 18:38
  • So I don't think i can go with the 2nd option, I have some `BroadcastReceivers` which call the methods in the ALgo.java that calidates and make the DB call, and if that object from the algo fulfills a condition it is passed to the `ActionService.java`. – rd22 Jul 23 '15 at 18:42
  • then don't register the receivers until you are bound. it's really not a discussion, you don't have any choice. i've just described two ways to accomplishing the same thing: don't use the service until it's bound. any way you slice it, you have to wait until you are bound before using the service, and binding is an asynchronous operation. there's no way around it. – Jeffrey Blattman Jul 23 '15 at 18:52