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

简介: 首先建立在server端建立两个aidl文件 ITaskCallback.aidl 用于存放要回调client端的方法 [java] view plaincopy package com.

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

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

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

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

  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

  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

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


目录
相关文章
|
3月前
|
Java 程序员 开发工具
Android|修复阿里云播放器下载不回调的问题
虽然 GC 带来了很多便利,但在实际编码时,我们也需要注意对象的生命周期管理,该存活的存活,该释放的释放,避免因为 GC 导致的问题。
49 2
|
4月前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
417 4
|
5月前
|
API Android开发
Android P 性能优化:创建APP进程白名单,杀死白名单之外的进程
本文介绍了在Android P系统中通过创建应用进程白名单并杀死白名单之外的进程来优化性能的方法,包括设置权限、获取运行中的APP列表、配置白名单以及在应用启动时杀死非白名单进程的代码实现。
79 1
|
5月前
|
Android开发 开发者 Kotlin
Android 多进程情况下判断应用是否处于前台或者后台
本文介绍在多进程环境下判断Android应用前后台状态的方法。通过`ActivityManager`和服务信息`RunningAppProcessInfo`可有效检测应用状态,优化资源使用。提供Kotlin代码示例,帮助开发者轻松集成。
318 8
|
5月前
|
算法 数据处理 开发工具
Android平台RTSP|RTMP播放器如何回调YUV或RGB数据
在开发Android平台上的RTSP或RTMP播放器时,开发者不仅追求低延迟播放,还希望获取解码后的视频数据(如YUV或RGB格式),以便进行视觉算法分析。使用大牛直播SDK中的SmartPlayer,可在确保播放流畅的同时,通过设置外部渲染器(`SmartPlayerSetExternalRender`)来高效地回调原始视频数据。例如,对于RGBA数据,需实现`NTExternalRender`接口,并重写相关方法以处理数据和尺寸变化。同样地,对于I420(YUV)数据,也需要相应地实现接口以满足需求。这种方式使得开发者能在不影响常规播放功能的情况下,进行定制化的视频处理任务。
|
5月前
|
开发工具 Android开发
Android项目架构设计问题之SDK内部减少每次回调时的冗余判断逻辑如何解决
Android项目架构设计问题之SDK内部减少每次回调时的冗余判断逻辑如何解决
47 0
|
5月前
|
开发工具 Android开发
Android项目架构设计问题之外部客户方便地设置回调如何解决
Android项目架构设计问题之外部客户方便地设置回调如何解决
35 0
|
5月前
|
Java API 开发工具
Android项目架构设计问题之为SDK添加新的回调支持如何解决
Android项目架构设计问题之为SDK添加新的回调支持如何解决
35 0
|
6月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
6月前
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
202 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)