Service(2)

    xiaoxiao2021-09-02  116

    IPC 进程间通信

    进程间通讯方式:共享内存--》共享文件----》Socket服务器与Client--》Java RPC(远程过程调用)

    Android :Service远程绑定,调用方法、传数据

    信使、AIDLAndroid Interface Definition Language

    信使通讯:信使发送的消息是通过IBinder发送,实际的方法就是sendMessage  

     

    sendMessage注意

    1、Message 消息:Message消息在信使传递的时候,所有的数据必须是基础数据类型或者是Parcelable数据类型Message.obj不能直接使用String类型,那么推荐使用Bundle(可序列化的)使用Bundle来传递复杂信息

     

            常见的Parcelable: Intent,Bundler,Bitmap            

     

    信使开发步骤:

    创建服务,注册服务

    为了对外提供服务的启动方式,隐式意图的定义 和exporter=“true”

    在服务中创建信使,定义接收消息的Handler,返回Binder给外界

    /**

     * 绑定的时候,返回绑定的用来发送消息的控制器。

     *

     * @param intent

     * @return

     */

    @Override

    public IBinder onBind(Intent intent) {

        // 返回信使的 Binder 就可以收消息了

        return receiveMessenger.getBinder();

    }

    返回的Binder

    @Override

    public void onServiceConnected(ComponentName name, IBinder service) {

        // 对于远程的服务 IBinder 采用信使方式的时候,类型就是信使之间的传输接口

        // 可以理解为一个手机号,通过Messenger类就可以封装 IBinder,就可以发消息了

        sendMessenger new Messenger(service);

     

    }

    public void btnPause(View view) {

     

        // 进行信息的发送

        if (sendMessenger != null) {

            Message message = new Message();

            message.what 998;

     

            try {

                sendMessenger.send(message);

            } catch (RemoteException e) {

                e.printStackTrace();

            }

        }

     

    }

     

    当发送relayTo

    // 进行信息的发送

    if (sendMessenger != null) {

        Message message = new Message();

        message.what 199;

     

        // 发送给服务的信息,服务收到的时候,可以进行

        // 回报,通过 replyTo 可以给Activity发消息

        message.replyTo replyMessenger;

     

        try {

            sendMessenger.send(message);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

     

    用于接收消息的信使必须采用Handler的构函,发送消息的信息必须采用IBinder进行构造 

    AIDL:定义了应用程序之间,接口方法调用规则Android的照相机

    服务部定义AIDL,外界使用

     

    AIDL编写规则

    package包路径;interface 接口接口名称{定义接口}

    注意这里的接口名称与文件名是一样的否则会告诉你在文件中声明。。。

     

    当参数是数组或者List的时候,AIDL不知道这个参数是用来设置数据或者获取数据的,那么需要开发人员指定:添加方向的修饰符,in out inout

    当AIDL文件中需要使用复杂的对象类型的时候,如Message作为参数,在客户端与服务端对应的源代码中必须要创建android.os.Message.aidl,这样aidl文件才可以编译通过

     

    指定的类必须是parcelable的类型,

    Message.aidl

            package android.os;

            parcelble Message;

     使用import android.os.Message;

    有非基础类型的参数使用in out inout来指定方向

     

    远程调用底层的原理:

    1、服务本身可以通过隐式意图启动,不论是否在一个进程中;真正的启动都是由Android系统。

    2、当服务启动之后绑定服务时,最底层的交互方式都是透过IBinder对象来交互,IBinder是Android定义的应用程序之间交互的一个桥梁,实际上可以认为是IO流操作

    3、IBinder的数据交互采用传递Parcelable对象形式常见的Parcelable: Intent,Bundler,Bitmap ,那么Parcelable最终可以形成字节数组,进行传递。同时也能够从字节数组解码出对象

     

    iConnection=IConnection.Stub.asInterface(service);// 相当于建立了通道可以进行通讯,接下来可以操作aidl文件里的方法

    客户端实现绑定后public void onServiceConnected(ComponentName name, IBinder service) {

        iConnection=IConnection.Stub.asInterface(service);

        try {

            int i=iConnection.getInt();

            Log.d("message","获得的889"+i);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

     

     

     

     

    1、

    Intent intent=new Intent("com.chen.action.PLAY_SERVICE");

    // 绑定其他程序的服务时不知道类名的

    // 因此需要是要隐式意图来绑定

    bindService(intent,this,BIND_AUTO_CREATE);

    2、服务

    @Override

    public void onCreate() {

        super.onCreate();

        // 在服务中用于接收其他程序发送过来的消息

        // 需要采用MessengerHandler)这种构函创建一个接收消息的信使

        message=new Messenger(rhandler);

     

    }

    @Override

    public IBinder onBind(Intent intent) {

        // 将信使的绑定接口返回给其他应用程序

        // 相当于把手机号给别人,其他人就可以用手机号给你发短信

        return message.getBinder();

    }

    3、Activity

    @Override

    public void onServiceConnected(ComponentName name, IBinder service) {

        // 对于远程的服务,那么IBinder采用信使的方式的时候,类型是信

        // 使之间的传输接口,可以认为是手机号Messenger类封装IBinder就可以发信息了

        smessenger=new Messenger(service);

        // 进行信息的发送

        Message message=new Message();

        message.what=100;

        try {

            smessenger.send(message);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

    与Activity的生命周期绑定同步

    @Override

    protected void onPause() {

        super.onPause();

        unbindService(this);

    }

     

    @Override

    public void onServiceDisconnected(ComponentName name) {

        smessenger=null;// 信使制空

    }

     

    AIDL

    @Override

        public void onServiceConnected(ComponentName name, IBinder service) {

            // 使用AIDLIBinder需要通过asInterface转化成相应的接口实现类

            // 转换的servre就是AIDL 的接口,包含了所有可以调用服务的Service里面的方法

            aidlService = AIDLService.Stub.asInterface(service);

            try {

                int result=aidlService.getVersion();

                String s=aidlService.getString();

    //            aidlService.sayHello("client");

                Log.d("result",""+result+s);

     

    绑定的服务类

    class Controller extends AIDLService.Stub{

     

        @Override

        public int getVersion() throws RemoteException {

            return 998;

        }

     

        @Override

        public String getString() throws RemoteException {

            return "hello";

        }

     

        @Override

        public void sayHello(String who) throws RemoteException {

            Log.d("Service","nihao"+who);

        }

     

        @Override

        public long sum(byte[] data) throws RemoteException {

            return 0;

        }

    }

    转载请注明原文地址: https://ju.6miu.com/read-677388.html

    最新回复(0)