跨进程的通信 [IPC]

本文详细介绍了Android中Messenger和AIDL两种进程间通信机制的原理及实现过程。包括Messenger的工作流程、AIDL的书写步骤及其背后的实现原理,并提供了具体的客户端和服务端代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Messenger 信使
  实现原理:
  在server和client端通过Messenger信使传递信息,该对象就相当于一个信息的中转站,所有的信息都要通过这个对象
 来携带,客户端向服务器端发送信息就需要服务器的信使对象,然后他想要接收到消息,就需要创建自己的信使对象,
 然后把自己的Messenger对象作为消息中的一部分,传递给服务器端,然后服务器端就能够拿着客户端的信使给客户端
 发消息。
 Messenger的实现流程:
  1.在server端创建一个信使对象:Messenger serverMessenger = new Messenger(handler);
  2.client端要通过bindService的方法绑定服务器端。
  3.在server端的onBind方法中返回一个binder对象,通过服务器端的信使获得的。serverMessenger.getBinder()
  4.在客户端通过重写onServiceConnected的方法可以获得服务器端的信使。就可以向服务器端发送消息。
  5.发送消息时,可以放入客户端的信使。
 小结:
  通过信使能够跨进程实现通信,底层是AIDL原理,和handler,thread相似。

实例:
客户端:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class MainActivity extends Activity {  
  2.     private Messenger serverMessenger;  
  3.   
  4.     private Messenger clientMessenger;  
  5.     Handler handler = new Handler() {  
  6.         public void handleMessage(Message msg) {  
  7.             Log.i("tag""-----服务器传来的消息------");  
  8.             Log.i("tag""arg1==" + msg.arg1 + ",arg2==" + msg.arg2);  
  9.         }  
  10.     };  
  11.   
  12.     @Override  
  13.     protected void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.activity_main);  
  16.         clientMessenger = new Messenger(handler);  
  17.   
  18.     }  
  19.   
  20.     ServiceConnection conn = new ServiceConnection() {  
  21.   
  22.         @Override  
  23.         public void onServiceDisconnected(ComponentName name) {  
  24.             // TODO Auto-generated method stub  
  25.   
  26.         }  
  27.   
  28.         @Override  
  29.         public void onServiceConnected(ComponentName name, IBinder service) {  
  30.             // 得到服务器端的信使  
  31.             serverMessenger = new Messenger(service);  
  32.         }  
  33.     };  
  34.   
  35.     @Override  
  36.     protected void onStart() {  
  37.         super.onStart();  
  38.         Intent intent = new Intent();  
  39.         intent.setAction("com.sdut.service");  
  40.         boolean b = bindService(intent, conn, BIND_AUTO_CREATE);  
  41.         if(b){  
  42.             Toast.makeText(this"绑定成功", Toast.LENGTH_SHORT).show();  
  43.         }  
  44.     }  
  45.   
  46.     public void click(View view) {  
  47.   
  48.         Message message = Message.obtain();  
  49.         message.what = 1;  
  50.         message.arg1 = 68;  
  51.         message.replyTo = clientMessenger;  
  52.         try {  
  53.             serverMessenger.send(message);  
  54.         } catch (RemoteException e) {  
  55.             e.printStackTrace();  
  56.         }  
  57.     }  
  58. }  
服务器端:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class MyService extends Service {  
  2.     Handler handler = new Handler() {  
  3.         public void handleMessage(android.os.Message msg) {  
  4.             if (msg.what == 1) {  
  5.                 Log.i("tag""客户端传来的消息");  
  6.                 Log.i("tag""传来的消息:" + msg.arg1+" "+msg.arg2);  
  7.                 Messenger clientMessage = msg.replyTo;  
  8.                 Message message = Message.obtain();  
  9.                 message.arg1 = 90;  
  10.                 message.arg2 = 180;  
  11.   
  12.                 try {  
  13.                     clientMessage.send(message);  
  14.                 } catch (RemoteException e) {  
  15.                     // TODO Auto-generated catch block  
  16.                     e.printStackTrace();  
  17.                 }  
  18.             }  
  19.         };  
  20.     };  
  21.     // 服务器端信使  
  22.     Messenger serviceMessage = new Messenger(handler);  
  23.   
  24.     @Override  
  25.     public IBinder onBind(Intent intent) {  
  26.         // TODO Auto-generated method stub  
  27.         return serviceMessage.getBinder();  
  28.     }  
  29.   
  30. }  
