Android中使用AIDL时的跨进程回调—Server回调Client

首先建立在server端建立两个aidl文件

ITaskCallback.aidl 用于存放要回调client端的方法

[java] view plaincopy

  1. package com.cmcc.demo.server;   
  2.   
  3. interface ITaskCallback {   
  4.     void actionPerformed(int actionId);  
  5. }   

ITaskBinder.aidl 用于存放供给client端调用的方法

[java] view plaincopy

  1. package com.cmcc.demo.server;   
  2.   
  3. import com.cmcc.demo.server.ITaskCallback;   
  4.   
  5. interface ITaskBinder {   
  6.     boolean isTaskRunning();   
  7.     void stopRunningTask();   
  8.     void registerCallback(ITaskCallback cb);   
  9.     void unregisterCallback(ITaskCallback cb);   
  10. }  

接着建立服务端,要实现回调,需要新建RemoteCallbackList对象(一个存储回调对象的列表),通过类似发送广播的形式来实现回调

MyService.java

[java] view plaincopy

  1. package com.cmcc.demo.server;   
  2.   
  3. import com.cmcc.demo.server.ITaskBinder;  
  4. import com.cmcc.demo.server.ITaskCallback;  
  5.   
  6. import android.app.Service;   
  7. import android.content.Intent;   
  8. import android.os.IBinder;   
  9. import android.os.RemoteCallbackList;   
  10. import android.os.RemoteException;   
  11. import android.util.Log;   
  12.   
  13. public class MyService extends Service {   
  14.     private static final String TAG = "aidltest";  
  15.   
  16.     @Override   
  17.     public void onCreate() {   
  18.         printf("service create");   
  19.     }  
  20.       
  21.     @Override   
  22.     public void onStart(Intent intent, int startId) {  
  23.         printf("service start id=" + startId);  
  24.         callback(startId);   
  25.     }  
  26.       
  27.     @Override  
  28.     public IBinder onBind(Intent t) {  
  29.         printf("service on bind");  
  30.         return mBinder;   
  31.     }  
  32.       
  33.     @Override  
  34.     public void onDestroy() {   
  35.         printf("service on destroy");   
  36.         super.onDestroy();   
  37.     }  
  38.       
  39.     @Override  
  40.     public boolean onUnbind(Intent intent) {   
  41.         printf("service on unbind");  
  42.         return super.onUnbind(intent);   
  43.     }  
  44.       
  45.     public void onRebind(Intent intent) {   
  46.         printf("service on rebind");  
  47.         super.onRebind(intent);   
  48.     }  
  49.       
  50.     private void printf(String str) {   
  51.         Log.v(TAG, "###################------ " + str + "------");   
  52.     }  
  53.       
  54.     void callback(int val) {   
  55.         final int N = mCallbacks.beginBroadcast();  
  56.         for (int i=0; i<N; i++) {   
  57.             try {  
  58.                 mCallbacks.getBroadcastItem(i).actionPerformed(val);   
  59.             }  
  60.             catch (RemoteException e) {   
  61.                 // The RemoteCallbackList will take care of removing   
  62.                 // the dead object for us.     
  63.             }  
  64.         }  
  65.         mCallbacks.finishBroadcast();  
  66.     }  
  67.       
  68.     private final ITaskBinder.Stub mBinder = new ITaskBinder.Stub() {  
  69.           
  70.         public void stopRunningTask() {  
  71.               
  72.         }  
  73.       
  74.         public boolean isTaskRunning() {   
  75.             return false;   
  76.         }   
  77.           
  78.         public void registerCallback(ITaskCallback cb) {   
  79.             if (cb != null) {   
  80.                 mCallbacks.register(cb);  
  81.             }  
  82.         }  
  83.           
  84.         public void unregisterCallback(ITaskCallback cb) {  
  85.             if(cb != null) {  
  86.                 mCallbacks.unregister(cb);  
  87.             }  
  88.         }  
  89.     };   
  90.       
  91.     final RemoteCallbackList <ITaskCallback>mCallbacks = new RemoteCallbackList <ITaskCallback>();  
  92.   
  93. }   

最后建立客户端,使用aidl,实现回调方法。

MyActivity.java

