AIDL自定义实现

我们知道一般的Service写法为:
1.实现一个子类继承自Service
2.复写一个onBind事件,里面返回一个我们自定义的Binder子类对象
3.在Binder子类中我们实现其他程序调用的相关接口
其实AIDL服务端的实现也是按照这一流程走的:
首先我们看一下服务端的所有的code:

package com.qs.aidldemo;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;
import android.widget.Toast;
//自己实现的AIDL方法:
//技术博客考:http://blog.csdn.net/hitlion2008/article/details/9824009
public class MyAIDLService extends Service {
    private Handler mHandler = new Handler();
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private MyPrinterInterfaceStub mBinder = new MyPrinterInterfaceStub() {

        @Override
        public void print(String msg) throws RemoteException {
            MyAIDLService.this.print(msg);
        }

        @Override
        public String add(String a, String b) throws RemoteException {
            return MyAIDLService.this.add(a,b);
        }
    };

    public void print(String msg)
    {
        try{
            System.out.println("Preparing printer...");  
            Thread.sleep(1000);  
            System.out.println("Connecting printer...");  
            Thread.sleep(1000);  
            System.out.println("Printing.... " + msg);  
            Thread.sleep(1000);  
            System.out.println( "Done");  
        }catch(Exception e)
        {

        }
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MyAIDLService.this, "MyService printing is donw", 0).show();
            }
        });
    }
    //这个是服务器实现的add函数的功能
    public String add(String a,String b)
    {
        int sum =0;
        try{
            System.out.println("a="+a+" b="+b);
            sum = Integer.valueOf(a)+Integer.valueOf(b);
            System.out.println("Printing.... " + sum);  
        }catch(Exception e)
        {

        }
        return String.valueOf(sum);
    }
    //定义我们需要实现的两个接口函数
    public interface MyPrinterInterface extends IInterface {
        public void print(String msg) throws android.os.RemoteException;
        public String add(String a,String b) throws android.os.RemoteException;
    }


    //这个又是Binder的封装类  也就是我们私有的Binder类的实现
    abstract class MyPrinterInterfaceStub extends Binder implements MyPrinterInterface{
        private static final String DESCRIPTOR="MyPrinterInterface";
        private static final String TAG="MyPrinterInterfaceStub";

        public MyPrinterInterfaceStub(){
            attachInterface(this, DESCRIPTOR);
        }
        //这个函数似乎就没有被调用过
        @Override
        public IBinder asBinder() {
            System.out.println("Server asBinder");
            return this;
        }
        //data表示客户端传送过来的值  code表示的是调用的函数,我们发现客户端调用的函数是:mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
        //这里和我们的这个函数传残一模一样  因此我们服务器的code和客户端的code是需要一一对应的
        @Override
        protected boolean onTransact(int code, Parcel data, Parcel reply,
                int flags) throws RemoteException {
            System.out.println("onTransact,code is "+code);
            switch(code)
            {
            case INTERFACE_TRANSACTION:
                System.out.println("MyPrinterInterfaceStub onTransact,code is "+code+" ,when this happens");
                reply.writeString(DESCRIPTOR);
                return true;
            case TRANSACTION_print:
                data.enforceInterface(DESCRIPTOR);
                String _arg0;
                _arg0 = data.readString();
                System.out.println("MyPrinterInterfaceStub ontransact, arg is "+_arg0+" , when this happened?");
                this.print(_arg0);
                reply.writeNoException();
                return true;
            case TRANSACTION_add:
                data.enforceInterface(DESCRIPTOR);
                String _arg2;
                _arg2 = data.readString();
                String _arg3;
                _arg3= data.readString();
                String _result = this.add(_arg2, _arg3);
                reply.writeNoException();
                reply.writeString(_result);
                return true;
            }
            return super.onTransact(code, data, reply, flags);
        }
        static final int TRANSACTION_print = (IBinder.FIRST_CALL_TRANSACTION+0);
        static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION+1);
    }
    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("start myAidl Service------");
    }
}

上面我们首先看到了依然是Service onBind 并且mBinder 是new的带有两个接口函数对象,因此我们肯定MyPrinterInterfaceStub一定是继承自Binder

private MyPrinterInterfaceStub mBinder = new MyPrinterInterfaceStub() {

        @Override
        public void print(String msg) throws RemoteException {
            MyAIDLService.this.print(msg);
        }

        @Override
        public String add(String a, String b) throws RemoteException {
            return MyAIDLService.this.add(a,b);
        }
    };

