Aidl与信使的区别

Messenger实现了IPC通信(进程间通信),其真实原理也是使用了AIDL进行通信,但是和直接使用AIDL不同的是Messenger利用了Handler处 理通信,所以它是线程安全的(不支持并发处理);
而我们平时用的AIDL是非线程安全的(支持并发处理)。所以大多数时候我们应用中是不需要处理夸进程并 发处理通信的,所以这时选择Messenger会比AIDL更加容易操作。

在不考虑并发的情况下,Messenger相比AIDL无论从代码量、工程结构、复杂度等上都更加胜出一筹

信使 代码的服务端:
//这个里面要注意自己的Messenger对象的创建是以Handler为构造参数的,而接受到的对方的Messenger则是以Binder为构造参数的(在客户端),在服务端接受的Messenger对象则是从消息中直接获取。
要在清单文件中注册服务:
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super .onCreate(savedInstanceState);
        setContentView(R.layout. activity_main );
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu. main , menu);
        return true ;
    }
}
public class PrintService extends Service {
        //1. 声明和实例化Handler及Messenger类对象,在这个方法中处理客户端发送过来的信息
              private static Handler mHandler = new Handler(){
                     @Override
                     public void handleMessage(Message msg) {
                            //处理其它线间或进程发送过来的消息
                           Log. i( "debug" , "--PrintService ---------------------->handleMessage:"
                                        +msg.getData().getString( "info" ));
                           
                           Message replyMsg=Message. obtain();
                           replyMsg. what =2;
                           
                            try {
                                 //msg.replyTo 是获取到客户端传递过来的Messenger对象。,然后用客户端自己的Messenger对象,在给客户端发送消息。
                                 msg. replyTo .send(replyMsg); //应答客户端: 向客户端回传消息
                                 
                           } catch (RemoteException e) {
                                 e.printStackTrace();
                           }
                    }
             };
             //创建本地的Messenger,以handler为构造参数。
              private Messenger messenger = new Messenger( mHandler );
             
              @Override
              public IBinder onBind(Intent intent) {
                     return messenger .getBinder(); //2.获取Messenger对象的IBinder接口对象
             }

}

布局文件:
< RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:tools = "http://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    android:paddingBottom = "@dimen/activity_vertical_margin"
    android:paddingLeft = "@dimen/activity_horizontal_margin"
    android:paddingRight = "@dimen/activity_horizontal_margin"
    android:paddingTop = "@dimen/activity_vertical_margin"
    tools:context = ".MainActivity" >

    < TextView
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:text = "@string/hello_world" />

</ RelativeLayout >
------------------------
信使客户端:
布局文件:
< RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:tools = "http://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    android:paddingBottom = "@dimen/activity_vertical_margin"
    android:paddingLeft = "@dimen/activity_horizontal_margin"
    android:paddingRight = "@dimen/activity_horizontal_margin"
    android:paddingTop = "@dimen/activity_vertical_margin"
    tools:context = ".MainActivity" >

    < Button
        android:id = "@+id/btnId"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:onClick = "send"
        android:text = "项服务端发送消息" />

</ RelativeLayout >

主界面代码:

/*
 * 基于Messenger实现应用间的线程间通信
 * 1.客户端:
 *           声明Messenger对象
 *           声明并实例化SerViceConnection 接口对象 ,在绑定服务组件时使用,用于监听绑定是否成功
 *           在合适的位置调用Context.bindService()方法进行绑定
 *           在 ServiceConnection接口 的onServiceConnected()方法中
 *           将方法的第二个参数作为实例化Messenger的构造方法参数使用
 *           在核实的位置,调用Messenger对象的send(Message msg) 项服务端的Handler中发送消息
 *
 * 2.  
 * 2) 如果客户端需要接收服务端回传或应答的消息,需要实例化Handler和Messenger,
 *       并将Messenger作为服务端应答的信使封装在向服务端发送的Message(消息)中
 */
public class MainActivity extends Activity {
        //1. 声明Messenger对象,这个对象是从服务端发送过来的Messenger对象。
              private Messenger messenger ;
             
              //2. 实例化ServiceConnection接口对象
              private ServiceConnection conn = new ServiceConnection(){
                     @Override
                     public void onServiceConnected(ComponentName name, IBinder service) {
                            // TODO 绑定成功的回调方法
                            //4.实例化Messenger对象,并使用当前方法的第二个参数,传入到Messenger构造方法中。这个Messenger对象是从服务端发送过来的。
                            messenger = new Messenger(service);
                    }
                     @Override
                     public void onServiceDisconnected(ComponentName name) {
                            // TODO Auto-generated method stub
                           
                    }
             };
             
              private Handler replyHandler = new Handler(){
                     @Override
                     public void handleMessage(Message msg) {
                            //接收服务端回传的消息
                            if (msg. what ==2){
                                 Toast. makeText(getApplicationContext(), "发送消息成功.." , 1).show();
                           }
                    }
             };
             //这个是客户端自己的信使,这个信使的作用是要被传递到服务端,在给客户端发送消息
              private Messenger replyMessenger = new Messenger( replyHandler ); //应答信使
             
             
              @Override
              protected voi d onCreate(Bundle savedInstanceState) {
                     super .onCreate(savedInstanceState);
                    setContentView(R.layout. activity_main );
                    
                     //3.开始绑定服务组件
                    bindService( new Intent( "com.mrl.messenger_server.PrintService" ),
                                  conn , BIND_AUTO_CREATE );
             }
             