[java] view plaincopy

  1. package com.cmcc.demo;   
  2.   
  3. import android.app.Activity;   
  4. import android.content.ComponentName;   
  5. import android.content.Intent;   
  6. import android.content.ServiceConnection;   
  7. import android.os.Bundle;   
  8. import android.os.IBinder;   
  9. import android.os.RemoteException;   
  10. import android.util.Log;   
  11. import android.view.View;   
  12. import android.view.View.OnClickListener;   
  13. import android.widget.Button;   
  14.   
  15. import com.cmcc.demo.server.*;  
  16.   
  17. public class MyActivity extends Activity {   
  18.   
  19.     private static final String TAG = "aidltest";  
  20.     private Button btnOk;   
  21.     private Button btnCancel;  
  22.   
  23. @Override   
  24. public void onCreate(Bundle icicle) {   
  25.     super.onCreate(icicle);   
  26.     setContentView(R.layout.test_service);   
  27.       
  28.     btnOk = (Button)findViewById(R.id.btn_ok);  
  29.     btnCancel = (Button)findViewById(R.id.btn_cancel);   
  30.     btnOk.setText("Start Service");   
  31.     btnCancel.setText("Stop Service");   
  32.     btnCancel.setEnabled(false);  
  33.       
  34.     btnOk.setOnClickListener(new OnClickListener() {  
  35.             public void onClick(View v) {  
  36.                 onOkClick();  
  37.             }  
  38.         });   
  39.       
  40.     btnCancel.setOnClickListener(new OnClickListener() {  
  41.             public void onClick(View v) {  
  42.                 onCancelClick();  
  43.             }  
  44.         });  
  45.     }   
  46.   
  47.     void onOkClick() {  
  48.         printf("send intent to start");   
  49.         Bundle args = new Bundle();  
  50.         Intent intent = new Intent("com.cmcc.demo.IMyService");  
  51.         intent.putExtras(args);  
  52.         startService(intent);  
  53.         //bindService(intent, mConnection, Context.BIND_AUTO_CREATE);  
  54.         btnCancel.setEnabled(true);  
  55.     }   
  56.       
  57.     void onCancelClick() {   
  58.           
  59.         printf("send intent to stop");  
  60.         //unbindService(mConnection);  
  61.         Intent intent = new Intent("com.cmcc.demo.IMyService");  
  62.         stopService(intent);   
  63.         btnCancel.setEnabled(false);  
  64.     }   
  65.       
  66.     private void printf(String str) {   
  67.         Log.v(TAG, "###################------ " + str + "------");   
  68.     }  
  69.       
  70.     ITaskBinder mService;   
  71.       
  72.     private ServiceConnection mConnection = new ServiceConnection() {   
  73.           
  74.         public void onServiceConnected(ComponentName className, IBinder service) {  
  75.             mService = ITaskBinder.Stub.asInterface(service);   
  76.             try {   
  77.                 mService.registerCallback(mCallback);  
  78.             } catch (RemoteException e) {  
  79.                   
  80.             }  
  81.         }  
  82.           
  83.         public void onServiceDisconnected(ComponentName className) {   
  84.             mService = null;  
  85.         }   
  86.     };   
  87.       
  88.     private ITaskCallback mCallback = new ITaskCallback.Stub() {  
  89.           
  90.         public void actionPerformed(int id) {   
  91.             printf("callback id=" + id);  
  92.         }   
  93.     };   
  94.   
  95. }   

总结一下aidl的使用

AIDL的创建方法: 
AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。由于远程调用的需要, 这些参数和返回值并不是任何类型.下面是些AIDL支持的数据类型: 
1. 不需要import声明的简单Java编程语言类型(int,boolean等) 
2. String, CharSequence不需要特殊声明 

3. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型. 

(另外: 我没尝试Parcelables, 在Eclipse+ADT下编译不过, 或许以后会有所支持). 
下面是AIDL语法: 
// 文件名: SomeClass.aidl // 文件可以有注释, 跟java的一样 // 在package以前的注释, 将会被忽略. // 函数和变量以前的注释, 都会被加入到生产java代码中. package com.cmcc.demo; 
// import 引入语句 import com.cmcc.demo.ITaskCallback; 