然后我们再看MyPrinterInterfaceStub这个类的实现:

abstract class MyPrinterInterfaceStub extends Binder implements MyPrinterInterface{
    public MyPrinterInterfaceStub(){
                attachInterface(this, DESCRIPTOR);
    }
}

可以看到我们确实是实现了一个接口,这个类是一个抽象类,因此接口实现是在刚才我们看到的new出这个对象的时候实现的两个接口函数,并且我们还能看到我们在上一节讲到的为了关联远程连接服务器的client,我们通过DESCRIPTOR关联两者,因此我们的构造函数中调用了attachInterface(this, DESCRIPTOR); 为了能让client明确的指明需要调用服务器的那个接口函数,我们仍然去复写实现了一个这样的函数:

        //data表示客户端传送过来的值  code表示的是调用的函数,我们发现客户端调用的函数是:mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
        //这里和我们的这个函数传残一模一样  因此我们服务器的code和客户端的code是需要一一对应的
        @Override
        protected boolean onTransact(int code, Parcel data, Parcel reply,
                int flags) throws RemoteException {
            System.out.println("onTransact,code is "+code);
            switch(code)
            {
            case INTERFACE_TRANSACTION:
                System.out.println("MyPrinterInterfaceStub onTransact,code is "+code+" ,when this happens");
                reply.writeString(DESCRIPTOR);
                return true;
            case TRANSACTION_print:
                data.enforceInterface(DESCRIPTOR);
                String _arg0;
                _arg0 = data.readString();
                System.out.println("MyPrinterInterfaceStub ontransact, arg is "+_arg0+" , when this happened?");
                this.print(_arg0);
                reply.writeNoException();
                return true;
            case TRANSACTION_add:
                data.enforceInterface(DESCRIPTOR);
                String _arg2;
                _arg2 = data.readString();
                String _arg3;
                _arg3= data.readString();
                String _result = this.add(_arg2, _arg3);
                reply.writeNoException();
                reply.writeString(_result);
                return true;
            }
            return super.onTransact(code, data, reply, flags);
        }
        static final int TRANSACTION_print = (IBinder.FIRST_CALL_TRANSACTION+0);
        static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION+1);

同样的是由code去区分调用哪个函数,最后我们通过Service中的onBind方法返回一个Binder对象,这样,当client拿到我们服务器的Binder对象的时候就可以调用我们服务器提供出去的两个方法了!这里我们是不是感觉到了服务器的code,这样写总感觉有些蛋疼,虽然Eclipse给我们生成的Service端的函数貌似也是这样写的,先定义出了接口,然后让Binder子类继承接口,然后在new的时候实现接口,其实这样写貌似没什么必要(我们自己定义的没有不对外公开接口,因此没必要引入这个interface增加代码的封装性),我们完全可以直接的不要这个接口的定义与实现!

package com.qs.aidldemo;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;
import android.widget.Toast;
//自己实现的AIDL方法:
//技术博客参考:http://blog.csdn.net/hitlion2008/article/details/9824009
public class MyAIDLService extends Service {
    private Handler mHandler = new Handler();
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private MyPrinterInterfaceStub mBinder = new MyPrinterInterfaceStub(); 
    public void print(String msg)
    {
        try{
            System.out.println("Preparing printer...");  
            Thread.sleep(1000);  
            System.out.println("Connecting printer...");  
            Thread.sleep(1000);  
            System.out.println("Printing.... " + msg);  
            Thread.sleep(1000);  
            System.out.println( "Done");  
        }catch(Exception e)
        {

        }
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MyAIDLService.this, "MyService printing is done", 0).show();
            }
        });
    }
    //这个是服务器实现的add函数的功能
    public String add(String a,String b)
    {
        int sum =0;
        try{
            System.out.println("a="+a+" b="+b);
            sum = Integer.valueOf(a)+Integer.valueOf(b);
            System.out.println("Printing.... " + sum);  
        }catch(Exception e)
        {

        }
        return String.valueOf(sum);
    }


    //这个又是Binder的封装类  也就是我们私有的Binder类的实现
    class MyPrinterInterfaceStub extends Binder implements IInterface{
        private static final String DESCRIPTOR="MyPrinterInterface";
        private static final String TAG="MyPrinterInterfaceStub";

        public MyPrinterInterfaceStub(){
            attachInterface(this, DESCRIPTOR);
        }
        //这个函数似乎就没有被调用过
        @Override
        public IBinder asBinder() {
            System.out.println("Server asBinder");
            return this;
        }
        //data表示客户端传送过来的值  code表示的是调用的函数,我们发现客户端调用的函数是:mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
        //这里和我们的这个函数传残一模一样  因此我们服务器的code和客户端的code是需要一一对应的
        @Override
        protected boolean onTransact(int code, Parcel data, Parcel reply,
                int flags) throws RemoteException {
            System.out.println("onTransact,code is "+code);
            switch(code)
            {
            case INTERFACE_TRANSACTION:
                System.out.println("MyPrinterInterfaceStub onTransact,code is "+code+" ,when this happens");
                reply.writeString(DESCRIPTOR);
                return true;
            case TRANSACTION_print:
                data.enforceInterface(DESCRIPTOR);
                String _arg0;
                _arg0 = data.readString();
                System.out.println("MyPrinterInterfaceStub ontransact, arg is "+_arg0+" , when this happened?");
                print(_arg0);
                reply.writeNoException();
                return true;
            case TRANSACTION_add:
                data.enforceInterface(DESCRIPTOR);
                String _arg2;
                _arg2 = data.readString();
                String _arg3;
                _arg3= data.readString();
                String _result = add(_arg2, _arg3);
                reply.writeNoException();
                reply.writeString(_result);
                return true;
            }
            return super.onTransact(code, data, reply, flags);
        }
        static final int TRANSACTION_print = (IBinder.FIRST_CALL_TRANSACTION+0);
        static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION+1);
    }
    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("start myAidl Service------");
    }
}