注册服务:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <service android:name="com.example.service.MyService">  
  2.            <intent-filter >  
  3.                <action android:name="com.sdut.service"/>  
  4.            </intent-filter>  
  5.        </service>  
AIDL方式   Android  Interface  Definition  Language   适用于不同应用程序之间的远程服务

书写步骤:
服务器端:
1.在服务器端,在src的文件夹中创建一个.aidl文件,在这个文件中定义客户端需要远程访问服务器端的方法。
2.在.aidl文件当中定义的方法和普通方法是一致的都有返回值和参数。
3.在服务器端暴漏.aidl这个类,并且在服务端获取其内部类Stub的对象。
4.实现aidl当中的方法,并且把Stub的对象添加为onBind的返回值。
客户端:
1.复制服务器端的.aidl文件到客户端,注意相同包名,相同类名。
2.重写onServiceConnected方法时获取aidl文件的对象。
3.绑定服务
4.通过获取到的对象,调用方法,得到返回值。
实现原理:
Android内存当中会自带一块存放aidl的公共区域,服务端会通过aidl文件,把要传入客户端的内容写入进去。
然后在通过onBind方法返回binder对象(继承于Binder类实现了aidl接口的Stub对象)。然后把生成的binder
对象通过序列化的方式写入到共享区域当中。
客户端也需要一个aidl的文件,这样才能够获得服务器端在共享区域里存放的文件的内容,然后客户端通过绑定服务
得到Binder对象,这个binder对象其实就是共享区域中服务器端生成的binder的对象经过反序列化的方式生成的对象。
通过binder对象就能够获得到服务器传来的信息了。
注意:
1.服务器端和客户端其实是对同一个aidl文件进行操作的。

2.服务器端生成的binder对象和客户端得到的binder对象不是同一个对象,是有相同内容的两个对象。


实例:

客户端:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class MainActivity extends Activity {  
  2.   
  3.     private DataService dataService;  
  4.     @Override  
  5.     protected void onCreate(Bundle savedInstanceState) {  
  6.         super.onCreate(savedInstanceState);  
  7.         setContentView(R.layout.activity_main);  
  8.     }  
  9.   
  10.     ServiceConnection conn = new ServiceConnection() {  
  11.         @Override  
  12.         public void onServiceDisconnected(ComponentName name) {  
  13.               
  14.         }  
  15.         @Override  
  16.         public void onServiceConnected(ComponentName name, IBinder service) {  
  17.             dataService = DataService.Stub.asInterface(service);  
  18.         }  
  19.     };  
  20.     public void bind(View v){  
  21.         Intent intent = new Intent();  
  22.         intent.setAction("com.qf.aidlserver");  
  23.         bindService(intent, conn, BIND_AUTO_CREATE);  
  24.           
  25.     }  
  26.     public void getInfo(View view){  
  27.         try {  
  28.             String str = dataService.getInfo();  
  29.             int i = dataService.getValue("哈哈");  
  30.               
  31.             Log.i("tag""从服务器传回的数据:"+i+","+str);  
  32.         } catch (RemoteException e) {  
  33.             e.printStackTrace();  
  34.         }  
  35.           
  36.     }  
  37.   
  38. }  

服务器端:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class MyService extends Service{  
  2.   
  3.     @Override  
  4.     public IBinder onBind(Intent intent) {  
  5.         Log.i("tag""绑定服务成功");  
  6.         return mBinder;  
  7.     }  
  8.       
  9.     DataService.Stub mBinder = new DataService.Stub() {  
  10.           
  11.         @Override  
  12.         public int getValue(String info) throws RemoteException {  
  13.             return 189;  
  14.         }  
  15.           
  16.         @Override  
  17.         public String getInfo() throws RemoteException {  
  18.             return "编程难,难于上青天!!!";  
  19.         }  
  20.     };  
  21. }  

注册服务:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <service android:name="com.example.service.MyService">  
  2.            <intent-filter >  
  3.                <action android:name="com.example.aidlserver"/>  
  4.            </intent-filter>  
  5.        </service>  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值