interface ITaskBinder { 
//函数跟java一样, 可以有0到多个参数 ,可以有一个返回值 boolean isTaskRunning(); 
void stopRunningTask(); //参数可以是另外的一个aidl定义的接口 void registerCallback(ITaskCallback cb); 
void unregisterCallback(ITaskCallback cb); 
//参数可以是String, 可以用in表入输入类型, out表示输出类型. 
int getCustomerList(in String branch, out String customerList); 

实现接口时有几个原则: 
.抛出的异常不要返回给调用者. 跨进程抛异常处理是不可取的. 
.IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。
也就是IPC调用会挂起应用程序导致界面失去响应. 这种情况应该考虑单起一个线程来处理. 
.不能在AIDL接口中声明静态属性。 

IPC的调用步骤: 
1. 声明一个接口类型的变量,该接口类型在.aidl文件中定义。 
2. 实现ServiceConnection。 
3. 调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递. 
4. 在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用 YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换为YourInterface类型。 
5. 调用接口中定义的方法。 你总要检测到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。 
6. 断开连接,调用接口实例中的ApplicationContext.unbindService() 

时间: 2024-12-28 18:16:08

Android中使用AIDL时的跨进程回调—Server回调Client的相关文章

使用android中的AIDL让Service与Activity通信(service回调activity)

http://blog.csdn.net/h3c4lenovo/article/details/7885514

Android应用程序四大组件之使用AIDL如何实现跨进程调用Service_Android

一.问题描述 Android应用程序的四大组件中Activity.BroadcastReceiver.ContentProvider.Service都可以进行跨进程.在上一篇我们通过ContentProvider实现了不同应用之间的跨进程调用,但ContentProvider主要是提供数据的共享(如sqlite数据库),那么我们希望跨进程调用服务(Service)呢?Android系统采用了远程过程调用(RPC)方式来实现.与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言

Android应用程序四大组件之使用AIDL如何实现跨进程调用Service

一.问题描述 Android应用程序的四大组件中Activity.BroadcastReceiver.ContentProvider.Service都可以进行跨进程.在上一篇我们通过ContentProvider实现了不同应用之间的跨进程调用,但ContentProvider主要是提供数据的共享(如sqlite数据库),那么我们希望跨进程调用服务(Service)呢?Android系统采用了远程过程调用(RPC)方式来实现.与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言

实例讲解Android中的AIDL内部进程通信接口使用_Android

首先描述下我们想要实现的内容,我们希望在一个应用中通过点击按钮,去操作另一个进程中应用的音乐播放功能. 如图,我们点击"播放"时,系统就会去远程调用我们提供的一个service(与当前service不是同一个应用哦),然后操作service中的音乐播放,点击"停止"则会终止播放.想要重新播放的话,必须先点"销毁service",再点播放按钮哦.(至于这里为什么要先点销毁按钮才能播放,完全是为了给大家展示下,远程调用service时,怎么去解绑se

实例讲解Android中的AIDL内部进程通信接口使用

首先描述下我们想要实现的内容,我们希望在一个应用中通过点击按钮,去操作另一个进程中应用的音乐播放功能. 如图,我们点击"播放"时,系统就会去远程调用我们提供的一个service(与当前service不是同一个应用哦),然后操作service中的音乐播放,点击"停止"则会终止播放.想要重新播放的话,必须先点"销毁service",再点播放按钮哦.(至于这里为什么要先点销毁按钮才能播放,完全是为了给大家展示下,远程调用service时,怎么去解绑se

Android IPC机制利用Messenger实现跨进程通信_Android

写作原因:跨进程通信的实现和理解是Android进阶中重要的一环.下面博主分享IPC一些相关知识.操作及自己在学习IPC过程中的一些理解.这一章使用Messenger实现跨进程通信,其中bindService基础部分参见Android IPC机制绑定Service实现本地通信. 跨进程简介 在介绍使用Messenger跨进程通信之前先要了解以下问题:为什么需要跨进程通信?只有有了需求才有学习的价值.我个人将不同进程简单的理解为不同的应用程序(当然也有例外,比如可以在同一个应用程序中开启两个或多个

Android IPC机制利用Messenger实现跨进程通信

写作原因:跨进程通信的实现和理解是Android进阶中重要的一环.下面博主分享IPC一些相关知识.操作及自己在学习IPC过程中的一些理解.这一章使用Messenger实现跨进程通信,其中bindService基础部分参见Android IPC机制绑定Service实现本地通信. 跨进程简介 在介绍使用Messenger跨进程通信之前先要了解以下问题:为什么需要跨进程通信?只有有了需求才有学习的价值.我个人将不同进程简单的理解为不同的应用程序(当然也有例外,比如可以在同一个应用程序中开启两个或多个

Android Studio创建AIDL文件并实现进程间通讯实例

在Android系统中,跨进程通信是非常普遍的事情,它用到了Binder机制处理进程之间的交互.Binder机制会开放一些接口给Java层,供android开发工程师调用进程之间通信.这些接口android封装到了AIDL文件里,当我们项目用到跨进程通信时可以创建.aidl文件,.aidl文件可以协助我们达到跨进程的通信.下面简单介绍用AndroidStudio创建AIDL文件的过程. a.新建AIDL文件 1.项目文件夹右键---> new --->选择AIDL 2.自定义一个接口名称 3.

android中的AIDL进程间通信示例

关于IPC应该不用多介绍了,Android系统中的进程之间不能共享内存,那么如果两个不同的应用程序之间需要通讯怎么办呢?比如公司的一个项目要更新,产品的需求是依附于当前项目开发一个插件,但是呢这个插件功能以及界面比较复杂,不能和当前项目在一个进程中,同时呢,还要用到当前项目中已经写好了的一些东西,那么因为新开发的依附于当前项目的插件和当前项目不是一个进程,因此不能共享内存,就出现了问题,于是,需要提供一些机制在不同进程之间进行数据通信,这个机制就是AIDL了. 一.一个android中AIDL的