这样我们就直接省略了interface的定义以及实现过程 。下面我们来看一下客户端的实现:

package com.qs.aidlclientdemo;

import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;

public interface MyPrinterInterface extends android.os.IInterface{
    //这两个是我们自己需要实现的函数,而asBinder函数是android.os.IInterface中需要实现的接口
    public void print(String msg) throws android.os.RemoteException;
    public String add(String a ,String b) throws android.os.RemoteException;

    //创建一个抽象类去封装我们的Binder
    public abstract class Stub extends Binder implements MyPrinterInterface
    {
        private static final String DESCRIPTOR="MyPrinterInterface";//这个描述符的定义必须与服务器的一致,不然无法得到想要的结果
        private static final String TAG="MyPrinterInterface.Stub";
        public Stub(){
            attachInterface(this, DESCRIPTOR);
        }

        public static MyPrinterInterface asInterface(IBinder obj)
        {
            if(obj==null)return null;
              System.out.println("we are talking to a remote one, we must use a proxy object to wrapper binder");  
                return new Stub.Proxy(obj);  //Proxy对象是MyPrinterInterface子类
        }
        static final int TRANSACTION_print =(IBinder.FIRST_CALL_TRANSACTION+0);
        static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION+1);

        //Stub 中的抽象的函数在这里面都一一实现了    
        //这里面会把我们客户端发送的数据传输给服务器,然后服务器会把结果回填到我们的reply  通过函数mRemote.transact(Stub.TRANSACTION_print, _data, _reply, 0);
        //同时我们发现我们创建的里面的IBinder对象就是当客户端脸上之后服务器返回给客户端的IBinder对象,因此我们里面的mRemote操作的是服务器的函数
        //我们client调用的函数其实都是通过发送数据到服务器,然后通过服务器的binder返回数据给我们完成一个进程间通讯交互
        private static class Proxy implements MyPrinterInterface
        {
            private IBinder mRemote;
            Proxy(IBinder remote)
            {
                mRemote = remote;
            }
            @Override
            public IBinder asBinder() {
                return mRemote;
            }

            @Override
            public void print(String msg) throws RemoteException {
                Parcel _data = Parcel.obtain();
                Parcel _reply =Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(msg);
                    mRemote.transact(Stub.TRANSACTION_print, _data, _reply, 0);//这里实际上是调用服务器的onTransact函数
                } catch (Exception e) {
                }finally{
                    _data.recycle();
                    _reply.recycle();
                }
            }
            @Override
            public String add(String a, String b) throws RemoteException {
                Parcel _data = Parcel.obtain();
                Parcel _reply =Parcel.obtain();
                String _result = null;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    //写入我们要传入的两个值
                    _data.writeString(a);
                    _data.writeString(b);
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    //这里特别注意,如果我们需要服务器的返回值,那么下面必须这样写
                    _reply.readException();//这个必须得带上不然没有值
                    _result = _reply.readString();//这个是服务器返回给我们的值
                    System.out.println("service client result ="+_result);
                } catch (Exception e) {
                }finally{
                    _data.recycle();
                    _reply.recycle();
                }
                return _result;//最后返回我们从服务器上面拿到的值
            }

        }
    }
}

