Android接口定义语言---AIDL(四)

调用IPC方法

以下是调用AIDL所定义的远程接口的必须的步骤:

1. 在工程的src/目录中包含对应的.aidl文件;

2. 声明IBinder接口(基于AIDL生成的)的一个实例;

3. 实现ServiceConnection接口;

4. 调用Context.bindService()方法,并传入ServiceConnection接口的实现;

5. 在onServiceConnected()方法的实现中,会接收到一个IBinder实例(叫做service)。调用YourInterfaceName.Stub.asInterface((IBider)service)方法把要返回的参数转换成YourInterfaceType;

6. 调用在接口中定义的方法。应该始终扑捉DeadObjectException异常,在连接被中断时会抛出这个异常。这是由远程方法所抛出的唯一异常;

7. 调用接口实例的Context.unbindService()方法来取消连接;

调用IPC服务的几点意见:

1. 对象是跨进程被引用计数的;

2. 能够发送匿名对象作为方法参数。

关于绑定服务的更多信息,请看“绑定服务”的文档.

http://developer.android.com/guide/components/bound-services.html#Binding

下面的示例代码演示了调用远程创建的AIDL服务,这个远程服务的例子在ApiDemos工程中:

public static class Binding extends Activity {

    /** The primary interface we will be calling on the service. */

    IRemoteService mService = null;

    /** Another interface we use on the service. */

    ISecondary mSecondaryService = null;

 

    Button mKillButton;

    TextView mCallbackText;

 

    private boolean mIsBound;

 

    /**

     * Standard initialization of this activity.  Set up the UI, then wait

     * for the user to poke it before doing anything.

     */

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

 

        setContentView(R.layout.remote_service_binding);

 

        // Watch for button clicks.

        Button button = (Button)findViewById(R.id.bind);

        button.setOnClickListener(mBindListener);

        button = (Button)findViewById(R.id.unbind);

        button.setOnClickListener(mUnbindListener);

        mKillButton = (Button)findViewById(R.id.kill);

        mKillButton.setOnClickListener(mKillListener);

        mKillButton.setEnabled(false);

 

        mCallbackText = (TextView)findViewById(R.id.callback);

        mCallbackText.setText("Not attached.");

    }

 

    /**

     * Class for interacting with the main interface of the service.

     */

    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.  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);

            mKillButton.setEnabled(true);

            mCallbackText.setText("Attached.");

 

            // We want to monitor the service for as long as we are

            // connected to it.

            try {

                mService.registerCallback(mCallback);

            } catch (RemoteException e) {

                // In this case the service has crashed before we could even

                // do anything with it; we can count on soon being

                // disconnected (and then reconnected if it can be restarted)

                // so there is no need to do anything here.

            }

 

            // As part of the sample, tell the user what happened.

            Toast.makeText(Binding.this, R.string.remote_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.

            mService = null;

            mKillButton.setEnabled(false);

            mCallbackText.setText("Disconnected.");

 

            // As part of the sample, tell the user what happened.

            Toast.makeText(Binding.this, R.string.remote_service_disconnected,

                    Toast.LENGTH_SHORT).show();

        }

    };

 

    /**

     * Class for interacting with the secondary interface of the service.

     */

    private ServiceConnection mSecondaryConnection = new ServiceConnection() {

        public void onServiceConnected(ComponentName className,

                IBinder service) {

            // Connecting to a secondary interface is the same as any

            // other interface.

            mSecondaryService = ISecondary.Stub.asInterface(service);

            mKillButton.setEnabled(true);

        }

 

        public void onServiceDisconnected(ComponentName className) {

            mSecondaryService = null;

            mKillButton.setEnabled(false);

        }

    };

 

    private OnClickListener mBindListener = new OnClickListener() {

        public void onClick(View v) {

            // Establish a couple connections with the service, binding

            // by interface names.  This allows other applications to be

            // installed that replace the remote service by implementing

            // the same interface.

            bindService(new Intent(IRemoteService.class.getName()),

                    mConnection, Context.BIND_AUTO_CREATE);

            bindService(new Intent(ISecondary.class.getName()),

                    mSecondaryConnection, Context.BIND_AUTO_CREATE);

            mIsBound = true;

            mCallbackText.setText("Binding.");

        }

    };

 

    private OnClickListener mUnbindListener = new OnClickListener() {

        public void onClick(View v) {

            if (mIsBound) {

                // If we have received the service, and hence registered with

                // it, then now is the time to unregister.

                if (mService != null) {

                    try {

                        mService.unregisterCallback(mCallback);

                    } catch (RemoteException e) {

                        // There is nothing special we need to do if the service

                        // has crashed.

                    }

                }

 

                // Detach our existing connection.

                unbindService(mConnection);

                unbindService(mSecondaryConnection);

                mKillButton.setEnabled(false);

                mIsBound = false;

                mCallbackText.setText("Unbinding.");

            }

        }

    };

 

    private OnClickListener mKillListener = new OnClickListener() {

        public void onClick(View v) {

            // To kill the process hosting our service, we need to know its

            // PID.  Conveniently our service has a call that will return

            // to us that information.

            if (mSecondaryService != null) {

                try {

                    int pid = mSecondaryService.getPid();

                    // Note that, though this API allows us to request to

                    // kill any process based on its PID, the kernel will

                    // still impose standard restrictions on which PIDs you

                    // are actually able to kill.  Typically this means only

                    // the process running your application and any additional

                    // processes created by that app as shown here; packages

                    // sharing a common UID will also be able to kill each

                    // other's processes.

                    Process.killProcess(pid);

                    mCallbackText.setText("Killed service process.");

                } catch (RemoteException ex) {

                    // Recover gracefully from the process hosting the

                    // server dying.

                    // Just for purposes of the sample, put up a notification.

                    Toast.makeText(Binding.this,

                            R.string.remote_call_failed,

                            Toast.LENGTH_SHORT).show();

                }

            }

        }

    };

 

    // ----------------------------------------------------------------------

    // Code showing how to deal with callbacks.

    // ----------------------------------------------------------------------

 

    /**

     * This implementation is used to receive callbacks from the remote

     * service.

     */

    private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {

        /**

         * This is called by the remote service regularly to tell us about

         * new values.  Note that IPC calls are dispatched through a thread

         * pool running in each process, so the code executing here will

         * NOT be running in our main thread like most other things -- so,

         * to update the UI, we need to use a Handler to hop over there.

         */

        public void valueChanged(int value) {

            mHandler.sendMessage(mHandler.obtainMessage(BUMP_MSG, value, 0));

        }

    };

 

    private static final int BUMP_MSG = 1;

 

    private Handler mHandler = new Handler() {

        @Override public void handleMessage(Message msg) {

            switch (msg.what) {

                case BUMP_MSG:

                    mCallbackText.setText("Received from service: " + msg.arg1);

                    break;

                default:

                    super.handleMessage(msg);

            }

        }

 

    };

 

你可能感兴趣的:(android,service,语言,button,interface,binding)