首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络基础 >

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

2012-09-13 
Android接口定义语言---AIDL(四)调用IPC方法以下是调用AIDL所定义的远程接口的必须的步骤:1. 在工程的src/

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

           }

       }

 

   };

 

热点排行