Search code examples
androidvariablesservice

What is the advantage of binding to a Service to get its variables, as opposed to using SharedPrefs, or getting the variables directly?


I've got a service meant to sometimes run in the background - started with startService(). What is the advantage of binding to this service so as to get/set its variables, instead of - controversial, I know, but still - just accessing its public variables directly (e.g. myVar = mainService.itsVar), or using SharedPrefs to set and get the values? Especially, what is the fastest, in terms of performance, based on the fact that the get interval would be roughly 3 seconds?


Solution

  • Advantage - You can access variables and run methods directly. Disadvantage - allot of cross thread headache, not to mention unresolved crashes on google developer console.

    How to do it correctly, I will give example of a foreground service, if it can be background then change only how to start it:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        mContext.startForegroundService(startIntent)
     } else {
        mContext.startService(startIntent);
     }
    

    In the service you need to implement all binding methods:

    private IBinder mBinder = new MyBinder();
    
    public MainService() {
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
    
    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }
    
    @Override
    public boolean onUnbind(Intent intent) {
        return true;
    }
    
    public class MyBinder extends Binder {
        public MainService getService() {
            return com.xxx.xxx.MainService.this;
        }
    }
    

    In the activity you need to listen to connection:

    private ServiceConnection mServiceConnection = new ServiceConnection() {
    
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mBoundService = null;
    
        }
    
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "connecting");
            MainService.MyBinder myBinder = (MainService.MyBinder) service;
            mBoundService = myBinder.getService();
            mShouldUnbind.set(true);
        }
    };
    

    If other activity or alarm can start your service you will need to check every second or so if the service was started by other and bind to it. Important - service run on the same thread like the main/GUI thread - so if you have time consumption actions like camera or uploading - you will need to start a background thread. back communication can be made by calling the GUI/main thread. on foreground service like mine - you need also to manage notifications otherwise the o.s. will kill the service after 5 seconds.

    Code example:

    if (mShouldUnbind.get() && mBoundService != null)
                val = mBoundService.getTimestamp();
    

    Edit I: advantage: I have a camera foreground service - I can set zoom values directly from the GUI thread since I have a handle to the service. the camera is running on the background thread in the service, but, since the preview is being drawn 30 times pro seconds - the zoom is set without any lag. you will never manage to do it in any other way.