              public void send(View v){
                     //5. 通过Messenger信使,向绑定服务组件所在的应用发送消息(由这一应用的Handler来处理的)
                    
                    Message msg=Message. obtain();
                     //进程间传递的信息必须实现Parcelable接口 ,一般如果要传递对象什么的,应该通过Bundle来传递不会抛异常。
                     //msg.obj="hello,Messenger~Server"; //此处会抛出异常,原因是String类没有实现 Parcelable接口
                    Bundle data= new Bundle();
                    data.putString( "info" , "hello,Messenger~Server" );
                    
                    msg.setData(data); //设置发送消息的数据
                    
                     //设置服务端应答信使,将客户端的信使作为消息发送给服务端
                    msg. replyTo = replyMessenger ;
                    
                     try {
                            //这个Messenger是服务端发送过来的Messenger对象,现在往服务端发送消息。
                            messenger .send(msg); //通过信使开始向外部应用发送消息
                    } catch (RemoteException e) {
                           e.printStackTrace();
                    }
             }

}
-----------------------------------------------------
aidl的创建于使用:
先在服务端的src下创建一个包,新建一个  .aidl文件。如下图:
aidl文件的写法:
package com.mrl.aidl;

interface IRemoteService{//接口名不能用public 修饰 

       void print(String msg );
       
       String getName();
}
在服务端的配置文件中配置service组件:
  <!-- 注册Service组件,注:此组件可被其应用访问,因此必须要提供一个Action -->
        < service android:name = "com.mrl.serviceaidl_server.RemoteService" >
            < intent-filter >
                < action android:name = "com.mrl.serviceaidl_server.RemoteService" />
            </ intent-filter >
        </ service >
将服务端的aidl文件连同包一块拷贝到客户端。

下面是代码实例:
客户端主界面:

/**
 * 通过AIDL方式绑定其它应用的服务组件
 * @author apple
 *
 */
public class MainActivity extends Activity {

        //声明aild接口对象
       IRemoteService remoteService ;
       
        //实例化绑定组件之间的通信接口
       ServiceConnection conn = new ServiceConnection() {
             
              @Override
              public void onServiceDisconnected(ComponentName name) {}
             
              @Override
              public void onServiceConnected(ComponentName name, IBinder service) {
                     //将第二个参数转化为. aidl接口对象
                     remoteService =IRemoteService.Stub.asInterface(service);
             }
       };
       
        @Override
        protected void onCreate(Bundle savedInstanceState) {
              super .onCreate(savedInstanceState);
             setContentView(R.layout. activity_main );
             
              //绑定其它应用的Service组件,在绑定成功之后,将返回的Stub对象转化为 aidl接口对象
             bindService( new Intent( "com.mrl.serviceaidl_server.RemoteService" ),
                            conn , BIND_AUTO_CREATE );
             
       }
       
       
        public void getRemoteName(View v) throws RemoteException{
              if ( remoteService != null ){
                    setTitle( remoteService .getName());
             }
       }

       
        public void print(View v) throws RemoteException{
              if ( remoteService != null ){
                     remoteService .print( "hello,service!!!" );
             }
       }
}
服务端主界面:

/**
 * 使用AIDL原理,实现进程间(应用间)的Service组件与Activity组件的通信
 * 1) 服务端
 *        1.声明. aidl文件,在此文件中声明进程间的通信接口(类似于Binder子类的作用)
 *        2.在Service组件的onBind()方法中,返回 aidl接口的Stub对象
 *        3. 注册Service组件是,必须要提供一个启动或绑定此组件的Action
 *
 * 2) 客户端
 *        1. 将服务端提供的. aidl文件复制到src
 *     2. 在Activity类中,实例化ServiceConnection接口对象,实现两个回调方法,
 *             在onServiceConnected()方法中将第二个参数转化. aidl接口对象
 *     3. 在适当的位置调用Context.bindService()方法,进行绑定
 *    
 *            此方法的第一个参数:Intent意图,在实例化时,需要指定Service组件的Action
 *    
 *
 * @author apple
 *
 */
public class MainActivity extends Activity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
              super .onCreate(savedInstanceState);
             setContentView(R.layout. activity_main );
       }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
              // Inflate the menu; this adds items to the action bar if it is present.
             getMenuInflater().inflate(R.menu. main , menu);
              return true ;
       }

}

public class RemoteService extends Service {

        //2.1 实例化.aidl接口的Stub对象
        private IRemoteService.Stub stub = new IRemoteService.Stub() {
             
              @Override
              public void print(String msg) throws RemoteException {
                    Log. i( "debug" , "--RemoteSerice---------------------------" +msg);
//                  Looper.prepare();
//                  这个操作会有问题:
//                  Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
//                  Looper.loop();
             }
//           cant't create handler inside thread that has has not called Looper.prepare()
              //only one looper may be created per thread at android.os.looper.prepare
              @Override
              public String getName() throws RemoteException {
//                  Looper.prepare();
//                  这个问题同样有错
//                  Toast.makeText(getApplicationContext(), "RemoteSerice", Toast.LENGTH_SHORT).show();
//                  Looper.loop();
                     return "RemoteSerice--------" ;
             }
       };
       
        @Override
        public IBinder onBind(Intent intent) {
              return stub ; //2.2 返回 aidl接口的Stub对象
       }
}
-------------------------------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值