首先是一个大的interface 提供client调用的两个接口,这个对应服务器提供出来的两个API

public interface MyPrinterInterface extends android.os.IInterface{
    //这两个是我们自己需要实现的函数,而asBinder函数是android.os.IInterface中需要实现的接口
    public void print(String msg) throws android.os.RemoteException;
    public String add(String a ,String b) throws android.os.RemoteException;

然后定义了一个Binder的抽象类实现这个接口并且里面有一个asInterface函数返回的是一个相当于服务器的代理
对象

private static class Proxy implements MyPrinterInterface
        {
            private IBinder mRemote;
            Proxy(IBinder remote)
            {
                mRemote = remote;
            }
            @Override
            public IBinder asBinder() {
                return mRemote;
            }

            @Override
            public void print(String msg) throws RemoteException {
                Parcel _data = Parcel.obtain();
                Parcel _reply =Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(msg);
                    mRemote.transact(Stub.TRANSACTION_print, _data, _reply, 0);//这里实际上是调用服务器的onTransact函数
                } catch (Exception e) {
                }finally{
                    _data.recycle();
                    _reply.recycle();
                }
            }
            @Override
            public String add(String a, String b) throws RemoteException {
                Parcel _data = Parcel.obtain();
                Parcel _reply =Parcel.obtain();
                String _result = null;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    //写入我们要传入的两个值
                    _data.writeString(a);
                    _data.writeString(b);
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    //这里特别注意,如果我们需要服务器的返回值,那么下面必须这样写
                    _reply.readException();//这个必须得带上不然没有值
                    _result = _reply.readString();//这个是服务器返回给我们的值
                    System.out.println("service client result ="+_result);
                } catch (Exception e) {
                }finally{
                    _data.recycle();
                    _reply.recycle();
                }
                return _result;//最后返回我们从服务器上面拿到的值
            }

        }

很明显看到代理类中我们实现了怎样通过服务器的binder对象来调用服务器的api去做相关操作:
private IBinder mRemote; 这个是我们调用

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            person = IPerson.Stub.asInterface(service);
        }

函数之后传进来的远程的binder对象,我们通过这个对象就可以直接调用服务器给我们提供的方法:

    mRemote.transact(Stub.TRANSACTION_print, _data, _reply, 0);//这里实际上是调用服务器的onTransact函数
    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

同理,里面想要调用什么的时候传入的第一个参数就是我们服务器端的switch中的code
也就是:

        static final int TRANSACTION_print =(IBinder.FIRST_CALL_TRANSACTION+0);
        static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION+1);

_data是client传入的数据,_reply是我们服务器处理的结果返回的
因此这个客户端中的code调用我们也做完了:
最后贴一下客户端中MainActivity调用的code:

package com.qs.aidlclientdemo;

import java.util.Date;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.widget.Toast;

import com.qs.aidl.IPerson;


public class MainActivity extends Activity {
    private IPerson person;
    private MyPrinterInterface myInterface;
    private ServiceConnection conn = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            person = IPerson.Stub.asInterface(service);
        }
    };

    private ServiceConnection myconn = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            System.out.println("myconn connected");
            myInterface = MyPrinterInterface.Stub.asInterface(service);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //首先要拉起服务器的service程序然后才能调用远程服务器提供的api
        Intent intent = new Intent("android.intent.action.AIDLService");
        String time = new Date().toLocaleString();
        intent.putExtra("time", time);//这里我们还可以给服务器发送数据,在服务器的onBind函数中它的参数接收这个数据
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
        doBindService();
    }

    public void greet(View v)
    {
        try {
            Toast.makeText(this,person.greet("qiusen "),0).show();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    public void add(View v)
    {
        try {
            Toast.makeText(this,person.add("1","2"),0).show();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    public  void printmsg(View v)
    {
        try {
            if(myInterface==null){
                System.out.println("myInterface is not success");
                return;
            }
            myInterface.print("this is a client msg");
            System.out.println("MyClient = "+myInterface.add("1", "4"));
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    } 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(conn!=null)
            unbindService(conn);
        if(myconn!=null)
            unbindService(myconn);
    }

    private void doBindService()
    {
        Intent intent = new Intent("com.qs.MyAIDLService");
        bindService(intent, myconn, Context.BIND_AUTO_CREATE);
    }
}

上面的code是系统实现和自定义实现的混合,code的demo:
代码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值