zoukankan      html  css  js  c++  java
  • Android 进程间通信之AIDL和Messenger

    AIDL:Android Interface Definition Language,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口。
    ICP:Interprocess Communication ,内部进程通信。

    使用:
    1、先创建一个aidl文件,aidl文件的定义和java代码类似,但是!它可以引用其它aidl文件中定义的接口和类,但是不能引用自定义的java类文件中定义的接口和类,要引用自定义的接口或类,需要为此类也定义一个对应的aidl文件,并且此类要实现Parcelable接口,同时aidl文件和类文件必须要在相同包下进行声明;Android包含了aidl编译器,当定义好一个aidl文件的时候,会自动编译生成一个java文件,此文件保存在gen目录之下。

    在这个项目中,定义了两个aidl文件,其中Person实现了接口Parcelable,下面是这两个aidl文件的定义:

    Person.aidl 

    {
      parcelable Person;
    }

    IAIDLServerService.aidl

    {
      package com.webview;
      import com.webview.Person;// 引用上面的Person.aidl
    
      interface IAIDLServerService{
        String sayHello();
        Person getPerson();
      }
    }

    2、编写一个Service实现定义aidl接口中的内部抽象类Stub,Stub继承自Binder,并继承我们在aidl文件中定义的接口,我们需要实现这些方法。Stub中文意思存根,Stub对象是在服务端进程中被调用,即服务端进程。

    在客户端调用服务端定义的aidl接口对象,实现Service.onBind(Intent)方法,该方法会返回一个IBinder对象到客户端,绑定服务时需要一个ServiceConnection对象,此对象其实就是用来在客户端绑定Service时接收Service返回的IBinder对象。

    ||public static abstract class Stub extends android.os.Binder implements com.webview.IAIDLServerService

    public class AIDLServerService extends Service{
    
        @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
        
        private IAIDLServerService.Stub binder = new Stub() {
            @Override
            public String sayHello() throws RemoteException {
                return "Hello AIDL";
            }
            
            @Override
            public Person getPerson() throws RemoteException {
                Person person = new Person();
                person.setName("Livingstone");
                person.setAge(22);
                return person;
            }
        };
    }

    3、在服务端注册Service,将如下代码添加进Application节点之下!

    <service android:name="com.webview.AIDLServerService" 
      android:process=":remote"> 
      <intent-filter> 
        <action android:name="com.webview.IAIDLServerService"></action> 
      </intent-filter> 
    </service>

    至此,服务端进程定义已经完成!

    4、编写客户端,注意需要在客户端存一个服务端实现了的aidl接口描述文件,客户端只是使用该aidl接口,获取服务端的aidl对象(IAIDLServerService.Stub.asInterface(service))之后就可以调用接口的相关方法,而对象的方法的调用不是在客户端执行,而是在服务端执行。

    public class MainActivity extends Activity {
    
        private Button btn;
        private IAIDLServerService aidlService = null;
    
        private ServiceConnection conn = new ServiceConnection() {
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                aidlService = null;
            }
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                aidlService = IAIDLServerService.Stub.asInterface(service);
                try {
                    aidlService.doFunction();// 执行接口定义的相关方法
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btn = (Button) findViewById(R.id.button);
            tv = (TextView) findViewById(R.id.textview);
            btn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent service = new Intent("com.webview.IAIDLServerService");
                    bindService(service, conn, BIND_AUTO_CREATE);// 绑定服务
                }
            });
        }
    }

     客户端目录结构:

    Messenger:

    它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,客户端持有这个Messenger就可以与服务端通信了。
    1.Service实现Handler接口用于接客户端的请求
    2.Handler是要用于创建一个Messenger对象,这个对象要引用此Handler
    3.Messenger创建一个IBinder,并且在Service的onBind()方法中返回给客户端
    4.客户端用服务端返回的IBider对象实例化一个Messenger,此Messenger用于发送Message到Service服务端
    5.服务端接收每一个Message,并且在Handler中对消息进行处理-->handleMessage()
    6.如果需要服务端进行用户请求响应,需要在发送消息到服务端的时候,让Message引用客户端的Messenger对象(Handler.replyTo=Messenger),然后再调用Messenger的send()方法。这样服务端接收到消息的同时也得到了客户端的Messenger对象,服务端就可以通过客户端的Messenger对象向客户端发送消息。

    这种方法,没有用于供客户端调用的方法,而是客户端发送消息到服务端,服务端接到消息后对消息进行相应的处理!

    public class MSGService extends Service {
        Messenger mMessenger = new Messenger(new myHandler());
        class myHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case 1:
                    Toast.makeText(getApplicationContext(), "Hello", 1).show();
                    break;
                }
            }
        }
        @Override
        public IBinder onBind(Intent intent) {
            return mMessenger.getBinder();
        }
    }
    public class MainActivity extends Activity {
        Messenger mService = null;
        boolean bound = false;
        @Override
        protected void onStart() {
            super.onStart();
            Intent intent = new Intent();
            intent.setClassName("com.broadlistener", "com.broadlistener.MSGService");
            bindService(intent, conn, Context.BIND_AUTO_CREATE);
        }
        private ServiceConnection conn = new ServiceConnection() {
            @Override
            public void onServiceDisconnected(ComponentName name) {
            }
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mService = new Messenger(service);    
                bound = true;
            }
        };
        public void click(View v) {
            if (bound) {
                Message msg = Message.obtain(null, 1, 0, 0);
                try {
                    msg.replyTo = mService;// [6]
                    mService.send(msg);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    }
  • 相关阅读:
    python-深入学习
    python-第一天学习python
    JMeter-关联、添加压力机、linux下运行、抓包、手机抓包等学习
    python模块---常用模块2
    python模块---常用模块
    python函数--装饰器
    python函数--匿名函数,内置函数,闭包
    python函数--生成器,生成器表达式,列表推导式
    python函数--global,nonlocal ,新格式化输出,迭代器
    python函数--万能参数,形参,名称空间,嵌套,内置函数globals locals ,关键字nonlocal global
  • 原文地址:https://www.cnblogs.com/a284628487/p/3024983.html
Copyright © 2011-2022 走看看