Aidl与信使的区别

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jiyidehao/article/details/50792458
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对象
       }
}
-------------------------------------------
展开阅读全文

没有更多推荐了,返回首页