Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Local Service Sample, bindservice(), and ServiceConnection()

I have a question which is related to this question that was asked by @mnish about a year ago.

Please have a look at his question and code. He implements a ServiceConnection() and passes it to bindService(). This follows the Local Service Sample in the Service documentation near the top.

I want to implement the Local Service Sample, so I am trying to add some details from @mnish question/answer. In ServiceConnection() @mnish has this line that confuses me:

mService = ILocService.Stub.asInterface(iservice);

I understand @mnish wrote this code, but does anybody have any idea what ILocService is and any idea how I might go about creating my own ILocService? Where is this construct documented and do I need it? Also where does the value for IBinder iservice come from?

like image 906
Marie Avatar asked Jan 20 '23 10:01

Marie


2 Answers

He is probably using Android Interface Definition Language (AIDL) http://developer.android.com/guide/components/aidl.html

Therefore he has to use a stub of the server side implementation like documented:

 // This is called when the connection with the service has been
 // established, giving us the service object we can use to
 // interact with the service.  We are communicating with our
 // service through an IDL interface, so get a client-side
 // representation of that from the raw service object.
 mService = IRemoteService.Stub.asInterface(service);

The iservice reference is coming from the onServiceConnected method which is called after binding the service to your activity. The call bindService gets passed the ServiceConnection which implements the onServiceConnected method.

You don't need the "IRemoteService.Stub.asInterface(service)" when your implementation of the service is local, then you can just cast the service to you local service.

The local service sample does this in the service:

public class LocalService extends Service {
    private NotificationManager mNM;

    // Unique Identification Number for the Notification.
    // We use it on Notification start, and to cancel it.
    private int NOTIFICATION = R.string.local_service_started;

    /**
     * Class for clients to access.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with
     * IPC.
     */
    public class LocalBinder extends Binder {
        LocalService getService() {
        return LocalService.this;
        }
    }

    ...

}

And this in the Activity in the ServiceConnection class:

private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
        // This is called when the connection with the service has been
        // established, giving us the service object we can use to
        // interact with the service.  Because we have bound to a explicit
        // service that we know is running in our own process, we can
        // cast its IBinder to a concrete class and directly access it.
        mBoundService = ((LocalService.LocalBinder)service).getService();

        // Tell the user about this for our demo.
        Toast.makeText(Binding.this, R.string.local_service_connected,
                Toast.LENGTH_SHORT).show();
    }

    public void onServiceDisconnected(ComponentName className) {
        // This is called when the connection with the service has been
        // unexpectedly disconnected -- that is, its process crashed.
        // Because it is running in our same process, we should never
        // see this happen.
        mBoundService = null;
        Toast.makeText(Binding.this, R.string.local_service_disconnected,
            Toast.LENGTH_SHORT).show();
    }
};
like image 200
Tosa Avatar answered Jan 21 '23 23:01

Tosa


Here you are, my example .. will make you clear about that LOL

// My MyServiceInterface.aidl
package com.mad.exam;

interface MyServiceInterface {
     int getNumber();
}

//MyService 
public class MyService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Toast.makeText(this, "Service OnBind()", Toast.LENGTH_LONG).show();
        return mBinder;
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        Toast.makeText(this, "Service Created", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        Toast.makeText(this, "Service Destroyed ", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub
        super.onStart(intent, startId);
        Toast.makeText(this, "Service Started ", Toast.LENGTH_SHORT).show();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        return super.onUnbind(intent);
    }

    private final MyServiceInterface.Stub mBinder = new MyServiceInterface.Stub() {
        public int getNumber() {
            return new Random().nextInt(100);
        }
    };
}

//My Activity 
public class ServiceDemo extends Activity implements OnClickListener {
    MyServiceInterface mService;
    ServiceConnection mConnection;
    Button retreive;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.service);
        retreive = (Button) findViewById(R.id.retreive);
        retreive.setOnClickListener(this);

        mConnection = new ServiceConnection() {

            public void onServiceDisconnected(ComponentName name) {
                // TODO Auto-generated method stub
            }

            public void onServiceConnected(ComponentName name, IBinder service) {
                // TODO Auto-generated method stub
                mService = MyServiceInterface.Stub.asInterface(service);

                try {
                    int i;
                    i = mService.getNumber();
                    Toast.makeText(ServiceDemo.this, "The service value is: " + String.valueOf(i), Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        };
    }

    public void onClick(View v) {
        // TODO Auto-generated method stub
        Log.i("My Tag", "Clicked");
        Button btn = (Button) v;
        Intent callService = new Intent(this, MyService.class);
        bindService(callService, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();
        Intent callService = new Intent(this, MyService.class);
        bindService(callService, mConnection, Context.BIND_AUTO_CREATE);
    }
}
like image 20
George Nguyen Avatar answered Jan 22 '23 01:01

George Nguyen