Service(2)

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;

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值